diff --git a/build/obj/kaleid/crtlib/.placeholder b/build/obj/kaleid/crtlib/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/build/obj/kaleid/crtlib/test/.paceholder b/build/obj/kaleid/crtlib/test/.paceholder new file mode 100644 index 0000000..e69de29 diff --git a/build/obj/kaleid/extras/.placeholder b/build/obj/kaleid/extras/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/kaleid/crtlib/arith.c b/kaleid/crtlib/arith.c new file mode 100644 index 0000000..68e2575 --- /dev/null +++ b/kaleid/crtlib/arith.c @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Arithmetical functions // +//----------------------------------------------------------------------------// + +// do not mask anything +#define _KALEID_UNMASKED +#include + +int _osk_abs(int x) +{ + return abs(x); +} + +long _osk_labs(long x) +{ + return labs(x); +} + +div_t _osk_div(int x, int y) +{ + return div(x, y); +} + +ldiv_t _osk_ldiv(long x, long y) +{ + return ldiv(x, y); +} + diff --git a/kaleid/crtlib/atoi.c b/kaleid/crtlib/atoi.c new file mode 100644 index 0000000..eaf42b6 --- /dev/null +++ b/kaleid/crtlib/atoi.c @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Conversion utilities - atoi family // +//----------------------------------------------------------------------------// + +#include + +// +// String to integer +// Do not change errno +// +#define _ATOI_IMPL(_Name, _Type, _Func) \ + _Type _Name(const char *str) { \ + __get_errno(old); \ + _Type ret = (_Type)_Func(str, NULL, 0); \ + __set_errno(old); \ + return ret; \ + } + + +// ISO C does not allow extra ‘;’ outside of a function +#if defined(_NEED_ATOI) +_ATOI_IMPL(atoi, int, strtol) +#elif defined(_NEED_ATOL) +_ATOI_IMPL(atol, long, strtol) +#elif defined(_NEED_ATOU) +_ATOI_IMPL(atou, uint, strtoul) +#elif defined(_NEED_ATOUL) +_ATOI_IMPL(atoul, ulong, strtoul) +#else +#error "What am I supposed to declare?" +#endif + diff --git a/kaleid/crtlib/itoa.c b/kaleid/crtlib/itoa.c new file mode 100644 index 0000000..b393a57 --- /dev/null +++ b/kaleid/crtlib/itoa.c @@ -0,0 +1,125 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Conversion utilities - itoa family // +//----------------------------------------------------------------------------// + +#include + +// +// Digits table for bases <=36 (unused) +// +#if 0 +static const char digits[] = + "0123456789abcdefghijklmnopqrstuvwxyz"; +#endif + +// +// Integer to string in any base between 2 and 36 (included) +// + +#if defined(_NEED_ITOA) + +#define _IL_MIN INT_MIN +#define _IL_MIN_STRING "-2147483648" +char *itoa(int i, char *str, int base) +{ + int rem; + +#elif defined(_NEED_LTOA) + +#define _IL_MIN LONG_MIN +#define _IL_MIN_STRING "-9223372036854775808" +char *ltoa(long i, char *str, int base) +{ + long rem; + +#elif defined(_NEED_UTOA) + +char *utoa(uint i, char *str, int base) +{ + uint rem; + +#elif defined(_NEED_ULTOA) + +char *ultoa(ulong i, char *str, int base) +{ + ulong rem; + +#else +#error "What am I supposed to declare?" +#endif + char *orig = str; + +#if defined(_NEED_ITOA) || defined(_NEED_LTOA) + // + // Deal with negatives + // + int neg = 0; + if (i < 0 && base == 10) { + // + // Handle INT_MIN and LONG_MIN... + // + if (__builtin_expect(i == _IL_MIN, 0)) { + strcpy(orig, _IL_MIN_STRING); + goto leave; + } + + else { + neg = 1; + i = -i; + } + } +#endif + + // + // Only handle base 2 -> 36 + // + if (base < 2 || base > 36) { + __set_errno(EINVAL); + *orig = '\0'; + goto leave; + } + + // + // Deal with zero separately + // + if (i == 0) { + *str++ = '0'; + *str = '\0'; + goto leave; + } + + // + // Compute digits... in reverse order + // + while (i > 0) { + rem = i % base; + *str++ = (rem > 9) + ? (rem - 10) + 'a' + : rem + '0'; + i /= base; + } + +#if defined(_NEED_ITOA) || defined(_NEED_LTOA) + if (neg) *str++ = '-'; +#endif + + *str = '\0'; + + // + // Reverse the string + // + orig = strrev2(orig); + + // + // End of conversion + // +leave: + return orig; +} + + diff --git a/kaleid/crtlib/memory.c b/kaleid/crtlib/memory.c new file mode 100644 index 0000000..925ae9f --- /dev/null +++ b/kaleid/crtlib/memory.c @@ -0,0 +1,245 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: mem*() functions // +//----------------------------------------------------------------------------// + +#include + +//------------------------------------------// +// memset() family // +//------------------------------------------// + +// +// Set "bytes"-many bytes starting from ptr to val +// +void *memset(void *ptr, int val, size_t bytes) +{ + uchar *uptr = (uchar *)ptr; + + // + // Deal with bytes before start of the first aligned qword + // + while (((ulong)uptr % QWORD_ALIGN) > 0 && bytes--) { + *uptr++ = (uchar)val; + } + + // + // At this point we're qword-aligned + // + if (bytes > QWORD_SIZE) { + const ulong uval = ((ulong)val << 56) | ((ulong)val << 48) + | ((ulong)val << 40) | ((ulong)val << 32) + | ((ulong)val << 24) | ((ulong)val << 16) + | ((ulong)val << 8) | ((ulong)val); + + ulong *uqptr = (ulong *)ptr; + + // + // Moving fast, qword by qword + // + while (bytes > QWORD_SIZE) { + *uqptr++ = uval; + bytes -= QWORD_SIZE; + } + + uptr = (uchar *)(ulong)uqptr; + } + + // + // Deal with the few remaining bytes + // + while (bytes--) *uptr++ = (uchar)val; + + return ptr; +} + +// +// Set "words"-many words starting from ptr to val +// +void *memsetw(void *ptr, int val, size_t words) +{ + ushort *uptr = (ushort *)ptr; + + // + // Check whether we can we do this an aligned way + // + if unlikely (((ulong)uptr % WORD_ALIGN) > 0) { + // + // We can't, so we write word by word all the way up + // + while (words--) *uptr++ = (ushort)val; + return uptr; + } + + while (((ulong)uptr % QWORD_ALIGN) > 0 && words--) { + *uptr++ = (ushort)val; + } + + if (words > QWORDS_TO_WORDS(1)) { + const ulong uval = ((ulong)val << 48) | ((ulong)val << 32) + | ((ulong)val << 16) | ((ulong)val); + + ulong *uqptr = (ulong *)uptr; + + while (words > QWORDS_TO_WORDS(1)) { + words -= QWORDS_TO_WORDS(1); + *uqptr++ = uval; + } + + uptr = (ushort *)(ulong)uqptr; + } + + while (words--) *uptr++ = (ushort)val; + + return ptr; +} + +// +// Set "dwords"-many dwords starting from ptr to val +// XXX unimplemented +// +void *memsetd(void *ptr, int val, size_t dwords) +{ + (void)val; + (void)dwords; + + return ptr; +} + +// +// Set "qwords"-many qwords starting from ptr to val +// +void *memsetq(void *ptr, long val, size_t qwords) +{ + ulong *uptr = (ulong *)ptr; + + // + // There's no need to check for alignment + // + while (qwords--) *uptr++ = (ulong)val; + + return ptr; +} + +//------------------------------------------// +// Other mem*() functions // +//------------------------------------------// + +// +// Set "bytes"-many bytes starting from ptr to 0 +// +void *memzero(void *ptr, size_t bytes) +{ + return memsetb(ptr, 0, bytes); +} + +// +// Copy "bytes"-many bytes of src to dst +// Does not deal with overlapping blocks (memmove's job) +// +void *memcpy(void *restrict dst, const void *restrict src, size_t bytes) +{ + const ulong *usrc = (const ulong *)src; + ulong *udst = (ulong *)dst; + + if unlikely (bytes == 0) return dst; + + // + // Can align both src and dst at once at once? + // + if unlikely ((ulong)src % WORD_ALIGN == 1 + && (ulong)dst % WORD_ALIGN == 1) { + const uchar *ubsrc = (const uchar *)usrc; + uchar *ubdst = (uchar *)udst; + + // + // Yes we can, we're guaranteed to be word-aligned now + // + *ubdst++ = *ubsrc++; + bytes--; + + udst = (ulong *)ubdst; + usrc = (ulong *)ubsrc; + } + + const ushort *uwsrc = (const ushort *)usrc; + ushort *uwdst = (ushort *)udst; + + // + // Align either dst or src for qword access + // + while ((ulong)dst % QWORD_ALIGN > 0 + && (ulong)src % QWORD_ALIGN > 0 + && bytes > WORD_SIZE) { + + *uwdst++ = *uwsrc++; + bytes -= WORD_SIZE; + } + + udst = (ulong *)uwdst; + usrc = (ulong *)uwsrc; + + // + // This should be most of the job + // + while (bytes > QWORD_SIZE) { + *udst++ = *usrc++; + bytes -= QWORD_SIZE; + } + + const uchar *ubsrc = (const uchar *)usrc; + ushort *ubdst = (ushort *)udst; + + // + // Deal with the few bytes left + // + while (bytes--) *ubdst ++ = *ubsrc++; + + return dst; +} + +// +// Move memory from src to dest, even if they overlap +// +void *memmove(void *dst, const void *src, size_t bytes) +{ + const uchar *usrc = src; + uchar *udst = dst; + + // + // Can we use memcpy() safely? + // + if (udst < usrc) { + return memcpy(dst, src, bytes); + } + + // + // No, so we go backwards + // + uchar *usrc_end = (uchar *)usrc + bytes - 1; + uchar *udst_end = udst + bytes - 1; + while (bytes--) *udst_end-- = *usrc_end--; + + return dst; +} + +// +// Compare memory areas +// +int memcmp(const void *ptr1, const void *ptr2, size_t bytes) +{ + const uchar *uptr1 = ptr1; + const uchar *uptr2 = ptr2; + + while (bytes--) { + if (*uptr1++ != *uptr2++) { + return uptr1[-1] < uptr2[-1] ? -1 : 1; + } + } + + return 0; +} diff --git a/kaleid/crtlib/rand.c b/kaleid/crtlib/rand.c new file mode 100644 index 0000000..186311f --- /dev/null +++ b/kaleid/crtlib/rand.c @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: RNG related functions // +//----------------------------------------------------------------------------// + +#include + +// +// Seed value +// +static ulong next = 7756; + +// +// Returns a pseudo-random integer +// To be improved +// +int rand(void) +{ + next = next * 1103515245 + 12347; + return (uint)(next / 65536); +} + +// +// (Re)Set the random seed +// +void srand(uint seed) +{ + next = (ulong)seed; +} + diff --git a/kaleid/crtlib/sprintf.c b/kaleid/crtlib/sprintf.c new file mode 100644 index 0000000..f0f6b15 --- /dev/null +++ b/kaleid/crtlib/sprintf.c @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: sprintf()-related functions // +//----------------------------------------------------------------------------// + +#include + +// +// Format str according to fmt using ellipsed arguments +// +// BE CAREFUL when using this +// you need to know for sure an overflow won't happen +// +int sprintf(char *str, const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap); + ret = vsnprintf(str, SIZE_T_MAX, fmt, ap); + va_end(ap); + + return ret; +} + +int vsprintf(char *str, const char *fmt, va_list ap) +{ + return vsnprintf(str, SIZE_T_MAX, fmt, ap); +} + +// +// (v)sprintf() but with a size limit: no more than n bytes are written in str +// Always null-terminate str +// +int snprintf(char *str, size_t n, const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap); + ret = vsnprintf(str, n, fmt, ap) + va_end(ap); + + return ret; +} + +int vsnprintf(char *str, size_t n, const char *fmt, va_list ap) +{ + int ret = 0; + + // + // Go throught the format string + // + while (*fmt) { + if (*fmt != '%') { + // + // Even if we don't have any more room we still increase ret + // + if (ret++ < n) { + *str++ = *fmt++; + } + continue; + } + + switch (*fmt) { + case 'd': + default: + break; + } + } + + return ret; +} + + diff --git a/kaleid/crtlib/status.c b/kaleid/crtlib/status.c new file mode 100644 index 0000000..6fc3c38 --- /dev/null +++ b/kaleid/crtlib/status.c @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Implementation of describe_status() // +//----------------------------------------------------------------------------// + +#include + +error_t __errno = 0; + +/* +static const char *descriptions[] = { + [-SUCCESS] = "Success", + [-FAILED] = "Failed (no precision)", + [-NOT_PERMITTED] = "Operation not permitted", + [-ACCESS_DENIED] = "Access denied", + + [-BAD_ARGUMENT] = "Bad argument", + [-BAD_ARG_RANGE] = "Bad argument (not in range)", + [-BAD_ARG_NULL] = "Bad argument (null pointer)", +}; + +const char *describe_status(status_t status) +{ + (void)descriptions; + (void)status; + + // XXX + return ""; +} +*/ diff --git a/kaleid/crtlib/string.c b/kaleid/crtlib/string.c new file mode 100644 index 0000000..895d031 --- /dev/null +++ b/kaleid/crtlib/string.c @@ -0,0 +1,330 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: String-related functions // +//----------------------------------------------------------------------------// + +#include + +// +// Compare two strings +// +int strcmp(const char *str1, const char *str2) +{ + while (*str1 == *str2 && *str2) str1++, str2++; + + return *(uchar *)str1 - *(uchar *)str2; +} + +// +// Compare at most n bytes of two strings +// +int strncmp(const char *str1, const char *str2, size_t n) +{ + size_t it = 0; + + while (*str1 == *str2 && *str2 && it < n) str1++, str2++, it++; + + return *(uchar *)str1 - *(uchar *)str2; +} + +// +// Return str's length +// +size_t strlen(const char *str) +{ + const char *base = str; + + while (*str) str++; + + return str - base; +} + +// +// Return a pointer to the first occurence of ch in str, +// or str's null-terminator if none is found +// +char *strchrnul(const char *str, int ch) +{ + while ((*str && *str != (char)ch)) str++; + + return (char *)str; +} + +// +// Return a pointer to the first occurence of ch in str, +// NULL if none is found +// +char *strchr(const char *str, int ch) +{ + while ((*str && *str != (char)ch)) str++; + + return *str ? (char *)str : NULL; +} + +// +// Return a point to the last occurence of ch in str, +// NULL if none is found +// +char *strrchr(const char *str, int ch) +{ + char *ptr = NULL; + + while (*str) { + if (*str == ch) { + ptr = (char *)str; + } + str++; + } + + return ptr; +} + +// +// Return the length of the longest inital segment of str +// that only contains characters in acc +// +size_t strspn(const char *str, const char *acc) +{ + const char *ptr = str; + + while (*ptr && strchr(acc, *ptr) != NULL) ptr++; + + return ptr - str; +} + +// +// Return the length of the longest initial segment of str +// that does not contain any character in rej +// +size_t strcspn(const char *str, const char *rej) +{ + const char *ptr = str; + + while (*ptr && strchr(rej, *ptr) == NULL) ptr++; + + return ptr - str; +} + +// +// Return the first occurence in str of any byte in acc +// +char *strpbrk(const char *str, const char *acc) +{ + str += strcspn(str, acc); + + return *str ? (char *)str : NULL; +} + +// +// Return the first occurence of the substring needle +// in the string haystack, NULL if none is found +// Null-terminators aren't compared +// +char *strstr(const char *haystack, const char *needle) +{ + const size_t needle_size = strlen(needle); + + // + // Moves haystack to first occurence of the needle's first byte + // + while ((haystack = strchr(haystack, *needle)) != NULL) { + if (strncmp(haystack, needle, needle_size) == 0) { + return (char *)haystack; + } + } + + return NULL; +} + +// +// Tokenize a string, using saveptr as a savestate +// We let a segmentation fault happen if *saveptr == NULL +// +char *strtok_r(char *restrict str, const char *restrict delim, char **restrict saveptr) +{ + assert(*saveptr != NULL); + + if (str == NULL) str = *saveptr; + + // + // Skip initial segments composed only of delimiters + // + str += strspn(str, delim); + + // + // If str is empty, store it in saveptr so that next call + // still finds an empty strings and returns NULL + // + if (*str == 0) { + *saveptr = str; + return NULL; + } + + char *ptr = str, *tok_end = strpbrk(str, delim); + + // + // If we found the last token, set *saveptr to a str's null-terminator + // Otherwise, null-terminate token and save next byte + // + + if (tok_end == NULL) { + while (*ptr) ptr++; + *saveptr = ptr; + } + + else { + *tok_end = 0; + *saveptr = tok_end + 1; + } + + return str; +} + +// +// Tokenize a string in a very thread-unsafe way +// +char *strtok(char *restrict str, const char *restrict delim) +{ + static char *saveptr = NULL; + + KalAssert(FALSE); + + if (str) saveptr = str; + + return strtok_r(str, delim, &saveptr); +} + +// +// Copy the string src into dest +// +char *strcpy(char *restrict dest, const char *restrict src) +{ + char *base = dest; + + while ((*dest++ = *src++)); + + return base; +} + +// +// strcpy() but always writes n bytes +// Will not null-terminate for strings longer than n bytes +// +char *strncpy(char *restrict dest, const char *restrict src, size_t n) +{ + size_t it; + + for (it = 0; it < n && src[it]; it++) { + dest[it] = src[it]; + } + + while (it < n) dest[it++] = 0; + + return dest; +} + +// +// Copies at most n-1 bytes from src to dest +// Always null-terminates dest, but doesn't fill +// dest's contents past the null-terminator +// +// Returns the number of bytes written +// +size_t strnzcpy(char *restrict dest, const char *restrict src, size_t n) +{ + size_t it; + + for (it = 0; it < n - 1 && src[it]; it++) { + dest[it] = src[it]; + } + + dest[it++] = 0; + + return it; +} + +// +// Appends a copy of src at the end of dest +// +char *strcat(char *restrict dest, const char *restrict src) +{ + char *base = dest; + while (*dest) dest++; + while ((*dest++ = *src++)); + return base; +} + +// +// Appends a copy of at most n bytes of src at the end of dest +// +char *strncat(char *restrict dest, const char *restrict src, size_t n) +{ + size_t it, off = 0; + + while (dest[off]) off++; + + for (it = 0; it < n && src[it]; it++) { + dest[it+off] = src[it]; + } + + while (it++ < n) dest[it+off] = 0; + + return dest; +} + +// +// Appends a copy of at most n bytes of src at the end of dest +// Always null-terminates, and returne TRUE or FALSE depending on whether +// regular strcat() would have null-terminated this string, or not +// +size_t strnzcat(char *restrict dest, const char *restrict src, size_t n) +{ + size_t it, off = 0; + + while (dest[off]) off++; + + for (it = 0; it < n - 1 && src[it]; it++) { + dest[it+off] = src[it]; + } + + dest[it+off] = 0; + + return it+1; +} + +// +// Reverses the string src, putting the result into dest +// +char *strrev(char *restrict dest, const char *restrict src) +{ + char *orig = dest; + size_t n = strlen(src); + + dest[n--] = '\0'; + + while ((*dest++ = src[n--])); + + return orig; +} + +// +// Reverses a string, modifying it +// +char *strrev2(char *str) +{ + char ch, *orig = str; + size_t n = strlen(str); + char *temp = str + n - 1; + + while (temp > str) { + ch = *temp; + *temp-- = *str; + *str++ = ch; + } + + return orig; +} diff --git a/kaleid/crtlib/strtol.c b/kaleid/crtlib/strtol.c new file mode 100644 index 0000000..87a132f --- /dev/null +++ b/kaleid/crtlib/strtol.c @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: strto(u)l functions // +//----------------------------------------------------------------------------// + +#include + +long strtol(const char *str, char **endp, int base) { + (void)str; + (void)endp; + (void)base; + __set_errno(ENOSYS); + return 0; +} + +ulong strtoul(const char *str, char **endp, int base) { + (void)str; + (void)endp; + (void)base; + __set_errno(ENOSYS); + return 0; +} + diff --git a/kaleid/extras/argv.c b/kaleid/extras/argv.c new file mode 100644 index 0000000..e4e2a49 --- /dev/null +++ b/kaleid/extras/argv.c @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Command line parsing utilities // +//----------------------------------------------------------------------------// + +#include +#include +#include +#if 0 +error_t KalCmdLineToArgV(const char *cmdLine, + int argcMax, + int *argcPtr, + const char **argv); + +error_t KalArgVToCmdLine(const char *cmdLine, + size_t lengthMax, + int argc, + const char **argv); +#endif diff --git a/kaleid/extras/prog.c b/kaleid/extras/prog.c new file mode 100644 index 0000000..e3591d0 --- /dev/null +++ b/kaleid/extras/prog.c @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Program utilities // +//----------------------------------------------------------------------------// + +#include +#include + +#ifdef _KALEID_KERNEL + +const char *__progname = "kaleid-kernel"; +const char *__progvers = "alpha-0.0.1"; + +#else + +const char *__progname = "kaleid-test"; +const char *__progvers = "(n/a)"; + +#endif + +const char *KalGetProgName(void) +{ + return __progname; +} + +const char *KalGetProgVersion(void) +{ + return __progvers; +} + +bool KalSetProgVers(const char *vers) +{ + (void)vers; + __set_errno(ENOSYS); + return false; +} + +bool KalSetProgName(const char *name) +{ + (void)name; + __set_errno(ENOSYS); + return false; +} + diff --git a/kaleid/include/base/assert.h b/kaleid/include/base/assert.h new file mode 100644 index 0000000..e5d5608 --- /dev/null +++ b/kaleid/include/base/assert.h @@ -0,0 +1,117 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Kaleid assert() support // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_ASSERT_H +#define _KALBASE_ASSERT_H + +//------------------------------------------// +// Macros // +//------------------------------------------// + +#ifndef noreturn +#define noreturn __attribute__((__noreturn__)) +#endif + +#ifndef unlikely +#define unlikely(x) (__builtin_expect((x), 0)) +#endif + +#ifndef static_assert +#define static_assert _Static_assert +#endif + +//------------------------------------------// +// API compatibility checks // +//------------------------------------------// + +#define _SA_MSG "Incompatible type sizes" +static_assert(sizeof(char) == 1, _SA_MSG); +static_assert(sizeof(short) == 2, _SA_MSG); +static_assert(sizeof(int) == 4, _SA_MSG); +static_assert(sizeof(long) == 8, _SA_MSG); +static_assert(sizeof(void *) == 8, _SA_MSG); +#undef _SA_MSG + +//------------------------------------------// +// Assert core // +//------------------------------------------// + +// +// Failed assert handler +// +noreturn void __assert_handler(const char *, const char *, int, const char *); + +// +// Unconditional assert +// +#define KalAlwaysAssert(x) \ + do { \ + if unlikely (!(x)) \ + __assert_handler(#x, __FILE__, __LINE__, __func__); \ + } while (0) + +//------------------------------------------// +// When debugging // +//------------------------------------------// + +#if !defined(_NO_DEBUG) && !defined(NDEBUG) && !defined(KalAssert) + +// +// Check whether (x) holds, if not call __assert_handler +// +#define KalAssert KalAlwaysAssert + +#ifndef _OSK_SOURCE + +// +// When not building for OS/K, use the system's assert +// +#include + +#undef KalAwaysAssert +#define KalAlwaysAssert assert + +#endif + +//------------------------------------------// +// When not debugging // +//------------------------------------------// + +#else + +#ifndef NDEBUG +#define NDEBUG 1 +#endif + +#ifndef _NO_DEBUG +#define _NO_DEBUG 1 +#endif + +#ifndef KalAssert +#define KalAssert(x) ((void)0) +#endif + +#endif + +//------------------------------------------// +// Aliases and extensions // +//------------------------------------------// + +#ifndef assert +#define assert KalAssert +#endif + +#define KalAssertEx(x,m) KalAssert(x && m) +#define KalAlwaysAssertEx(x,m) KalAlwaysAssert(x && m) + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif diff --git a/kaleid/include/base/bdefs.h b/kaleid/include/base/bdefs.h new file mode 100644 index 0000000..1c1ef13 --- /dev/null +++ b/kaleid/include/base/bdefs.h @@ -0,0 +1,100 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Kaleid general preprocessor constants // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_BDEFS_H +#define _KALDEFS_BDEFS_H + +//------------------------------------------// +// Actual constants // +//------------------------------------------// + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef INITOK +#define INITOK ((unsigned int)0xCAFEBABE) +#endif + +//------------------------------------------// +// Keywords // +//------------------------------------------// + +#ifndef __alignof_is_defined +#define __alignof_is_defined +#define alignof _Alignof +#endif + +#ifndef __alignas_is_defined +#define __alignas_is_defined +#define alignas _Alignas +#endif + +#ifndef __bool_true_false_are_defined +#define __bool_true_false_are_defined +# define bool _Bool +# define true 1 +# define false 0 +# ifndef TRUE +# define TRUE 1 +# endif +# ifndef FALSE +# define FALSE 0 +# endif +#endif + +//------------------------------------------// +// Attributes and macros // +//------------------------------------------// + +#ifndef _PACKED +#define _PACKED __attribute__((__packed__)) +#endif + +#ifndef noreturn +#define noreturn __attribute__((__noreturn__)) +#endif + +#ifndef likely +#define likely(x) (__builtin_expect((x), 1)) +#endif + +#ifndef unlikely +#define unlikely(x) (__builtin_expect((x), 0)) +#endif + +#ifndef _STR +#define _STR(x) #x +#endif + +#ifndef _XSTR +#define _XSTR(x) _STR(x) +#endif + +//------------------------------------------// +// API specific macros // +//------------------------------------------// + +#ifndef KALAPI +# define KALAPI +#endif + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif diff --git a/kaleid/include/base/crtlib.h b/kaleid/include/base/crtlib.h new file mode 100644 index 0000000..e4e7767 --- /dev/null +++ b/kaleid/include/base/crtlib.h @@ -0,0 +1,242 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Kaleid C runtime library // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_CRTLIB_H +#define _KALBASE_CRTLIB_H + +//------------------------------------------// +// Typedefs // +//------------------------------------------// + +#ifndef __error_t_defined +#define __error_t_defined +typedef int error_t; +#endif + +#ifndef __size_t_defined +#define __size_t_defined +typedef unsigned long size_t; +#endif + +#ifndef __va_list_defined +#define __va_list_defined +typedef __builtin_va_list va_list; +#endif + +#ifndef __div_t_defined +#define __div_t_defined +typedef struct { int quot, rem; } div_t; +#endif + +#ifndef __ldiv_t_defined +#define __ldiv_t_defined +typedef struct { long quot, rem; } ldiv_t; +#endif + +//------------------------------------------// +// Global variables // +//------------------------------------------// + +#ifndef _KALEID_KERNEL + +extern error_t __errno; + +#ifndef errno +#define errno __errno +#endif + +#define __get_errno(x) error_t x = errno; +#define __set_errno(x) (errno = (x)) + +#else + +#define errno +#define __get_errno(x) +#define __set_errno(x) + +#endif + +//------------------------------------------// +// Macros // +//------------------------------------------// + +#ifndef _NO_MASK +#define _NO_MASK +#endif + +//------------------------------------------// +// va_list utilities // +//------------------------------------------// + +#ifndef va_start +#define va_start __builtin_va_start +#endif + +#ifndef va_arg +#define va_arg __builtin_va_arg +#endif + +#ifndef va_copy +#define va_copy __builtin_va_copy +#endif + +#ifndef va_end +#define va_end __builtin_va_end +#endif + +//------------------------------------------// +// Memory management utilities // +//------------------------------------------// + +#ifndef memsetb +#define memsetb memset +#endif + +#ifndef memchrb +#define memchrb memchr +#endif + +void *memset(void *, int, size_t); +void *memsetw(void *, int, size_t); +void *memsetd(void *, int, size_t); +void *memsetq(void *, long, size_t); + +void *memchr(const void *, int, size_t); +void *memchrw(const void *, int, size_t); +void *memchrd(const void *, int, size_t); +void *memchrq(const void *, long, size_t); + +void *memrchr(const void *, int, size_t); + +void *memcpy(void *restrict, const void *restrict, size_t); +void *memmove(void *, const void *, size_t); + +void *memzero(void *, size_t); +int memcmp(const void *, const void *, size_t); + +//------------------------------------------// +// String manipulation utilities // +//------------------------------------------// + +size_t strlen(const char *); +size_t strspn(const char *, const char *); +size_t strcspn(const char *, const char *); + +int strcmp(const char *, const char *); +int strncmp(const char *, const char *, size_t); + +char *strchr(const char *, int); +char *strrchr(const char *, int); +char *strchrnul(const char *, int); + +char *strstr(const char *, const char *); +char *strpbrk(const char *, const char *); + +char *strtok(char *restrict, const char *restrict); +char *strtok_r(char *restrict, const char *restrict, char **restrict); + +char *strcpy (char *restrict, const char *restrict); +char *strncpy (char *restrict, const char *restrict, size_t); +size_t strnzcpy(char *restrict, const char *restrict, size_t); + +char *strcat (char *restrict, const char *restrict); +char *strncat (char *restrict, const char *restrict, size_t); +size_t strnzcat(char *restrict, const char *restrict, size_t); + +char *strrev(char *restrict, const char *restrict); +char *strrev2(char *); + +int sprintf(char *, const char *, ...); +int snprintf(char *, size_t, const char *, ...); +int vsprintf(char *, const char *, va_list); +int vsnprintf(char *, size_t, const char *, va_list); + +//------------------------------------------// +// Type conversion utilities // +//------------------------------------------// + +char *itoa(int, char *, int); +char *ltoa(long, char *, int); +char *utoa(unsigned int, char *, int); +char *ultoa(unsigned long, char *, int); + +int atoi(const char *); +long atol(const char *); +unsigned int atou(const char *); +unsigned long atoul(const char *); + +long strtol (const char *restrict, char **restrict, int); +unsigned long strtoul(const char *restrict, char **restrict, int); + +//------------------------------------------// +// RNG utilities // +//------------------------------------------// + +int rand(void); +void srand(unsigned int); + +//------------------------------------------// +// Time utilities // +//------------------------------------------// + +//------------------------------------------// +// Diverse utilities // +//------------------------------------------// + +char *strerror(int); +char *strsignal(int); + +//------------------------------------------// +// Arithmetical macros // +//------------------------------------------// + +#ifndef __abs +#define __abs +static inline int abs(int __x) +{ + return __x < 0 ? -__x : __x; +} +#endif + +#ifndef __labs +#define __labs +static inline long labs(long __x) +{ + return __x < 0 ? -__x : __x; +} +#endif + +#ifndef __div +#define __div +static inline div_t div(int __x, int __y) +{ + div_t __res; + __res.quot = __x/__y; + __res.rem = __x%__y; + return __res; +} +#endif + +#ifndef __ldiv +#define __ldiv +static inline ldiv_t ldiv(long __x, long __y) +{ + ldiv_t __res; + __res.quot = __x/__y; + __res.rem = __x%__y; + return __res; +} +#endif + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif + diff --git a/kaleid/include/base/errno.h b/kaleid/include/base/errno.h new file mode 100644 index 0000000..c4476e3 --- /dev/null +++ b/kaleid/include/base/errno.h @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Values for errno_t and errno // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_ERRNO_H +#define _KALBASE_ERRNO_H + +//------------------------------------------// +// "errno" values // +//------------------------------------------// + +// Everything went fine +#define EOK 0 + +// Operation not permitted +#define EPERM 1 + +// No such file or directory +#define ENOENT 2 + +// No such process +#define ESRCH 3 + +// Syscall interrupted (e.g. by signal) +#define EINTR 4 + +// I/0 error +#define EIO 5 + +// No such device or address +#define ENXIO 6 + +// Argument list too long +#define E2BIG 7 + +// Not an executable format +#define ENOEXEC 8 + +// Bad file number +#define EBADF 9 + +// Invalid argument +#define EINVAL 22 + +// Functionality not implemented +#define ENOSYS 38 + +// Component crashed +#define ECRASH 500 + +// System is panicking +#define EPANIC 600 + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif diff --git a/kaleid/include/base/limits.h b/kaleid/include/base/limits.h new file mode 100644 index 0000000..affe0fa --- /dev/null +++ b/kaleid/include/base/limits.h @@ -0,0 +1,117 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Kaleid type limits definitions // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_LIMITS_H +#define _KALBASE_LIMITS_H + +//------------------------------------------// +// Data sizes blocks // +//------------------------------------------// + +#ifndef DATA_SIZE_BLOCK +#define DATA_SIZE_BLOCK +# define BYTE_SIZE sizeof(char) +# define WORD_SIZE sizeof(short) +# define DWORD_SIZE sizeof(int) +# define QWORD_SIZE sizeof(long) +#endif + +#ifndef DATA_ALIGN_BLOCK +#define DATA_ALIGN_BLOCK +# define BYTE_ALIGN alignof(char) +# define WORD_ALIGN alignof(short) +# define DWORD_ALIGN alignof(int) +# define QWORD_ALIGN alignof(long) +#endif + +#ifndef DATA_BITS_BLOCK +#define DATA_BITS_BLOCK +# define BYTE_BIT 8 +# define CHAR_BIT (BYTE_SIZE * BYTE_BIT) +# define WORD_BIT (WORD_SIZE * BYTE_BIT) +# define DWORD_BIT (DWORD_SIZE * BYTE_BIT) +# define QWORD_BIT (QWORD_SIZE * BYTE_BIT) +# define SHORT_BIT WORD_BIT +# define INT_BIT DWORD_BIT +# define LONG_BIT QWORD_BIT +#endif + +#ifndef DATA_SHIFTS_BLOCK +#define DATA_SHIFTS_BLOCK +# define BYTES_TO_WORDS(B) ((B) >> 1) +# define BYTES_TO_DWORDS(B) ((B) >> 2) +# define BYTES_TO_QWORDS(B) ((B) >> 3) +# define WORDS_TO_BYTES(W) ((W) << 1) +# define WORDS_TO_DWORDS(W) ((W) >> 1) +# define WORDS_TO_QWORDS(W) ((W) >> 2) +# define DWORDS_TO_BYTES(D) ((D) << 2) +# define DWORDS_TO_WORDS(D) ((D) << 1) +# define DWORDS_TO_QWORDS(D) ((D) >> 1) +# define QWORDS_TO_BYTES(Q) ((Q) << 3) +# define QWORDS_TO_WORDS(Q) ((Q) << 2) +# define QWORDS_TO_DWORDS(Q) ((Q) << 1) +#endif + +//------------------------------------------// +// Numeric data limits // +//------------------------------------------// + +#ifndef DATA_MAX_LIMITS_BLOCK +#define DATA_MAX_LIMITS_BLOCK +# define SCHAR_MAX ((signed char) 0x7F) +# define SHRT_MAX ((short) 0x7FFF) +# define INT_MAX ((int) 0x7FFFFFFF) +# define LONG_MAX ((long) 0x7FFFFFFFFFFFFFFF) +# define UCHAR_MAX ((unsigned char) 0xFF +# define USHRT_MAX ((unsigned short) 0xFFFF) +# define UINT_MAX ((unsigned int) 0xFFFFFFFF) +# define ULONG_MAX ((unsigned long) 0xFFFFFFFFFFFFFFFF) +#endif + +#ifndef DATA_MIN_LIMITS_BLOCK +#define DATA_MIN_LIMITS_BLOCK +# define SCHAR_MIN ((signed char) -SCHAR_MAX - 1) +# define SHRT_MIN ((short) -SHRT_MAX - 1) +# define INT_MIN ((int) -INT_MAX - 1) +# define LONG_MIN ((long) -LONG_MAX - 1L) +#endif + +#ifndef DATA_CHAR_LIMITS_BLOCK +#define DATA_CHAR_LIMITS_BLOCK +# ifdef __CHAR_UNSIGNED__ +# define CHAR_MIN ((char)0) +# define CHAR_MAX ((char)UCHAR_MAX) +# else +# define CHAR_MIN ((char)SCHAR_MIN) +# define CHAR_MAX ((char)SCHAR_MAX) +# endif +#endif + +#ifndef DATA_SPTYPES_LIMITS_BLOCK +#define DATA_SPTYPES_LIMITS_BLOCK +# define SSIZE_T_MIN LONG_MIN +# define SSIZE_T_MAX LONG_MAX +# define SIZE_T_MAX ULONG_MAX +#endif + +#ifdef NEED_MORE_USELESS_DATA +# define UCHAR_MIN ((unsigned char)0) +# define USHRT_MIN ((unsigned short)0) +# define UINT_MIN ((unsigned int)0) +# define ULONG_MIN ((unsigned long)0) +# ifdef STILL_NEED_MORE_USELESS_DATA +# error "Not enough useless data!" +# endif +#endif + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif diff --git a/kaleid/include/base/masks.h b/kaleid/include/base/masks.h new file mode 100644 index 0000000..60e861e --- /dev/null +++ b/kaleid/include/base/masks.h @@ -0,0 +1,119 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Masks for the functions in the KCRL // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_MASKS_H +#define _KALBASE_MASKS_H + +//------------------------------------------// + +#define div_t _osk_div_t +#define ldiv_t _osk_ldiv_t + +//------------------------------------------// + +#define memset _osk_memsetb +#define memchr _osk_memchrb + +#define memsetb _osk_memsetb +#define memsetw _osk_memsetw +#define memsetd _osk_memsetd +#define memsetq _osk_memsetq + +#define memchr _osk_memchrb +#define memchrw _osk_memchrw +#define memchrd _osk_memchrd +#define memchrq _osk_memchrq + +#define memcpy _osk_memcpy +#define memmove _osk_memmove + +#define memcmp _osk_memcmp +#define memzero _osk_memzero + +//------------------------------------------// + +#define strlen _osk_strlen +#define strspn _osk_strspn +#define strcspn _osk_strcspn + +#define strcmp _osk_strcmp +#define strncmp _osk_strncmp + +#define strchr _osk_strchr +#define strrchr _osk_strrchr + +#define strstr _osk_strstr +#define strpbrk _osk_strpbrk + +#define strtok _osk_strtok +#define strtok_r _osk_strtok_r + +#define strcpy _osk_strcpy +#define strncpy _osk_strncpy +#define strnzcpy _osk_strnzcpy + +#define strcat _osk_strcat +#define strncat _osk_strncat +#define strnzcat _osk_strnzcat + +#define strrev _osk_strrev +#define strrev2 _osk_strrev2 + +#define sprintf _osk_sprintf +#define snprintf _osk_snprintf +#define vsprintf _osk_vsprintf +#define vsnprintf _osk_vsnprintf + +//------------------------------------------// + + +#define itoa _osk_itoa +#define ltoa _osk_ltoa +#define utoa _osk_utoa +#define ultoa _osk_ultoa + +#define atoi _osk_atoi +#define atol _osk_atol +#define atou _osk_atou +#define atoul _osk_atoul + +#define strtol _osk_strtol +#define strtoul _osk_strtoul + +//------------------------------------------// + +#define rand _osk_rand +#define srand _osk_srand + +//------------------------------------------// + +#define abs _osk_abs +#define labs _osk_labs + +#define min _osk_min +#define lmin _osk_lmin + +#define max _osk_max +#define lmax _osk_lmax + +#define __div +#define __ldiv + +#define div _osk_div +#define ldiv _osk_ldiv + +//------------------------------------------// + +#define strerror _osk_strerror + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif diff --git a/kaleid/include/base/types.h b/kaleid/include/base/types.h new file mode 100644 index 0000000..115319a --- /dev/null +++ b/kaleid/include/base/types.h @@ -0,0 +1,120 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Kaleid C common types // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_TYPES_H +#define _KALBASE_TYPES_H + +//------------------------------------------// +// Basic integer types aliases // +//------------------------------------------// + +#ifndef __base_types_aliases +#define __base_types_aliases +typedef unsigned char uchar; +typedef signed char schar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef signed long long llong; +typedef unsigned long long ullong; +typedef long double ldouble; +#endif + +//------------------------------------------// +// Miscellaneous types // +//------------------------------------------// + +#ifndef __size_t_defined +#define __size_t_defined +typedef unsigned long size_t; +#endif + +#ifndef __ssize_t_defined +#define __ssize_t_defined +typedef signed long ssize_t; +#endif + +#ifndef __wchar_t_defined +#define __wchar_t_defined +typedef signed int wchar_t; +#endif + +#ifndef __off_t_defined +#define __off_t_defined +typedef unsigned long off_t; +#endif + +//------------------------------------------// +// Standard fixed-width integer types // +//------------------------------------------// + +#ifndef __ptrdiff_t_defined +#define __ptrdiff_t_defined +typedef signed long ptrdiff_t; +#endif + +#ifndef __intptr_t_defined +#define __intptr_t_defined +typedef signed long intptr_t; +#endif + +#ifndef __uintptr_t_defined +#define __uintptr_t_defined +typedef unsigned long uintptr_t; +#endif + +#ifndef __intmax_t_defined +#define __intmax_t_defined +typedef signed long intmax_t; +#endif + +#ifndef __uintmax_t_defined +#define __uintmax_t_defined +typedef unsigned long uintmax_t; +#endif + +//------------------------------------------// +// Special types // +//------------------------------------------// + +#ifndef __va_list_defined +#define __va_list_defined +typedef __builtin_va_list va_list; +#endif + +#ifndef __div_t_defined +#define __div_t_defined +typedef struct { int quot, rem; } div_t; +#endif + +#ifndef __ldiv_t_defined +#define __ldiv_t_defined +typedef struct { long quot, rem; } ldiv_t; +#endif + + +//------------------------------------------// +// Kaleid-specific types // +//------------------------------------------// + +#ifndef __error_t_defined +#define __error_t_defined +typedef int error_t; +#endif + +#ifndef __port_t_defined +#define __port_t_defined +typedef ushort port_t; +#endif + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif diff --git a/kaleid/include/extras/argv.h b/kaleid/include/extras/argv.h new file mode 100644 index 0000000..352c532 --- /dev/null +++ b/kaleid/include/extras/argv.h @@ -0,0 +1,126 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Command line parsing utilities // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_H +#include +#endif + +//------------------------------------------// +// Start of header // +//------------------------------------------// + +#ifndef _KALEXTRAS_ARGV_H +#define _KALEXTRAS_ARGV_H + +//------------------------------------------// +// Types // +//------------------------------------------// + +// +// Option types +// +typedef enum { + // + // A flag option, without any more parameters + // + CMDOPT_FLAG, + + // + // An option that expects a parameter + // + CMDOPT_PARAM, + +} CmdOptType_t; + +// +// An option for a command, e.g. "-o file" in "cc -o file" +// +typedef struct { + // + // The option's name, e.g. "help" for "--help" + // May be 0, but only if letter is not zero + // + const char *longName; + + // + // The option's letter, e.g. 'h' for '-h' + // + int letter; + + // + // The option's group, for sorting during --help + // Must be positive and < 256, or option won't shop up + // during help texts + // + int group; + + // + // The option's type, see above + // + CmdOptType_t type; + + // + // Address of the variable to put the parameter into + // Should be an int point for flag arguments, string + // pointer for parameter arguments + // + void *param; + + // + // The option's help text + // If this is 0, this option is hidden + // + const char *helpText; + +} CmdOption_t; + +//------------------------------------------// +// Functions // +//------------------------------------------// + +int KalComputeArgC(const char *argv[]); + +size_t KalComputeArgVSize(const char *argv[]); + +error_t KalCmdLineToArgV(const char *cmdLine, + int *argcPtr, + const char *argv[]); + +error_t KalArgVToCmdLine(const char *cmdLine, + size_t lengthMax, + int argc, + const char *argv[]); + +error_t KalParseCmdLine(const char *cmdLine, + CmdOption_t *options); + +error_t KalParseArgV(int argc, + const char *argv[], + CmdOption_t *options); + +// +// The "Ex" variants reacts to "--help" and "--version" by themselves +// + +error_t KalParseCmdLineEx(const char *cmdLine, + CmdOption_t *options, + const char *progDesc, + const char *groupDescs[]); + +error_t KalParseArgVEx(int argc, + const char *argv[], + CmdOption_t *options, + const char *progDesc, + const char *groupDescs[]); + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif diff --git a/kaleid/include/extras/list.h b/kaleid/include/extras/list.h new file mode 100644 index 0000000..d9f5bd6 --- /dev/null +++ b/kaleid/include/extras/list.h @@ -0,0 +1,273 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Doubly linked lists implementation // +//----------------------------------------------------------------------------// + +#ifdef _KALEID_KERNEL +#error "extra/list.h - Not ready for kernel compilation" +#endif + +#ifndef _KALBASE_H +#include +#endif + +//------------------------------------------// +// Start of header // +//------------------------------------------// + +#ifndef _KALEXTRAS_LIST_H +#define _KALEXTRAS_LIST_H + +// +// XXX ¯\_(ツ)_/¯ +// +#ifndef _STDLIB_H +void *malloc(long); +void free(void *); +#endif + +#define AllocMemory malloc +#define FreeMemory free + +//------------------------------------------// +// Data structures // +//------------------------------------------// + +typedef struct sListHead_t { + Lock_t *lock; + unsigned long length; + struct sListNode_t *first; + struct sListNode_t *last; +} ListHead_t; + +typedef struct sListNode_t { + void *data; + ListHead_t *head; + struct sListNode_t *prev; + struct sListNode_t *next; +} ListNode_t; + +//------------------------------------------// +// Functions // +//------------------------------------------// + +// +// Create a list head with an extern lock +// +static inline ListHead_t +*CreateListHeadWithLock(Lock_t *lock) +{ + ListHead_t *head = AllocMemory(sizeof(ListHead_t)); + + if (head == NULL) return NULL; + + head->first = head->last = NULL; + head->length = 0; + + head->lock = lock; + + return head; +} + +// +// Create a liste head +// +static inline ListHead_t +*CreateListHead(void) +{ + return CreateListHeadWithLock(NULL); +} + +// +// Create a node +// +static inline ListNode_t +*CreateNode(void *data) +{ + ListNode_t *node = AllocMemory(sizeof(ListNode_t)); + + if (node == NULL) return NULL; + + node->data = data; + node->head = NULL; + node->prev = node->next = NULL; + + return node; +} + +// +// Prepend node at beginning of list +// +static inline ListHead_t +*PrependNode(ListHead_t *head, ListNode_t *node) +{ + KalAssert(head && node); + + node->head = head; + node->prev = NULL; + + if (head->length > 0) { + node->next = head->first; + head->first->prev = node; + head->first = node; + } + + else { + head->first = node; + head->last = node; + node->next = NULL; + } + + head->length++; + + return head; +} + +// +// Append node at end of list +// +static inline ListHead_t +*AppendNode(ListHead_t *head, ListNode_t *node) +{ + KalAssert(head && node); + + node->head = head; + node->next = NULL; + + if (head->length > 0) { + node->prev = head->last; + head->last->next = node; + head->last = node; + } + + else { + head->first = node; + head->last = node; + node->prev = NULL; + } + + head->length++; + + return head; +} + +// +// Insert node2 before node1 +// +static inline ListHead_t +*AddNodeBefore(ListHead_t *head, ListNode_t *node1, ListNode_t *node2) +{ + KalAssert(head && node1 && node2 && node1->head == head); + + if (head->first == node1) { + return PrependNode(head, node2); + } + + node2->head = head; + node2->next = node1; + node2->prev = node1->prev; + + // node1->prev does exist + // or node1 would be first + node1->prev->next = node2; + node1->prev = node2; + + head->length++; + + return head; +} + +// +// Insert node2 after node1 +// +static inline ListHead_t +*AddNodeAfter(ListHead_t *head, ListNode_t *node1, ListNode_t *node2) +{ + KalAssert(head && node1 && node2 && node1->head == head); + + if (head->last == node1) { + return AppendNode(head, node2); + } + + node2->head = head; + node2->prev = node1; + node2->next = node1->next; + + node1->next->prev = node2; + node1->next = node2; + + head->length++; + + return head; +} + +// +// Remove node of list (and frees it) +// +static inline ListHead_t +*RemoveNode(ListHead_t *head, ListNode_t *node) +{ + KalAssert(head && node && head->length > 0 && node->head == head); + + if (head->length == 1) { + head->first = head->last = NULL; + goto leave; + } + + if (head->first == node) { + head->first = node->next; + node->next->prev = NULL; + } + + else if (head->last == node) { + head->last = node->prev; + node->prev->next = NULL; + } + + else { + node->prev->next = node->next; + node->next->prev = node->prev; + } + +leave: + head->length--; + FreeMemory(node); + + return head; +} + +// +// Free a node +// +static inline void +DestroyNode(ListNode_t *node) +{ + KalAssert(node); + FreeMemory(node); +} + +// +// Free a list head +// +static inline void +DestroyListHead(ListHead_t *head) +{ + KalAssert(head); + FreeMemory(head); +} + +// +// Access a node's data +// +#define GetNodeData(node, type) ((type)(node)->data) + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif + diff --git a/kaleid/include/extras/locks.h b/kaleid/include/extras/locks.h new file mode 100644 index 0000000..4ca5220 --- /dev/null +++ b/kaleid/include/extras/locks.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Spinlocks and mutexes // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_H +#include +#endif + +#ifdef _KALEID_KERNEL +#ifndef _KALKERN_BASE_H +#include +#endif +#endif + +//------------------------------------------// +// Start of header // +//------------------------------------------// + +#ifndef _KALEXTRAS_LOCKS_H +#define _KALEXTRAS_LOCKS_H + +//------------------------------------------// +// Types // +//------------------------------------------// + +typedef enum eLockType_t { + // + // Mutex-type lock + // + // WARNING + // AquireLock() panics when used on a mutex while not running a process + // + KLOCK_MUTEX, + + // + // Spinlock-type lock + // + KLOCK_SPINLOCK, + +} LockType_t; + +// +// "volatile" may not be actually needed +// +typedef struct sLock_t { + unsigned int initDone; // initialized? + int locked; // is locked? + LockType_t type; // lock type? +#ifdef _KALEID_KERNEL + Thread_t *ownerThread; // unused + Thread_t *waitingThread; // unused +#endif +} volatile Lock_t; + +//------------------------------------------// +// Functions // +//------------------------------------------// + +// +// Linux syscall vs unimplemented syscall... +// +#ifndef _KALEID_KERNEL +#ifdef _OSK_SOURCE +int KalYieldCPU(void), +#else +int sched_yield(void); +#endif +#endif + +// +// Initialize a lock +// +static inline +void InitLock(Lock_t *lock, LockType_t type) +{ + lock->type = type; + lock->locked = FALSE; + lock->initDone = INITOK; +#ifdef _KALEID_KERNEL + lock->ownerThread = NULL; + lock->waitingThread = NULL; +#endif +} + +// +// Alternative way to initalize a lock +// +#ifdef _KALEID_KERNEL +# define INITLOCK(type) { INITOK, FALSE, (type), NULL, NULL } +#else +# define INITLOCK(type) { INITOK, FALSE, (type) } +#endif + +// +// Destroy a lock +// +static inline +void DestroyLock(Lock_t *lock) +{ + KalAssert(lock->initDone); + + __sync_synchronize(); + lock->initDone = 0; +} + +// +// Aquire the lock +// Panic on double aquisition since that should never happen +// until we have at least a basic scheduler +// +static inline +void AquireLock(Lock_t *lock) +{ + KalAssert(lock->initDone == INITOK); + + while (!__sync_bool_compare_and_swap(&lock->locked, 0, 1)) { +#ifdef _KALEID_KERNEL + StartPanic("AquireLock on an already locked object"); +#else + if likely (lock->type == KLOCK_SPINLOCK) continue; +#ifdef _OSK_SOURCE + else KalYieldCPU(); +#else + else sched_yield(); +#endif +#endif + } + __sync_synchronize(); +} + +// +// Release an already aquired lock +// Panic if the lock was never aquired +// +static inline +void ReleaseLock(Lock_t *lock) +{ +#ifdef _KALEID_KERNEL + KalAssert(lock->ownerThread == GetCurThread()); +#endif + + __sync_synchronize(); + lock->locked = 0; +} + +// +// Tries to aquire lock +// +static inline +bool AttemptLock(Lock_t *lock) +{ + KalAssert(lock->initDone == INITOK); + + bool retval = __sync_bool_compare_and_swap(&lock->locked, 0, 1); + + __sync_synchronize(); + + return retval; +} + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif diff --git a/kaleid/include/extras/prog.h b/kaleid/include/extras/prog.h new file mode 100644 index 0000000..bae5b1a --- /dev/null +++ b/kaleid/include/extras/prog.h @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Program utilities // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_H +#include +#endif + +//------------------------------------------// +// Start of header // +//------------------------------------------// + +#ifndef _KALEXTRAS_PROG_H +#define _KALEXTRAS_PROG_H + +//------------------------------------------// +// Constants // +//------------------------------------------// + +extern const char *__progname; +extern const char *__progvers; + +//------------------------------------------// +// Functions // +//------------------------------------------// + +const char *KalGetProgName(void); +const char *KalGetProgVersion(void); + +bool KalSetProgVers(const char *); +bool KalSetProgName(const char *); + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif diff --git a/kaleid/include/kalbase.h b/kaleid/include/kalbase.h new file mode 100644 index 0000000..618061a --- /dev/null +++ b/kaleid/include/kalbase.h @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Kaleid API base minimal include file // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_H +#define _KALBASE_H + +//------------------------------------------// +// Building for OS/K // +//------------------------------------------// + +#if !defined(_OSK_SOURCE) +# if defined(_KALEID_KERNEL) || defined(_KALEID_SYSTEM) +# define _OSK_SOURCE 1 +# endif +#endif + +#if !defined(_OSK_SOURCE) && !defined(_KALEID_UNMASKED) +#ifndef _KALBASE_MASKS_H +#include +#endif +#endif + +//------------------------------------------// +// Include common part of API // +//------------------------------------------// + +#ifndef _KALBASE_BDEFS_H +#include +#endif + +#ifndef _KALBASE_ERRNO_H +#include +#endif + +#ifndef _KALBASE_TYPES_H +#include +#endif + +#ifndef _KALBASE_LIMITS_H +#include +#endif + +#ifndef _KALBASE_ASSERT_H +#include +#endif + +#ifndef _KALBASE_CRTLIB_H +#include +#endif + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif diff --git a/kaleid/include/kalext.h b/kaleid/include/kalext.h new file mode 100644 index 0000000..5dcc19f --- /dev/null +++ b/kaleid/include/kalext.h @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Kaleid extras main include file // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_H +#include +#endif + +//------------------------------------------// +// Start of header // +//------------------------------------------// + +#ifndef _KALEXT_H +#define _KALEXT_H + +//------------------------------------------// +// Extra headers // +//------------------------------------------// + +#ifndef _KALEXTRAS_LOCKS_H +#include +#endif + +#ifndef _KALEXTRAS_PROG_H +#include +#endif + +#ifndef _KALEXTRAS_ARGV_H +#include +#endif + +#ifndef _KALEID_KERNEL +#ifndef _KALEXTRAS_LIST_H +#include +#endif +#endif + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif + diff --git a/kaleid/include/kernel/base.h b/kaleid/include/kernel/base.h new file mode 100644 index 0000000..6ac5134 --- /dev/null +++ b/kaleid/include/kernel/base.h @@ -0,0 +1,199 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Kaleid Kernel base types and functionalities // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_H +#include +#endif + +//------------------------------------------// +// Start of header // +//------------------------------------------// + +#ifndef _KALKERN_BASE_H +#define _KALKERN_BASE_H + +//------------------------------------------// +// Elementary types // +//------------------------------------------// + +typedef struct sLock_t volatile Lock_t; +typedef struct sThread_t Thread_t; +typedef struct sProcess_t Process_t; +typedef struct sTerminal_t Terminal_t; +typedef struct sListHead_t ListHead_t; +typedef struct sListNode_t ListNode_t; + +//------------------------------------------// +// Values for __kstate // +//------------------------------------------// + +// +// Current state of the kernel +// +typedef enum { + // the kernel is booting + KSTATE_INIT, + + // the kernel is not running a process + KSTATE_KERNEL, + + // a process is running in kernel mode + KSTATE_PROCESS, + + // the kernel is panicking + KSTATE_PANIC, + +} KernelState_t; + +//------------------------------------------// +// Multiprocessor misc. // +//------------------------------------------// + +#ifndef INITOK +#define INITOK ((unsigned int)0xCAFEBABE) +#endif + +#ifndef NCPUS +#define NCPUS 4 +#endif + +#define GetCurCPU() 0 + +// +// Declare an (extern) CPU-local variable +// +#define __DECLARE_PER_CPU(_X, _Tp, _Qual) \ + _Qual _Tp __ ## _X [NCPUS]; \ + static inline _Tp Get ## _X (void) \ + { return __ ## _X [GetCurCPU()]; } \ + static inline void _Set ## _X (_Tp _Y) \ + { (__ ## _X [GetCurCPU()] = _Y); } + +#define DECLARE_PER_CPU(_X, _Tp) \ + __DECLARE_PER_CPU(_X, _Tp, extern) + +#define LOCAL_DEC_PER_CPU(_X, _Tp) \ + __DECLARE_PER_CPU(_X, _Tp, static) + +// +// Actually creates a CPU-local variable +// +#define CREATE_PER_CPU(_X, _Tp) \ + _Tp __ ## _X [NCPUS] = { (_Tp) 0 } + + +//------------------------------------------// +// Global constants // +//------------------------------------------// + +// XXX +DECLARE_PER_CPU(PanicStr, const char *); + +DECLARE_PER_CPU(KernState, KernelState_t); + +DECLARE_PER_CPU(_StdOut, Terminal_t *); +DECLARE_PER_CPU(_StdDbg, Terminal_t *); + +DECLARE_PER_CPU(CurProc, Process_t *); +DECLARE_PER_CPU(CurThread, Thread_t *); + +//------------------------------------------// +// Macros for manipulating said // +// global constants // +//------------------------------------------// + +#define SetKernState(x) \ + do { \ + _SetKernState(x); \ + } while (0) + +#define GetStdOut() (GetCurProc() == NULL ? Get_StdOut() : NULL) +#define SetStdOut(tm) \ + do { \ + if (GetCurProc() == NULL) \ + _Set_StdOut(tm); \ + } while (0); + +#define GetStdDbg() (GetCurProc() == NULL ? Get_StdDbg() : NULL) +#define SetStdDbg(tm) \ + do { \ + if (GetCurProc() == NULL) \ + _Set_StdDbg(tm); \ + } while (0) + +//------------------------------------------// +// Other Macros // +//------------------------------------------// + +// +// Size of a tabulation in spaces +// Default: 4 spaces/tab +// +#define KTABSIZE 4 + +// +// Disable IRQs +// +#define DisableIRQs() asm volatile ("cli") + +// +// Enable IRQs +// +#define EnableIRQs() asm volatile ("sti") + +// +// Pause CPU until next interuption +// !!! Enables IRQs !!! +// +#define PauseCPU() asm volatile("sti\n\thlt") + +// +// Halt the CPU indefinitely +// +#define HaltCPU() do { asm volatile ("hlt"); } while (1) + +//------------------------------------------// +// Some base functions // +//------------------------------------------// + +noreturn void StartPanic(const char *); +noreturn void CrashSystem(void); + +//------------------------------------------// +// Useful I/O inlines // +//------------------------------------------// + +static inline +void WriteByteOnPort(port_t port, port_t val) +{ + asm volatile ("out %0, %1" : : "dN" (port), "a" (val)); +} + +static inline +uchar ReadByteFromPort(port_t port) +{ + KalAssert(FALSE && ENOSYS); + (void)port; + return 0; +} + +static inline +ushort ReadWordFromPort(port_t port) +{ + KalAssert(FALSE && ENOSYS); + (void)port; + return 0; +} + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif + diff --git a/kaleid/include/kernel/sched.h b/kaleid/include/kernel/sched.h new file mode 100644 index 0000000..596e08f --- /dev/null +++ b/kaleid/include/kernel/sched.h @@ -0,0 +1,107 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Scheduler header // +//----------------------------------------------------------------------------// + +#ifndef _KALKERN_BASE_H +#include +#endif + +//------------------------------------------// +// Start of header // +//------------------------------------------// + +#ifndef _KALKERN_SCHED_H +#define _KALKERN_SCHED_H + +//------------------------------------------// +// Preprocessor // +//------------------------------------------// + +// +// Debug stuff +// +#define printdbg printf + +// +// States for a process +// +#define STATE_RUNNING 0 +#define STATE_RUNNABLE 1 +#define STATE_BLOCKED 2 + +// +// Time in ticks a process should be run +// +#define DEF_PROC_TSLICE 5 // 20 ticks +#define TCR_PROC_TSLICE 20000 // 20000 ticks (time critical) + +//------------------------------------------// +// List heads // +//------------------------------------------// + +DECLARE_PER_CPU(IdlePrioProcs, ListHead_t *); +DECLARE_PER_CPU(ReglPrioProcs, ListHead_t *); +DECLARE_PER_CPU(ServPrioProcs, ListHead_t *); +DECLARE_PER_CPU(TimeCritProcs, ListHead_t *); + +extern const char *PrioClassesNames[]; + +//------------------------------------------// +// Data types // +//------------------------------------------// + +// +// A process +// +typedef struct sProcess_t { + + // Identifier + int pid; + + // Current priority class + int prioClass; + + // Default priority class (without boosts) + int defPrioClass; + + // Current priority level + int prioLevel; + + // Default priority level + int defPrioLevel; + + // Current state + int procState; + + // Remaining time running + ulong timeSlice; + + // Default time-slice + ulong defTimeSlice; + + // Scheduler internals + ListNode_t *schedNode; + +} Process_t; + +//------------------------------------------// +// Functions // +//------------------------------------------// + +void SchedInit(void); +void SchedFini(void); + +void SchedThisProc(Process_t *); +void SchedOnTick(void); + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif + diff --git a/kaleid/include/kernel/terminal.h b/kaleid/include/kernel/terminal.h new file mode 100644 index 0000000..1cde180 --- /dev/null +++ b/kaleid/include/kernel/terminal.h @@ -0,0 +1,91 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Terminal functions // +//----------------------------------------------------------------------------// + +#ifndef _KALKERN_BASE_H +#include +#endif + +//------------------------------------------// +// Start of header // +//------------------------------------------// + +#ifndef _KALKERN_TERMINAL_H +#define _KALKERN_TERMINAL_H + +//------------------------------------------// +// Types // +//------------------------------------------// + +// +// The VGA colors +// +typedef enum { + KTERM_COLOR_BLACK, KTERM_COLOR_BLUE, + KTERM_COLOR_GREEN, KTERM_COLOR_CYAN, + KTERM_COLOR_RED, KTERM_COLOR_MAGENTA, + KTERM_COLOR_BROWN, KTERM_COLOR_LGREY, + KTERM_COLOR_DARK_GREY, KTERM_COLOR_LBLUE, + KTERM_COLOR_LGREEN, KTERM_COLOR_LCYAN, + KTERM_COLOR_LRED, KTERM_COLOR_LMAGENTA, + KTERM_COLOR_LBROWN, KTERM_COLOR_WHITE +} TermColor_t; + +// +// Terminal structure, right now VGA and output only +// +typedef struct sTerminal_t { + + uint initDone; + Lock_t lock; + + const char *name; + const char *type; + + void *data; + + size_t width; + size_t height; + off_t currentX; + off_t currentY; + + uint tabSize; + TermColor_t fgColor; + TermColor_t bgColor; + + error_t (*ClearTermUnlocked)(Terminal_t *); + error_t (*PutOnTermUnlocked)(Terminal_t *, char); + error_t (*PrintOnTermUnlocked)(Terminal_t *, const char *); + +} Terminal_t; + +//------------------------------------------// +// Functions // +//------------------------------------------// + +void InitTerms(void); +error_t ClearTerm(Terminal_t *); +error_t PutOnTerm(Terminal_t *, char); +error_t PrintOnTerm(Terminal_t *, const char *); +error_t ChTermColor(Terminal_t *, TermColor_t, TermColor_t); + +//------------------------------------------// +// Macros // +//------------------------------------------// + +#ifndef _NO_DEBUG +# define DebugLog(...) PrintOnTerm(GetStdDbg(), __VA_ARGS__) +#else +# define DebugLog(...) +#endif + +//------------------------------------------// +// End of header // +//------------------------------------------// + +#endif