diff --git a/Makefile.in b/Makefile.in index eadc905..8fa91e9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,3 +1,4 @@ +// -*- Mode: Makefile -*- //----------------------------------------------------------------------------// // GNU GPL OS/K // // // @@ -13,23 +14,23 @@ CCNAME="/opt/cross-cc/bin/x86_64-elf-gcc" CC2NAME=gcc COPTIM=-O2 -CWARNS=-Wall -Wextra -Wshadow // -Wpedantic -CINCLUDES=-isystem./kaleid/include +CWARNS=-Wall -Wextra // -Wshadow -Wpedantic +CINCLUDES=-Ikaleid/include -CFLAGS1=-std=gnu11 -nostdlib -ffreestanding -mcmodel=large -CFLAGS2=-m64 -masm=intel -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -CFLAGS=$(CFLAGS1) $(CFLAGS2) $(SFLAG) +CFLAGS1=-nostdlib -ffreestanding -mcmodel=large // -std=gnu11 +CFLAGS2=_ASMTYPE -mno-red-zone -mno-mmx -mno-sse -mno-sse2 +CFLAGS=$(CFLAGS1) $(CFLAGS2) CC=$(CCNAME) $(COPTIM) $(CWARNS) $(CFLAGS) $(CINCLUDES) -BINDIR=./build/bin -OBJDIR=./build/obj +BINDIR=build/bin +OBJDIR=build/obj BOOTDIR=boot COMMDIR=kaleid/crtlib KERNDIR=kaleid/kernel SYSTDIR=kaleid/system -LINXDIR=$(COMMDIR)/test +LINXDIR=kaleid/test //----------------------------------------------------------------------------# // TESTING MAKEFILE @@ -49,7 +50,7 @@ LOBJDIR=$(OBJDIR)/$(LINXDIR) COMMOBJS=COBJ6(string, status, rand, memory, arith, strtol) COBJ4(itoa, ltoa, utoa, ultoa) COBJ4(atoi, atol, atou, atoul) COBJ2(../extras/prog, ../extras/argv) TCC=$(CC2NAME) $(COPTIM) $(CWARNS) $(CINCLUDES) -KCC=$(CC) -T ./build/kernel.ld -D_OSK_SOURCE -D_KALEID_KERNEL +KCC=$(CC) -D_KALEID_KERNEL comm-convert: COMPILE_CONVRT1(itoa) -D_NEED_ITOA @@ -73,20 +74,22 @@ common: comm-convert tests: common $(TCC) -c $(LINXDIR)/test-common.c -o $(LOBJDIR)/test-common.o - $(TCC) $(COMMOBJS) $(LOBJDIR)/test-common.o -o $(BINDIR)/kaleid-common.elf + $(TCC) $(COMMOBJS) $(LOBJDIR)/test-common.o -o $(BINDIR)/comm-test //----------------------------------------------------------------------------# // KERNEL MAKEFILE KOBJDIR=$(OBJDIR)/$(KERNDIR) -KERNOBJS=KOBJ4(init/init, init/table, ke/panic, ke/terminal) +KERNOBJS=KOBJ6(init/init, init/table, ke/panic, io/term, io/cursor, io/vga) kernel: common COMPILE_KERNEL(init/init) COMPILE_KERNEL(init/table) COMPILE_KERNEL(ke/panic) - COMPILE_KERNEL(ke/terminal) + COMPILE_KERNEL(io/cursor) + COMPILE_KERNEL(io/term) + COMPILE_KERNEL(io/vga) LINK_KERNEL(kaleid-kernel.elf) //----------------------------------------------------------------------------# diff --git a/build/bin/comm-test b/build/bin/comm-test new file mode 100755 index 0000000..ea0cd8f Binary files /dev/null and b/build/bin/comm-test differ diff --git a/build/obj/kaleid/test/.placeholder b/build/obj/kaleid/test/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/build/preproc.h b/build/preproc.h index f690c6e..746bd2c 100644 --- a/build/preproc.h +++ b/build/preproc.h @@ -9,11 +9,13 @@ #ifdef _TO_ASM # define _CSPREF -S # define _OUTFIX S +# define _ASMTYPE -masm=intel # define LINK_KERNEL(out) #else # define _CSPREF -c # define _OUTFIX o -# define LINK_KERNEL(out) $(KCC) $(CLDSCR) $(COMMOBJS) $(KERNOBJS) -o $(BINDIR)/out +# define _ASMTYPE +# define LINK_KERNEL(out) $(KCC) -T ./build/kernel.ld $(CLDSCR) $(COMMOBJS) $(KERNOBJS) -o $(BINDIR)/out #endif #define COMPILE_CONVRT1(file) $(CCC) _CSPREF $(COMMDIR)/itoa.c -o $(COBJDIR)/file._OUTFIX diff --git a/kaleid/crtlib/atoi.c b/kaleid/crtlib/atoi.c index eaf42b6..7066c55 100644 --- a/kaleid/crtlib/atoi.c +++ b/kaleid/crtlib/atoi.c @@ -9,10 +9,8 @@ #include -// // String to integer // Do not change errno -// #define _ATOI_IMPL(_Name, _Type, _Func) \ _Type _Name(const char *str) { \ __get_errno(old); \ diff --git a/kaleid/crtlib/itoa.c b/kaleid/crtlib/itoa.c index b393a57..67572e1 100644 --- a/kaleid/crtlib/itoa.c +++ b/kaleid/crtlib/itoa.c @@ -9,9 +9,7 @@ #include -// // Digits table for bases <=36 (unused) -// #if 0 static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; @@ -20,7 +18,6 @@ static const char digits[] = // // Integer to string in any base between 2 and 36 (included) // - #if defined(_NEED_ITOA) #define _IL_MIN INT_MIN @@ -55,14 +52,11 @@ char *ultoa(ulong i, char *str, int base) 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; @@ -75,27 +69,21 @@ char *ultoa(ulong i, char *str, int base) } #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) @@ -110,14 +98,10 @@ char *ultoa(ulong i, char *str, int base) *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 index 925ae9f..ee31348 100644 --- a/kaleid/crtlib/memory.c +++ b/kaleid/crtlib/memory.c @@ -20,17 +20,13 @@ 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--) { + while (((ulong)uptr % alignof(QWORD)) > 0 && bytes--) { *uptr++ = (uchar)val; } - // // At this point we're qword-aligned - // - if (bytes > QWORD_SIZE) { + if (bytes > sizeof(QWORD)) { const ulong uval = ((ulong)val << 56) | ((ulong)val << 48) | ((ulong)val << 40) | ((ulong)val << 32) | ((ulong)val << 24) | ((ulong)val << 16) @@ -38,20 +34,16 @@ void *memset(void *ptr, int val, size_t bytes) ulong *uqptr = (ulong *)ptr; - // // Moving fast, qword by qword - // - while (bytes > QWORD_SIZE) { + while (bytes > sizeof(QWORD)) { + bytes -= sizeof(QWORD); *uqptr++ = uval; - bytes -= QWORD_SIZE; } uptr = (uchar *)(ulong)uqptr; } - // // Deal with the few remaining bytes - // while (bytes--) *uptr++ = (uchar)val; return ptr; @@ -64,18 +56,14 @@ 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) { - // + // Check whether we can we do this a word-aligned way + if unlikely (((ulong)uptr % alignof(WORD)) > 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--) { + while (((ulong)uptr % alignof(QWORD)) > 0 && words--) { *uptr++ = (ushort)val; } @@ -98,28 +86,22 @@ void *memsetw(void *ptr, int val, size_t words) 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; - + __set_errno(ENOSYS); 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; @@ -148,17 +130,13 @@ void *memcpy(void *restrict dst, const void *restrict src, size_t bytes) 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) { + if unlikely ((ulong)src % alignof(WORD) == 1 + && (ulong)dst % alignof(WORD) == 1) { const uchar *ubsrc = (const uchar *)usrc; uchar *ubdst = (uchar *)udst; - // - // Yes we can, we're guaranteed to be word-aligned now - // + // Yes we can, we're guaranteed to be word-aligned after that *ubdst++ = *ubsrc++; bytes--; @@ -169,34 +147,28 @@ void *memcpy(void *restrict dst, const void *restrict src, size_t bytes) 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) { + while ((ulong)dst % alignof(QWORD) > 0 + && (ulong)src % alignof(QWORD) > 0 + && bytes > sizeof(WORD)) { + bytes -= sizeof(WORD); *uwdst++ = *uwsrc++; - bytes -= WORD_SIZE; } udst = (ulong *)uwdst; usrc = (ulong *)uwsrc; - // - // This should be most of the job - // - while (bytes > QWORD_SIZE) { + // Copy fast + while (bytes > sizeof(QWORD)) { + bytes -= sizeof(QWORD); *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; @@ -210,16 +182,12 @@ 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--; diff --git a/kaleid/crtlib/sprintf.c b/kaleid/crtlib/sprintf.c index f0f6b15..c3ad3f1 100644 --- a/kaleid/crtlib/sprintf.c +++ b/kaleid/crtlib/sprintf.c @@ -52,14 +52,10 @@ 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++; } diff --git a/kaleid/crtlib/string.c b/kaleid/crtlib/string.c index 895d031..d9d6776 100644 --- a/kaleid/crtlib/string.c +++ b/kaleid/crtlib/string.c @@ -128,9 +128,7 @@ 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; @@ -150,15 +148,11 @@ char *strtok_r(char *restrict str, const char *restrict delim, char **restrict s 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; @@ -191,6 +185,7 @@ char *strtok(char *restrict str, const char *restrict delim) { static char *saveptr = NULL; + // Avoid this function if possible KalAssert(FALSE); if (str) saveptr = str; @@ -232,19 +227,22 @@ char *strncpy(char *restrict dest, const char *restrict src, size_t n) // Always null-terminates dest, but doesn't fill // dest's contents past the null-terminator // -// Returns the number of bytes written +// Returns the number of bytes NOT written, not counting null-terminators // size_t strnzcpy(char *restrict dest, const char *restrict src, size_t n) { - size_t it; + size_t it, loss; for (it = 0; it < n - 1 && src[it]; it++) { dest[it] = src[it]; } - dest[it++] = 0; + dest[it] = 0; - return it; + // Compute how many bytes were not copied + for (loss = it; src[loss]; loss++); + + return loss - it; } // @@ -277,13 +275,15 @@ char *strncat(char *restrict dest, const char *restrict src, size_t n) } // -// 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 +// Appends 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 NOT written, not counting null-terminators // size_t strnzcat(char *restrict dest, const char *restrict src, size_t n) { - size_t it, off = 0; + size_t it, loss, off = 0; while (dest[off]) off++; @@ -293,7 +293,10 @@ size_t strnzcat(char *restrict dest, const char *restrict src, size_t n) dest[it+off] = 0; - return it+1; + // Compute how many bytes were not copied + for (loss = it; src[loss+off]; loss++); + + return loss - it; } // diff --git a/kaleid/extras/argv.c b/kaleid/extras/argv.c index e4e2a49..d9920da 100644 --- a/kaleid/extras/argv.c +++ b/kaleid/extras/argv.c @@ -10,14 +10,193 @@ #include #include #include -#if 0 -error_t KalCmdLineToArgV(const char *cmdLine, - int argcMax, - int *argcPtr, - const char **argv); +#include -error_t KalArgVToCmdLine(const char *cmdLine, - size_t lengthMax, - int argc, - const char **argv); -#endif +// +// Computes argument count, the least N such +// that argv[N] == NULL +// +int KalComputeArgCount(const char **argv) +{ + int argc = 0; + + while (argv[argc]) argc++; + + return argc; +} + +// +// Computes the total size of argv, including +// the null-terminators +// +size_t KalComputeArgVecSize(const char *argv[]) +{ + size_t len; + + for (len = 0; *argv; len += strlen(*argv) + 1, argv++); + + return len; +} + +// +// Converts command line to an argument vector +// +// This function assumes that argv[0] is a pointer +// to a ARG_MAX-wide buffer, which will be filled +// with strings in succession; the address of the nth +// string will be stored in argv[n-1] +// +// Technically ARG_MAX is the maximum number of bytes +// in both the buffer *and* argv, i.e. (argc + 1) * sizeof(char *) +// bytes are reserved for the argv[i] pointers, so in fact less than +// ARG_MAX bytes are available +// +// That available space, however, remains strictly higher than 4KB, +// which is the POSIX minimum; in case of doubt, safely use 4KB +// +// TODO long escape sequences +// get program command line if cmdLine == NULL +// +error_t KalCmdLineToArgVecEx(const char *cmdLine, + int *argcPtr, + char **argv, + bool doEscaping) +{ + int argc; + char quotes = 0; + bool started = false; + bool escaping = false; + size_t written = 0; + error_t retcode = EOK; + + KalAlwaysAssert(argv && *argv && cmdLine); + + // An ARG_MAX-wide buffer + char *buffer = *argv; + + // Null-terminate current argv slot + // and save the start of next string + // Macro'd to avoid copypasting code +#define NULLTERM_AND_SAVE \ + *buffer = 0; \ + argv[++argc] = buffer++ + 1; \ + written += sizeof(char *) + 1; \ + + // Is character a blank character? + // To be replaced by ctype stuff once + // that's implemented +#define ISBLANK(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') + + // Both " and ' are valid quotes chars + // XXX aren't there more? +#define ISQUOTE(c) ((c) == '\'' || (c) == '"') + + + // Go through the command line + for (argc = 0; *cmdLine; cmdLine++) { + + // Make sure we don't go beyond ARG_MAX bytes + if (written >= ARG_MAX - (1 + sizeof(char *))) { + + // All we have left is one byte for the null-terminator of the current slot + // and sizeof(char *) bytes for the NULL at the end of argv + *buffer = 0; + + // Did we write anything in this slot? + if (started) { + argc++; + } + + // We're done, get out of here + retcode = ENOMEM; + break; + } + + // Switch to next argv slot + if (ISBLANK(*cmdLine) && !quotes && !escaping) { + + // Has slot even started? + if (started) { + started = false; + NULLTERM_AND_SAVE; + } + + continue; + } + + // Escaping next character + if (*cmdLine == '\\' && !escaping && doEscaping) { + escaping = true; + continue; + } + + // Deal with escape sequences + if (escaping) { + if (*cmdLine == 'n') *buffer++ = '\n'; + else if (*cmdLine == 'r') *buffer++ = '\r'; + else if (*cmdLine == 't') *buffer++ = '\t'; + else if (*cmdLine == 'f') *buffer++ = '\f'; + else if (*cmdLine == 'v') *buffer++ = '\v'; + + written++; + started = true; + escaping = false; + continue; + } + + // Deal with quotes + if (ISQUOTE(*cmdLine) && !escaping) { + + // Quoted text always fills a whole slot + // Note that this is the only way an empty + // string can be put in a slot + if (!quotes && !started) { + quotes = *cmdLine; + started = true; + + continue; + } + + // End a quote block + if (quotes == *cmdLine && ISBLANK(cmdLine[1])) { + quotes = 0; + started = false; + + NULLTERM_AND_SAVE; + continue; + } + + // Quotes were either preceeded by unquoted non-blank text + // or couldn't close quoted text block because succeeded + // by text; we consider this " to be escaped and fall through + } + + // Just a regular character, or it is being escaped + written++; + started = true; + escaping = false; + *buffer++ = *cmdLine; + } + + // Ensures that argv[argc] == NULL + argv[++argc] = NULL; + + // Update *argcPtr, but we don't mind if + // NULL was passed for argcPtr + if (argcPtr) { + *argcPtr = argc; + } + + return retcode; +} + +#undef ISQUOTE +#undef ISBLANK +#undef NULLTERM_AND_SAVE + +error_t KalCmdLineToArgVec(const char *cmdLine, + int *argcPtr, + char **argv) +{ + return KalCmdLineToArgVecEx(cmdLine, argcPtr, argv, false); +} diff --git a/kaleid/extras/prog.c b/kaleid/extras/prog.c index e3591d0..b0ce13d 100644 --- a/kaleid/extras/prog.c +++ b/kaleid/extras/prog.c @@ -13,7 +13,7 @@ #ifdef _KALEID_KERNEL const char *__progname = "kaleid-kernel"; -const char *__progvers = "alpha-0.0.1"; +const char *__progvers = "pre-pre-alpha-0.0.1"; #else diff --git a/kaleid/include/base/assert.h b/kaleid/include/base/assert.h index e5d5608..65d00da 100644 --- a/kaleid/include/base/assert.h +++ b/kaleid/include/base/assert.h @@ -10,8 +10,6 @@ #ifndef _KALBASE_ASSERT_H #define _KALBASE_ASSERT_H -//------------------------------------------// -// Macros // //------------------------------------------// #ifndef noreturn @@ -42,14 +40,10 @@ static_assert(sizeof(void *) == 8, _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)) \ @@ -69,12 +63,10 @@ noreturn void __assert_handler(const char *, const char *, int, const char *); #ifndef _OSK_SOURCE -// // When not building for OS/K, use the system's assert -// #include -#undef KalAwaysAssert +#undef KalAlwaysAssert #define KalAlwaysAssert assert #endif @@ -110,8 +102,6 @@ noreturn void __assert_handler(const char *, const char *, int, const char *); #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 index 1c1ef13..9b3c4d4 100644 --- a/kaleid/include/base/bdefs.h +++ b/kaleid/include/base/bdefs.h @@ -10,8 +10,6 @@ #ifndef _KALBASE_BDEFS_H #define _KALDEFS_BDEFS_H -//------------------------------------------// -// Actual constants // //------------------------------------------// #ifndef TRUE @@ -30,8 +28,6 @@ #define INITOK ((unsigned int)0xCAFEBABE) #endif -//------------------------------------------// -// Keywords // //------------------------------------------// #ifndef __alignof_is_defined @@ -57,8 +53,6 @@ # endif #endif -//------------------------------------------// -// Attributes and macros // //------------------------------------------// #ifndef _PACKED @@ -85,16 +79,6 @@ #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 index e4e7767..47b269d 100644 --- a/kaleid/include/base/crtlib.h +++ b/kaleid/include/base/crtlib.h @@ -10,8 +10,6 @@ #ifndef _KALBASE_CRTLIB_H #define _KALBASE_CRTLIB_H -//------------------------------------------// -// Typedefs // //------------------------------------------// #ifndef __error_t_defined @@ -39,8 +37,6 @@ typedef struct { int quot, rem; } div_t; typedef struct { long quot, rem; } ldiv_t; #endif -//------------------------------------------// -// Global variables // //------------------------------------------// #ifndef _KALEID_KERNEL @@ -62,16 +58,12 @@ extern error_t __errno; #endif -//------------------------------------------// -// Macros // //------------------------------------------// #ifndef _NO_MASK #define _NO_MASK #endif -//------------------------------------------// -// va_list utilities // //------------------------------------------// #ifndef va_start @@ -90,8 +82,6 @@ extern error_t __errno; #define va_end __builtin_va_end #endif -//------------------------------------------// -// Memory management utilities // //------------------------------------------// #ifndef memsetb @@ -107,10 +97,12 @@ 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); @@ -120,8 +112,6 @@ 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 *); @@ -157,8 +147,6 @@ 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); @@ -174,26 +162,16 @@ 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 @@ -234,8 +212,6 @@ static inline ldiv_t ldiv(long __x, long __y) } #endif -//------------------------------------------// -// End of header // //------------------------------------------// #endif diff --git a/kaleid/include/base/errno.h b/kaleid/include/base/errno.h index c4476e3..f77c8f8 100644 --- a/kaleid/include/base/errno.h +++ b/kaleid/include/base/errno.h @@ -10,8 +10,6 @@ #ifndef _KALBASE_ERRNO_H #define _KALBASE_ERRNO_H -//------------------------------------------// -// "errno" values // //------------------------------------------// // Everything went fine @@ -44,6 +42,12 @@ // Bad file number #define EBADF 9 +// Try again +#define EAGAIN 11 + +// Out of memory +#define ENOMEM 12 + // Invalid argument #define EINVAL 22 @@ -56,8 +60,6 @@ // System is panicking #define EPANIC 600 -//------------------------------------------// -// End of header // //------------------------------------------// #endif diff --git a/kaleid/include/base/limits.h b/kaleid/include/base/limits.h index affe0fa..56a03ee 100644 --- a/kaleid/include/base/limits.h +++ b/kaleid/include/base/limits.h @@ -10,95 +10,58 @@ #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 +#define BYTE unsigned char +#define WORD unsigned short +#define DWORD unsigned int +#define QWORD unsigned long -#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 +#define CHAR_BIT 8 +#define BITS_IN(T) (sizeof(T) * CHAR_BIT) -#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 +/* XXX find a generic way */ +#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) -//------------------------------------------// -// 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 +/* U/L suffixes on hex numbers look odd */ +#define SCHAR_MAX ((signed char) 0x7F) +#define SHRT_MAX ((short) 0x7FFF) +#define INT_MAX ((int) 0x7FFFFFFF) +#define LONG_MAX ((long) 0x7FFFFFFFFFFFFFFFL) +#define UCHAR_MAX ((unsigned char) 0xFFU) +#define USHRT_MAX ((unsigned short) 0xFFFFU) +#define UINT_MAX ((unsigned int) 0xFFFFFFFFU) +#define ULONG_MAX ((unsigned long) 0xFFFFFFFFFFFFFFFFUL) -#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 +#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) -#ifndef DATA_CHAR_LIMITS_BLOCK -#define DATA_CHAR_LIMITS_BLOCK -# ifdef __CHAR_UNSIGNED__ +#ifdef __CHAR_UNSIGNED__ # define CHAR_MIN ((char)0) # define CHAR_MAX ((char)UCHAR_MAX) -# else +#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 +#define SSIZE_T_MIN LONG_MIN +#define SSIZE_T_MAX LONG_MAX +#define SIZE_T_MAX ULONG_MAX #ifdef NEED_MORE_USELESS_DATA # define UCHAR_MIN ((unsigned char)0) @@ -110,8 +73,6 @@ # endif #endif -//------------------------------------------// -// End of header // //------------------------------------------// #endif diff --git a/kaleid/include/base/masks.h b/kaleid/include/base/masks.h index 60e861e..868df80 100644 --- a/kaleid/include/base/masks.h +++ b/kaleid/include/base/masks.h @@ -38,26 +38,40 @@ //------------------------------------------// +#undef strspn +#undef strcspn #define strlen _osk_strlen #define strspn _osk_strspn #define strcspn _osk_strcspn +#undef strcmp +#undef strncmp #define strcmp _osk_strcmp #define strncmp _osk_strncmp +#undef strchr +#undef strrchr #define strchr _osk_strchr #define strrchr _osk_strrchr +#undef strstr +#undef strpbrk #define strstr _osk_strstr #define strpbrk _osk_strpbrk +#undef strtok +#undef strtok_r #define strtok _osk_strtok #define strtok_r _osk_strtok_r +#undef strcpy +#undef strncpy #define strcpy _osk_strcpy #define strncpy _osk_strncpy #define strnzcpy _osk_strnzcpy +#undef strcat +#undef strncat #define strcat _osk_strcat #define strncat _osk_strncat #define strnzcat _osk_strnzcat @@ -72,7 +86,6 @@ //------------------------------------------// - #define itoa _osk_itoa #define ltoa _osk_ltoa #define utoa _osk_utoa @@ -112,8 +125,6 @@ #define strerror _osk_strerror -//------------------------------------------// -// End of header // //------------------------------------------// #endif diff --git a/kaleid/include/base/types.h b/kaleid/include/base/types.h index 115319a..7e40d34 100644 --- a/kaleid/include/base/types.h +++ b/kaleid/include/base/types.h @@ -10,8 +10,6 @@ #ifndef _KALBASE_TYPES_H #define _KALBASE_TYPES_H -//------------------------------------------// -// Basic integer types aliases // //------------------------------------------// #ifndef __base_types_aliases @@ -26,8 +24,6 @@ typedef unsigned long long ullong; typedef long double ldouble; #endif -//------------------------------------------// -// Miscellaneous types // //------------------------------------------// #ifndef __size_t_defined @@ -50,8 +46,6 @@ typedef signed int wchar_t; typedef unsigned long off_t; #endif -//------------------------------------------// -// Standard fixed-width integer types // //------------------------------------------// #ifndef __ptrdiff_t_defined @@ -79,8 +73,6 @@ typedef signed long intmax_t; typedef unsigned long uintmax_t; #endif -//------------------------------------------// -// Special types // //------------------------------------------// #ifndef __va_list_defined @@ -99,8 +91,6 @@ typedef struct { long quot, rem; } ldiv_t; #endif -//------------------------------------------// -// Kaleid-specific types // //------------------------------------------// #ifndef __error_t_defined @@ -113,8 +103,6 @@ typedef int error_t; typedef ushort port_t; #endif -//------------------------------------------// -// End of header // //------------------------------------------// #endif diff --git a/kaleid/include/extras/argv.h b/kaleid/include/extras/argv.h index 352c532..2a1a22e 100644 --- a/kaleid/include/extras/argv.h +++ b/kaleid/include/extras/argv.h @@ -11,116 +11,272 @@ #include #endif -//------------------------------------------// -// Start of header // -//------------------------------------------// +#ifdef _KALEID_KERNEL +#define FILE FILE +typedef void* FILE; +#else +#include +#endif #ifndef _KALEXTRAS_ARGV_H #define _KALEXTRAS_ARGV_H //------------------------------------------// -// Types // + +// +// Maximal total size of argv, including the pointers, +// the pointed-to strings and their null-terminators +// This is a 32-bit integer +// +#define ARG_MAX (1 << 16) // 16 KB + //------------------------------------------// // -// Option types +// Flags for options // typedef enum { - // - // A flag option, without any more parameters - // - CMDOPT_FLAG, - // - // An option that expects a parameter - // - CMDOPT_PARAM, + // The option parameter is optional + KALOPT_OPTIONAL = (1 << 0), -} CmdOptType_t; + // Do not show option in any help message + KALOPT_HIDDEN = (1 << 1), + + // This option is an alias for the previous one + KALOPT_ALIAS = (1 << 2), + + // This isn't an option but a docstring + KALOPT_DOCSTR = (1 << 3), + + // Only show in long help messages + KALOPT_LONGDOC = (1 << 4), + +} CmdOptionFlag_t; + +// +// Flags for KalParse(CmdLine|ArgV) +// +typedef enum { + + // Don't exit on errors= + KALOPT_NO_EXIT = (1 << 0), + + // Don't react to --help + KALOPT_NO_HELP = (1 << 1), + + // Don't react to --version + KALOPT_NO_VERSION = (1 << 2), + + // Alias -h for --help and -V for --version + KALOPT_ALIASES = (1 << 3), + + // Don't print any error message + // Implies KALOPT_NO_EXIT + KALOPT_NO_ERRORS = (1 << 4) | KALOPT_NO_EXIT, + + // Use KalGetProgName() instead of argv[0] + // as program name + KALOPT_USE_ARGV0 = (1 << 5), + + // Call argument parser for non-options + // Non-options arguments will be indicated by + // a key of 0, the argument passed as a parameter + KALOPT_PARSE_ALL = (1 << 6), + + // Call argument parser with options and non-options in the + // order they were found, instead of parsing options first + KALOPT_IN_ORDER = (1 << 7) | KALOPT_PARSE_ALL, + + // Stay silent all along + KALOPT_SILENT = KALOPT_NO_EXIT | KALOPT_NO_ERRORS + | KALOPT_NO_HELP | KALOPT_NO_VERSION, + +} CmdParserFlags_t; + +// +// Return values for the command parser +// These flags can be combined and are applied in order +// +// "Continue" and "Break" actions do not prevent +// later actions from applying +// +typedef enum { + + // Continue parsing new options + KALOPT_CONTINUE = 0, + + // Stop parsing further options + KALOPT_BREAK = (1 << 0), + + // Show help/version message (by default, continue parsing) + KALOPT_SHOWHELP = (1 << 1), + KALOPT_SHOWVERS = (1 << 2), + +} CmdParserReturn_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; - // + // Address of the variable to put the parameter into + const char *param; + + // Option flags, see above + CmdOptionFlag_t flags; + + // The option's help text + // If this is 0, this option is hidden + const char *helpText; + // 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 // -//------------------------------------------// +// +// Program help/documentation strings; any can be 0 +// +// Help messages are printed in this format: +// (letting "this" be a CmdDocStrings_t* variable) +// +// Usage: (this->usage) +// (this->header) +// +// (this->groups[0]) +// -o, --option-name option description +// ... +// ... +// +// (this->bottom) +// +// XXX progname/version +// +typedef struct { -int KalComputeArgC(const char *argv[]); + const char *usage; + const char *header; + const char *bottom; -size_t KalComputeArgVSize(const char *argv[]); + // Groups documentation + // groups[n] should be either 0 or contain the + // description of the option group n + const char **groups; -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); +} CmdDocStrings_t; // -// The "Ex" variants reacts to "--help" and "--version" by themselves +// The state variable passed to the parser containing useful infos // +typedef struct { -error_t KalParseCmdLineEx(const char *cmdLine, - CmdOption_t *options, - const char *progDesc, - const char *groupDescs[]); + // Option we're currently parsing + const CmdOption_t *option; -error_t KalParseArgVEx(int argc, - const char *argv[], - CmdOption_t *options, - const char *progDesc, - const char *groupDescs[]); + // Index (in argv) of the option we're parsing + int argvIndex; + + // Flags passed to KalParse(CmdLine|ArgV) + CmdParserFlags_t flags; + + // Has help/version messages been displayed already? + bool shownHelp; + bool shownVersion; + + // Standard output streams + FILE *outStream; + FILE *errStream; + + // Private, internal data; do not touch + void *priv; + +} CmdParserState_t; + +// +// The argument parser function +// +typedef CmdParserReturn_t (*CmdParser_t)(int key, + const char *param, + CmdParserState_t *state); //------------------------------------------// -// End of header // + +// +// Misc. simple functions +// +int KalComputeArgCount(const char **argv); +size_t KalComputeArgVecSize(const char **argv); + +// +// Command line to argument vector utility +// +error_t KalCmdLineToArgVecEx(const char *cmdLine, + int *argcPtr, + char **argv, + bool doEscaping); + +// +// KalCmdLineToArgVecEx but doEscaping = false +// +error_t KalCmdLineToArgVec(const char *cmdLine, + int *argcPtr, + char **argv); +/* + +// +// Argument vector to command line utility +// +error_t KalArgVecToCmdLineEx(char *cmdLine, + size_t lengthMax, + int argc, + const char **argv, + bool doUnEscaping); + +// +// KalArgVecToCmdLineEx but doUnEscapign = false +// +error_t KalArgVecToCmdLine(char *cmdLine, + size_t lengthMax, + int argc, + const char **argv); +// +// Command line parser; only takes an argument vector +// The argv argument *will* be modified and all parsed +// options and arguments will be removed, except argv[0] +// which is guanranteed to be left +// +error_t KalParseArgVecEx(int argc, + char **argv, + const CmdOption_t *options, + const CmdDocStrings_t *docStrings, + CmdParserFlags_t *flags, + CmdParser_t *parser, + FILE *outStream, + FILE *errStream); +// +// KalParseArgVecEx(argc, argv, options, docString, stdin, stdout, parser, NULL) +// +error_t KalParseArgVec(int argc, + char **argv, + const CmdOption_t *options, + const CmdDocStrings_t *docStrings, + CmdParserFlags_t *flags, + CmdParser_t *parser); + +*/ + //------------------------------------------// #endif diff --git a/kaleid/include/extras/list.h b/kaleid/include/extras/list.h index d9f5bd6..d394ddf 100644 --- a/kaleid/include/extras/list.h +++ b/kaleid/include/extras/list.h @@ -15,26 +15,13 @@ #include #endif -//------------------------------------------// -// Start of header // -//------------------------------------------// +#ifndef _KALEXTRAS_MALLOC_H +#include +#endif #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 { @@ -51,8 +38,6 @@ typedef struct sListNode_t { struct sListNode_t *next; } ListNode_t; -//------------------------------------------// -// Functions // //------------------------------------------// // @@ -74,7 +59,7 @@ static inline ListHead_t } // -// Create a liste head +// Create a list head // static inline ListHead_t *CreateListHead(void) @@ -265,8 +250,6 @@ DestroyListHead(ListHead_t *head) // #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 index 4ca5220..e2333e3 100644 --- a/kaleid/include/extras/locks.h +++ b/kaleid/include/extras/locks.h @@ -17,48 +17,35 @@ #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? + volatile int locked; // is locked? #ifdef _KALEID_KERNEL Thread_t *ownerThread; // unused Thread_t *waitingThread; // unused #endif -} volatile Lock_t; +} Lock_t; -//------------------------------------------// -// Functions // //------------------------------------------// // @@ -124,9 +111,9 @@ void AquireLock(Lock_t *lock) #else if likely (lock->type == KLOCK_SPINLOCK) continue; #ifdef _OSK_SOURCE - else KalYieldCPU(); + else (void)KalYieldCPU(); #else - else sched_yield(); + else (void)sched_yield(); #endif #endif } @@ -163,8 +150,6 @@ bool AttemptLock(Lock_t *lock) return retval; } -//------------------------------------------// -// End of header // //------------------------------------------// #endif diff --git a/kaleid/include/extras/malloc.h b/kaleid/include/extras/malloc.h new file mode 100644 index 0000000..65728cd --- /dev/null +++ b/kaleid/include/extras/malloc.h @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Memory allocation utilities // +//----------------------------------------------------------------------------// + +#ifndef _KALBASE_H +#include +#endif + +#ifndef _KALEXTRAS_MALLOC_H +#define _KALEXTRAS_MALLOC_H + +//------------------------------------------// + +// +// ¯\_(ツ)_/¯ +// +#ifndef _STDLIB_H +void *malloc(unsigned long); +void free(void *); +#endif + +#define AllocMemory malloc +#define FreeMemory free + +//------------------------------------------// + +#endif + diff --git a/kaleid/include/extras/prog.h b/kaleid/include/extras/prog.h index bae5b1a..57a008b 100644 --- a/kaleid/include/extras/prog.h +++ b/kaleid/include/extras/prog.h @@ -11,22 +11,14 @@ #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); @@ -35,8 +27,6 @@ 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 index 618061a..8743f05 100644 --- a/kaleid/include/kalbase.h +++ b/kaleid/include/kalbase.h @@ -14,10 +14,10 @@ // Building for OS/K // //------------------------------------------// -#if !defined(_OSK_SOURCE) -# if defined(_KALEID_KERNEL) || defined(_KALEID_SYSTEM) -# define _OSK_SOURCE 1 -# endif +#ifndef _OSK_SOURCE +#if defined(_KALEID_KERNEL) || defined(_KALEID_SYSTEM) +#define _OSK_SOURCE 1 +#endif #endif #if !defined(_OSK_SOURCE) && !defined(_KALEID_UNMASKED) @@ -54,8 +54,6 @@ #include #endif -//------------------------------------------// -// End of header // //------------------------------------------// #endif diff --git a/kaleid/include/kaleid.h b/kaleid/include/kaleid.h index 239b222..36401a3 100644 --- a/kaleid/include/kaleid.h +++ b/kaleid/include/kaleid.h @@ -27,8 +27,7 @@ #include #endif #endif -//------------------------------------------// -// End of header // + //------------------------------------------// #endif diff --git a/kaleid/include/kalext.h b/kaleid/include/kalext.h index 5dcc19f..a4c5b4f 100644 --- a/kaleid/include/kalext.h +++ b/kaleid/include/kalext.h @@ -11,8 +11,6 @@ #include #endif -//------------------------------------------// -// Start of header // //------------------------------------------// #ifndef _KALEXT_H @@ -40,8 +38,6 @@ #endif #endif -//------------------------------------------// -// End of header // //------------------------------------------// #endif diff --git a/kaleid/include/kalkern.h b/kaleid/include/kalkern.h index 82c84c6..2020436 100644 --- a/kaleid/include/kalkern.h +++ b/kaleid/include/kalkern.h @@ -15,8 +15,6 @@ #include #endif -//------------------------------------------// -// Start of header // //------------------------------------------// #ifndef _KALKERN_H @@ -41,8 +39,6 @@ #endif #endif -//------------------------------------------// -// End of header // //------------------------------------------// #endif diff --git a/kaleid/include/kernel/base.h b/kaleid/include/kernel/base.h index 6ac5134..dbf03bd 100644 --- a/kaleid/include/kernel/base.h +++ b/kaleid/include/kernel/base.h @@ -11,18 +11,14 @@ #include #endif -//------------------------------------------// -// Start of header // //------------------------------------------// #ifndef _KALKERN_BASE_H #define _KALKERN_BASE_H -//------------------------------------------// -// Elementary types // //------------------------------------------// -typedef struct sLock_t volatile Lock_t; +typedef struct sLock_t Lock_t; typedef struct sThread_t Thread_t; typedef struct sProcess_t Process_t; typedef struct sTerminal_t Terminal_t; @@ -30,23 +26,23 @@ typedef struct sListHead_t ListHead_t; typedef struct sListNode_t ListNode_t; //------------------------------------------// -// Values for __kstate // -//------------------------------------------// + +/* XXX */ // // Current state of the kernel // typedef enum { - // the kernel is booting + // The kernel is booting KSTATE_INIT, - // the kernel is not running a process + // The kernel is not running a process KSTATE_KERNEL, - // a process is running in kernel mode + // A process is running in kernel mode KSTATE_PROCESS, - // the kernel is panicking + // The kernel is panicking KSTATE_PANIC, } KernelState_t; @@ -88,48 +84,50 @@ typedef enum { _Tp __ ## _X [NCPUS] = { (_Tp) 0 } -//------------------------------------------// -// Global constants // //------------------------------------------// // XXX -DECLARE_PER_CPU(PanicStr, const char *); +DECLARE_PER_CPU(PanicStr, const char *); -DECLARE_PER_CPU(KernState, KernelState_t); +DECLARE_PER_CPU(KernState, KernelState_t); -DECLARE_PER_CPU(_StdOut, Terminal_t *); -DECLARE_PER_CPU(_StdDbg, Terminal_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 *); +DECLARE_PER_CPU(CurProc, Process_t *); +DECLARE_PER_CPU(CurThread, Thread_t *); + +DECLARE_PER_CPU(ReSchedFlag, bool); +DECLARE_PER_CPU(PreemptCount, ulong); -//------------------------------------------// -// Macros for manipulating said // -// global constants // //------------------------------------------// -#define SetKernState(x) \ - do { \ - _SetKernState(x); \ - } while (0) +#define SetKernState(x) _SetKernState(x); -#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) +// +// StdOut/StdDbg manipulation +// +#define GetStdOut() (GetCurProc() == NULL ? Get_StdOut() : GetCurProc()->stdOut) +#define GetStdDbg() (GetCurProc() == NULL ? Get_StdDbg() : GetCurProc()->stdDbg) +#define SetStdOut(tm) do { if (GetCurProc() == NULL) _Set_StdOut(tm); \ + else GetCurProc()->stdOut = (tm); } while (0) +#define SetStdDbg(tm) do { if (GetCurProc() == NULL) _Set_StdDbg(tm); \ + else GetCurProc()->stdDbg = (tm); } while (0) +// +// Re-scheduling and preemption +// XXX XXX XXX atomic operations +// +#define SetReSchedFlag(x) _SetReSchedFlag(x) +#define DisablePreemption() _SetPreemptCount(GetPreemptCount()+1) +#define EnablePreemption() do { KalAssert(GetPreemptCount() > 0); \ + _SetPreemptCount(GetPreemptCount()-1); } while(0) //------------------------------------------// -// Other Macros // -//------------------------------------------// + +// +// Value of the preemption count indicating that preemption is activated +// +#define PREEMPT_ON 0 // // Size of a tabulation in spaces @@ -159,7 +157,44 @@ DECLARE_PER_CPU(CurThread, Thread_t *); #define HaltCPU() do { asm volatile ("hlt"); } while (1) //------------------------------------------// -// Some base functions // + +// +// 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; + + // Standard output/debug + Terminal_t *stdOut, *stdDbg; + +} Process_t; + //------------------------------------------// noreturn void StartPanic(const char *); @@ -169,10 +204,13 @@ 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)); + KalAssert(FALSE && ENOSYS); + (void)port; + (void)val; } static inline @@ -191,9 +229,6 @@ ushort ReadWordFromPort(port_t port) return 0; } -//------------------------------------------// -// End of header // //------------------------------------------// #endif - diff --git a/kaleid/include/kernel/sched.h b/kaleid/include/kernel/sched.h index 596e08f..5dc1023 100644 --- a/kaleid/include/kernel/sched.h +++ b/kaleid/include/kernel/sched.h @@ -11,37 +11,25 @@ #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 *); @@ -51,46 +39,6 @@ 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); @@ -99,8 +47,6 @@ 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 index 1cde180..0cb08f1 100644 --- a/kaleid/include/kernel/terminal.h +++ b/kaleid/include/kernel/terminal.h @@ -11,15 +11,11 @@ #include #endif -//------------------------------------------// -// Start of header // //------------------------------------------// #ifndef _KALKERN_TERMINAL_H #define _KALKERN_TERMINAL_H -//------------------------------------------// -// Types // //------------------------------------------// // @@ -64,8 +60,6 @@ typedef struct sTerminal_t { } Terminal_t; -//------------------------------------------// -// Functions // //------------------------------------------// void InitTerms(void); @@ -74,8 +68,6 @@ 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 @@ -84,8 +76,6 @@ error_t ChTermColor(Terminal_t *, TermColor_t, TermColor_t); # define DebugLog(...) #endif -//------------------------------------------// -// End of header // //------------------------------------------// #endif diff --git a/kaleid/kernel/init/table.c b/kaleid/kernel/init/table.c index 4b98d25..e610a42 100644 --- a/kaleid/kernel/init/table.c +++ b/kaleid/kernel/init/table.c @@ -19,3 +19,5 @@ CREATE_PER_CPU(_StdDbg, Terminal_t *); CREATE_PER_CPU(CurProc, Process_t *); CREATE_PER_CPU(CurThread, Thread_t *); +CREATE_PER_CPU(ReSchedFlag, bool); + diff --git a/kaleid/kernel/io/cursor.c b/kaleid/kernel/io/cursor.c new file mode 100644 index 0000000..e69de29 diff --git a/kaleid/kernel/io/term.c b/kaleid/kernel/io/term.c new file mode 100644 index 0000000..98d3827 --- /dev/null +++ b/kaleid/kernel/io/term.c @@ -0,0 +1,105 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Early terminal functions // +//----------------------------------------------------------------------------// + +#include + +extern void VGA_Init(void); +extern Terminal_t VGA_Terminal; + +// +// Initialize standard output +// +void InitTerms(void) +{ + KalAssert(!GetStdOut() && !GetStdDbg()); + + VGA_Init(); + + // vgaTerm.initDone = INITOK; + + SetStdDbg(&VGA_Terminal); + SetStdOut(&VGA_Terminal); + + ClearTerm(GetStdOut()); +} + +// +// Fill terminal with spaces +// +error_t ClearTerm(Terminal_t *term) +{ + error_t retcode; + + if (term == NULL) return EINVAL; + KalAssert(term->initDone == INITOK); + + AquireLock(&term->lock); + retcode = term->ClearTermUnlocked(term); + ReleaseLock(&term->lock); + + return retcode; +} + +// +// Change the color code +// +error_t ChTermColor(Terminal_t *term, TermColor_t fgColor, TermColor_t bgColor) +{ + if (fgColor > KTERM_COLOR_WHITE || bgColor > KTERM_COLOR_WHITE) + return EINVAL; + + if (term == NULL) + return EINVAL; + + AquireLock(&term->lock); + + term->fgColor = fgColor; + term->bgColor = bgColor; + + ReleaseLock(&term->lock); + + return EOK; +} + +// +// Write a single character on the terminal +// +error_t PutOnTerm(Terminal_t *term, char ch) +{ + error_t retcode; + + if (term == NULL) return EINVAL; + KalAssert(term->initDone == INITOK); + + AquireLock(&term->lock); + retcode = term->PutOnTermUnlocked(term, ch); + ReleaseLock(&term->lock); + + return retcode; +} + +// +// Print string on terminal +// +error_t PrintOnTerm(Terminal_t *term, const char *str) +{ + error_t retcode = EOK; + + if (term == NULL) return EINVAL; + KalAssert(term->initDone == INITOK); + + AquireLock(&term->lock); + while (*str && retcode == EOK) { + retcode = term->PutOnTermUnlocked(term, *str++); + } + ReleaseLock(&term->lock); + + return retcode; +} + diff --git a/kaleid/kernel/ke/terminal.c b/kaleid/kernel/io/vga.c similarity index 66% rename from kaleid/kernel/ke/terminal.c rename to kaleid/kernel/io/vga.c index 1d7439b..f26ef65 100644 --- a/kaleid/kernel/ke/terminal.c +++ b/kaleid/kernel/io/vga.c @@ -4,102 +4,11 @@ // Authors: spectral` // // NeoX // // // -// Desc: Early terminal functions // +// Desc: VGA terminal functions // //----------------------------------------------------------------------------// #include -static Terminal_t vgaTerm; - -// -// Initialize standard output -// -void InitTerms(void) -{ - KalAssert(!GetStdOut() && vgaTerm.initDone != INITOK); - - vgaTerm.initDone = INITOK; - - SetStdDbg(&vgaTerm); - SetStdOut(&vgaTerm); - - ClearTerm(GetStdOut()); -} - -// -// Fill terminal with spaces -// -error_t ClearTerm(Terminal_t *term) -{ - error_t retcode; - - if (term == NULL) return EINVAL; - KalAssert(term->initDone == INITOK); - - AquireLock(&term->lock); - retcode = term->ClearTermUnlocked(term); - ReleaseLock(&term->lock); - - return retcode; -} - -// -// Change the color code -// -error_t ChTermColor(Terminal_t *term, TermColor_t fgColor, TermColor_t bgColor) -{ - if (fgColor > KTERM_COLOR_WHITE || bgColor > KTERM_COLOR_WHITE) - return EINVAL; - - if (term == NULL) - return EINVAL; - - AquireLock(&term->lock); - - term->fgColor = fgColor; - term->bgColor = bgColor; - - ReleaseLock(&term->lock); - - return EOK; -} - -// -// Write a single character on the terminal -// -error_t PutOnTerm(Terminal_t *term, char ch) -{ - error_t retcode; - - if (term == NULL) return EINVAL; - KalAssert(term->initDone == INITOK); - - AquireLock(&term->lock); - retcode = term->PutOnTermUnlocked(term, ch); - ReleaseLock(&term->lock); - - return retcode; -} - -// -// Print string on terminal -// -error_t PrintOnTerm(Terminal_t *term, const char *str) -{ - error_t retcode = EOK; - - if (term == NULL) return EINVAL; - KalAssert(term->initDone == INITOK); - - AquireLock(&term->lock); - while (*str && retcode == EOK) { - retcode = term->PutOnTermUnlocked(term, *str++); - } - ReleaseLock(&term->lock); - - return retcode; -} - //----------------------------------------------------------// // Internal functions for VGA terminals // // These DO NOT check input correctness // @@ -143,23 +52,17 @@ error_t VGA_PutOnTermUnlocked(Terminal_t *term, char ch) return EOK; } - // // Line feed first takes us to the very end of the line // Later in this function we actually do the line feed - // else if (ch == '\n') { term->currentY = term->width - 1; } - // // Tabulations account for "term->tabSize" spaces - // else if (ch == '\t') { prevY = term->currentY; for (i = 0; i < term->tabSize; i++) { - // // Make sure tabulations can't spread over two lines - // if (term->currentY == prevY) { VGA_PutOnTermUnlocked(term, ' '); } @@ -172,26 +75,18 @@ error_t VGA_PutOnTermUnlocked(Terminal_t *term, char ch) buffer[offset] = VGA_ComputeEntry(ch, VGA_ComputeColorCode(term->fgColor, term->bgColor)); } - // // Did we reach the end of line? - // if (++term->currentX == term->width) { term->currentX = 0; - // // Did we reach the buffer's end? - // if (++term->currentY == term->height) { - // // XXX scroll up - // term->currentY = 0; } } - // // Nothing can go wrong - // return EOK; } @@ -211,8 +106,9 @@ error_t VGA_PrintOnTermUnlocked(Terminal_t *term, const char *str) // // VGA output +// XXX custom sizes // -static Terminal_t vgaTerm = { +Terminal_t VGA_Terminal = { .initDone = FALSE, .lock = INITLOCK(KLOCK_MUTEX), @@ -234,3 +130,14 @@ static Terminal_t vgaTerm = { .PrintOnTermUnlocked = VGA_PrintOnTermUnlocked, }; + +// +// Initialize VGA output +// +void VGA_Init(void) +{ + KalAssert(VGA_Terminal.initDone != INITOK); + + VGA_Terminal.initDone = INITOK; +} + diff --git a/kaleid/kernel/proc/Makefile b/kaleid/kernel/proc/Makefile index 7c15976..c83ea97 100644 --- a/kaleid/kernel/proc/Makefile +++ b/kaleid/kernel/proc/Makefile @@ -1,4 +1,6 @@ sched-test: - gcc -O2 -Wall -Wextra -Wshadow -std=gnu11 -masm=intel -I../../include ./sched.c + gcc -O2 -Wall -Wextra -I../../include ./sched.c +clean: + rm a.out diff --git a/kaleid/kernel/proc/sched.c b/kaleid/kernel/proc/sched.c index 2a8dd9e..46b75f6 100644 --- a/kaleid/kernel/proc/sched.c +++ b/kaleid/kernel/proc/sched.c @@ -12,6 +12,7 @@ #ifndef _KALEID_KERNEL #include + CREATE_PER_CPU(CurProc, Process_t *); // @@ -19,16 +20,16 @@ CREATE_PER_CPU(CurProc, Process_t *); // int procslen = 10; Process_t procs[] = { - { 0, 0, 0, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL }, - { 1, 2, 2, 16, 16, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL }, - { 2, 3, 3, 31, 31, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL }, - { 3, 2, 2, 1, 1, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL }, - { 4, 3, 3, 5, 5, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL }, - { 5, 0, 0, 30, 30, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL }, - { 6, 1, 1, 19, 19, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL }, - { 7, 1, 1, 0, 0, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL }, - { 8, 3, 3, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL }, - { 9, 2, 2, 21, 21, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL }, + { 0, 0, 0, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL, NULL, NULL }, + { 1, 2, 2, 16, 16, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL, NULL, NULL }, + { 2, 3, 3, 31, 31, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL, NULL, NULL }, + { 3, 2, 2, 1, 1, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL, NULL, NULL }, + { 4, 3, 3, 5, 5, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL, NULL, NULL }, + { 5, 0, 0, 30, 30, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL, NULL, NULL }, + { 6, 1, 1, 19, 19, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL, NULL, NULL }, + { 7, 1, 1, 0, 0, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL, NULL, NULL }, + { 8, 3, 3, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL, NULL, NULL }, + { 9, 2, 2, 21, 21, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL, NULL, NULL }, }; #endif @@ -138,9 +139,7 @@ void SchedThisProcUnlocked(Process_t *proc) proc->schedNode = procNode; - // // Find a process with lesser priority - // for (iterNode = head->first; iterNode; iterNode = iterNode->next) { if (proc->prioLevel > GetNodeData(iterNode, Process_t *)->prioLevel) { // Detect double insertions @@ -153,9 +152,7 @@ void SchedThisProcUnlocked(Process_t *proc) } } - // // Didn't find any process with lesser priority - // if (found == false) { AppendNode(head, procNode); } @@ -240,15 +237,11 @@ void SchedOnTick(void) Process_t *procNext, *winner, *previous = GetCurProc(); - // // We're either idle or running something - // KalAssert(GetCurProc() == NULL || GetCurProc()->procState == STATE_RUNNING); - // // Have the current process spent its timeslice? // (To be handled in CPU decisions function) - // if (GetCurProc() != NULL) { if (GetCurProc()->timeSlice <= 1) { // Re-schedule @@ -258,42 +251,36 @@ void SchedOnTick(void) _SetCurProc(NULL); } - // // Otherwise, make it lose a tick - // else { GetCurProc()->timeSlice--; } } - // // Are we idle, or scheduling next process? - // if (GetCurProc() == NULL) { SetCurProc(SelectSchedNext()); goto leave; } - // - // Is there a higher priority process that is runnable? - // - procNext = SelectSchedNext(); - winner = CompareProcs(GetCurProc(), procNext); + // Is preemption on and a re-schedule is needed? + if (GetPreemptCount() == PREEMPT_ON && GetReSchedFlag()) { - // - // Yes, procNext should preempt current process - // - if (winner == procNext) { - // Re-schedule - ReSchedCurProc(); + // Is there a higher priority process that is runnable? + procNext = SelectSchedNext(); + winner = CompareProcs(GetCurProc(), procNext); - // Switch to procNext - SetCurProc(procNext); + // Yes, procNext should preempt current process + if (winner == procNext) { + // Re-schedule + ReSchedCurProc(); + + // Switch to procNext + SetCurProc(procNext); + } } - // // Current process won't be preempted and has time remaining - // leave: SchedUnlock(); @@ -436,4 +423,3 @@ int main(void) } #endif -