From cd0913ed134bebf6bc551d7698bb8074115b36c9 Mon Sep 17 00:00:00 2001 From: Adrien Bourmault Date: Fri, 8 Mar 2019 09:00:55 +0100 Subject: [PATCH] sprintf family, ctype, better panic, better terminals, better kernel/base.h & other stuff (#29) --- .gitignore | 2 +- kaleid/crtlib/arith.c => .stylehlp | 26 +--- Makefile.in | 9 +- kaleid/crtlib/ctype.c | 74 +++++++++++ kaleid/crtlib/itoa.c | 1 + kaleid/crtlib/sprintf.c | 199 +++++++++++++++++++++++++---- kaleid/crtlib/string.c | 67 ++++------ kaleid/extras/argv.c | 6 +- kaleid/include/base/assert.h | 8 -- kaleid/include/base/bdefs.h | 32 ++++- kaleid/include/base/crtlib.h | 108 +++++++++++----- kaleid/include/base/masks.h | 29 ++++- kaleid/include/base/types.h | 13 +- kaleid/include/extras/argv.h | 33 ++--- kaleid/include/extras/list.h | 16 +-- kaleid/include/extras/malloc.h | 2 +- kaleid/include/kaleid.h | 6 - kaleid/include/kalkern.h | 56 -------- kaleid/include/kernel/base.h | 71 ++++++---- kaleid/include/kernel/panic.h | 6 +- kaleid/include/kernel/proc.h | 4 +- kaleid/include/kernel/sched.h | 16 +-- kaleid/include/kernel/term.h | 32 +++-- kaleid/kernel/init/init.c | 2 +- kaleid/kernel/init/table.c | 12 +- kaleid/kernel/ke/panic.c | 22 ++-- kaleid/kernel/proc/sched.c | 1 - 27 files changed, 538 insertions(+), 315 deletions(-) rename kaleid/crtlib/arith.c => .stylehlp (84%) create mode 100644 kaleid/crtlib/ctype.c delete mode 100644 kaleid/include/kalkern.h diff --git a/.gitignore b/.gitignore index 49d6ef7..9fd0621 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,7 @@ multiboot.pdf grub.log Makefile.out.2 build/bin/s** -.stylehlp +#.stylehlp # Linker output *.ilk diff --git a/kaleid/crtlib/arith.c b/.stylehlp similarity index 84% rename from kaleid/crtlib/arith.c rename to .stylehlp index 150c37b..588d391 100644 --- a/kaleid/crtlib/arith.c +++ b/.stylehlp @@ -1,7 +1,7 @@ //----------------------------------------------------------------------------// // GNU GPL OS/K // // // -// Desc: Arithmetic functions // +// Desc: // // // // // // Copyright © 2018-2019 The OS/K Team // @@ -22,27 +22,5 @@ // along with OS/K. If not, see . // //----------------------------------------------------------------------------// -// 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/Makefile.in b/Makefile.in index a791b0a..8e4c573 100644 --- a/Makefile.in +++ b/Makefile.in @@ -30,7 +30,7 @@ CCNAME="/opt/cross-cc/bin/x86_64-elf-gcc" CC2NAME=gcc COPTIM=-O2 -CWARNS=-Wall -Wextra -Werror=implicit-function-declaration +CWARNS=-Wall -Wextra // -Werror=implicit-function-declaration CINCLUDES=-Ikaleid/include CFLAGS1=-nostdlib -ffreestanding -mcmodel=large // -std=gnu11 @@ -63,10 +63,10 @@ testing: bootloader pseudo_kern COBJDIR=$(OBJDIR)/$(COMMDIR) 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) +COMMOBJS=COBJ6(string, status, rand, memory, strtol, sprintf) COBJ4(itoa, ltoa, utoa, ultoa) COBJ4(atoi, atol, atou, atoul) COBJ3(../extras/prog, ../extras/argv, ctype) TCC=$(CC2NAME) $(COPTIM) $(CWARNS) $(CINCLUDES) -KCC=$(CC) -D_KALEID_KERNEL +KCC=$(CC) -D_OSK_SOURCE -D_KALEID_KERNEL comm-convert: COMPILE_CONVRT1(itoa) -D_NEED_ITOA @@ -80,11 +80,12 @@ comm-convert: common: comm-convert COMPILE_COMMON(rand) - COMPILE_COMMON(arith) + COMPILE_COMMON(ctype) COMPILE_COMMON(string) COMPILE_COMMON(status) COMPILE_COMMON(memory) -fno-strict-aliasing COMPILE_COMMON(strtol) + COMPILE_COMMON(sprintf) COMPILE_COMMON(../extras/prog) COMPILE_COMMON(../extras/argv) diff --git a/kaleid/crtlib/ctype.c b/kaleid/crtlib/ctype.c new file mode 100644 index 0000000..f35fcc3 --- /dev/null +++ b/kaleid/crtlib/ctype.c @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Desc: Character types // +// // +// // +// Copyright © 2018-2019 The OS/K Team // +// // +// This file is part of OS/K. // +// // +// OS/K is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License, or // +// any later version. // +// // +// OS/K is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY//without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with OS/K. If not, see . // +//----------------------------------------------------------------------------// + +#include + +#define SH(x) (1 << x) + +enum +{ + CT = SH(0), // control + PR = SH(1), // printing + GR = SH(2)|PR, // graphical + DX = SH(3)|GR, // hex digit + DG = SH(4)|DX, // decimal digit + SP = SH(5), // space + BK = SH(6)|SP, // blank + PT = SH(7)|GR, // punctuation + AL = SH(8)|GR, // alpha + UP = SH(9)|AL, // upper alpha + LW = SH(10)|AL // lower alpha +}; + +int __ctype[] = { + // ASCII ctype table + /* 0 */ CT, CT, CT, CT, CT, CT, CT, CT, CT, BK|CT, + /* 10 */ SP|CT, SP|CT, SP|CT, SP|CT, CT, CT, CT, CT, CT, CT, + /* 20 */ CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, + /* 30 */ CT, CT, BK|PR, PT, PT, PT, PT, PT, PT, PT, + /* 40 */ PT, PT, PT, PT, PT, PT, PT, PT, DG, DG, + /* 50 */ DG, DG, DG, DG, DG, DG, DG, DG, PT, PT, + /* 60 */ PT, PT, PT, PT, PT, UP|DX, UP|DX, UP|DX, UP|DX, UP|DX, + /* 70 */ UP|DX, UP, UP, UP, UP, UP, UP, UP, UP, UP, + /* 80 */ UP, UP, UP, UP, UP, UP, UP, UP, UP, UP, + /* 90 */ UP, PT, PT, PT, PT, PT, PT, LW|DX, LW|DX, LW|DX, + /* 100 */ LW|DX, LW|DX, LW|DX, LW, LW, LW, LW, LW, LW, LW, + /* 110 */ LW, LW, LW, LW, LW, LW, LW, LW, LW, LW, + /* 120 */ LW, LW, LW, PT, PT, PT, PT, CT, +}; + +static_assert(sizeof(__ctype) == 128 * sizeof(int), "ctype table - invalid size"); + +int tolower(int c) +{ + if (isupper(c)) return c + ('a' - 'A'); + return c; +} + +int toupper(int c) +{ + if (islower(c)) return c - ('a' - 'A'); + return c; +} + diff --git a/kaleid/crtlib/itoa.c b/kaleid/crtlib/itoa.c index 67572e1..95c1bd7 100644 --- a/kaleid/crtlib/itoa.c +++ b/kaleid/crtlib/itoa.c @@ -17,6 +17,7 @@ static const char digits[] = // // Integer to string in any base between 2 and 36 (included) +// Returns str // #if defined(_NEED_ITOA) diff --git a/kaleid/crtlib/sprintf.c b/kaleid/crtlib/sprintf.c index f0e5e5e..5613434 100644 --- a/kaleid/crtlib/sprintf.c +++ b/kaleid/crtlib/sprintf.c @@ -22,27 +22,34 @@ // along with OS/K. If not, see . // //----------------------------------------------------------------------------// +// +// TODO integer modifiers +// + #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 +// Standard is dumb so we won't follow it: +// 1) we return a size_t instead of int +// 2) for (v)snprintf we return the number of characters written +// instead of the number of characters that would have been written +// given large enough n // -int sprintf(char *str, const char *fmt, ...) +size_t sprintf(char *str, const char *fmt, ...) { int ret; va_list ap; - va_start(ap); + va_start(ap, fmt); ret = vsnprintf(str, SIZE_T_MAX, fmt, ap); va_end(ap); return ret; } -int vsprintf(char *str, const char *fmt, va_list ap) +size_t vsprintf(char *str, const char *fmt, va_list ap) { return vsnprintf(str, SIZE_T_MAX, fmt, ap); } @@ -51,40 +58,188 @@ int vsprintf(char *str, const char *fmt, va_list 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, ...) +size_t snprintf(char *str, size_t n, const char *fmt, ...) { int ret; va_list ap; - va_start(ap); - ret = vsnprintf(str, n, fmt, ap) + va_start(ap, fmt); + 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; +// Size of the buffer is for convertions +#define CONVBUF 4096 - // Go throught the format string - while (*fmt) { +size_t vsnprintf(char *str, size_t n, const char *fmt, va_list ap) +{ + size_t ret = 0; + bool lflag = 0, hflag = 0, hhflag = 0, altflag = 0; + + int base; + char mod; + char convbuf[CONVBUF] = { 0 }; + + char c; + int d; + uint u; + char *s; + + // For aesthetic reasons... + n--; + + // Go through the format string + while (*fmt && ret < n) { + + // Regular character if (*fmt != '%') { - // Even if we don't have any more room we still increase ret - if (ret++ < n) { - *str++ = *fmt++; - } + *str++ = *fmt++; + ret++; continue; } - switch (*fmt) { - case 'd': - default: + // Found a '%' + while (1) { + mod = *++fmt; + + if (mod == '%') { + *str++ = '%'; + ret++; + break; + } + + if (mod == '#') { + altflag = 1; + continue; + } + + if (mod == 'l' || mod == 'z' || mod == 't') { + // 'll'/'z'/'t' aliased to 'l' + lflag = 1; + continue; + } + + if (mod == 'h') { + if (hflag) hhflag = 1; + else hflag = 1; + continue; + } + + if (mod == 'c') { + c = (char)va_arg(ap, int); + *str++ = c; + ret++; + break; + } + + if (mod == 's') { + s = va_arg(ap, char *); + + while (*s && ret < n) { + *str++ = *s++; + ret++; + } + + break; + } + + if (mod == 'i') { + mod = 'd'; + goto numeric; + } + + if (mod == 'p') { + mod = 'x'; + lflag = 1; + altflag = 1; + goto numeric; + } + + if (mod == 'd' || mod == 'u' || mod == 'b' || + mod == 'o' || mod == 'x' || mod == 'X') { + + // Label to avoid some useless tests + numeric: + + if (altflag && mod != 'd' && mod != 'u') { + // #d / #u is undefined behaviour + + *str++ = '0'; + if (++ret >= n) break; + + if (mod != 'o') { + *str++ = mod; + ret++; + } + } + + // "%d" is a special snowflake, deal with it separately + if (mod == 'd') { + if (lflag) { + ltoa(va_arg(ap, long), convbuf, 10); + } + + else { + d = va_arg(ap, int); + if (hhflag) d &= 0xff; // char-ify + else if (hflag) d &= 0xffff; // short-ify + itoa(d, convbuf, 10); + } + } + + // All unsigned mods + else { + base = (mod == 'u' ? 10 : (mod == 'b' ? 2 : (mod == 'o' ? 8 : 16))); + + // Every other mod here is unsigned + if (lflag) { + ultoa(va_arg(ap, ulong), convbuf, base); + } + + else { + u = va_arg(ap, uint); + if (hhflag) u &= 0xff; // char-ify + else if (hflag) u &= 0xffff; // short-ify + utoa(u, convbuf, base); + } + + // "abcdef" => "ABCDEF" + if (mod == 'X') { + // Re-use s as an iterator for convbuf + s = convbuf; + while (*s) { + if (islower(*s)) + *s = toupper(*s); + s++; + } + } + } + + s = convbuf; + // Convertions happened, now we write into str + while (*s && ret < n) { + *str++ = *s++; + ret++; + } + + // We're done dealing with this modifier + break; + } + + // Unknown/unsupported modifier :| + *str++ = mod; break; } + + // We fallthrough here from the "while (1)" + fmt++; } - return ret; + // Null-terminate no matter what + *str = 0; + + return ret + 1; } - diff --git a/kaleid/crtlib/string.c b/kaleid/crtlib/string.c index 89ae054..71768c7 100644 --- a/kaleid/crtlib/string.c +++ b/kaleid/crtlib/string.c @@ -226,15 +226,12 @@ char *strcpy(char *restrict dest, const char *restrict src) // char *strncpy(char *restrict dest, const char *restrict src, size_t n) { - size_t it; + char *base = dest; - for (it = 0; it < n && src[it]; it++) { - dest[it] = src[it]; - } + while (n-- && (*dest++ = *src++)); + while (n--) *dest++ = 0; - while (it < n) dest[it++] = 0; - - return dest; + return base; } // @@ -242,22 +239,16 @@ 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 NOT written, not counting null-terminators +// Returns a pointer to the last character of src copied +// (In particular it points to src's null-terminator if +// and only if every character of src was successfuly copied) // -size_t strnzcpy(char *restrict dest, const char *restrict src, size_t n) +char *strnzcpy(char *restrict dest, const char *restrict src, size_t n) { - size_t it, loss; + while (n-- > 1 && (*dest = *src)) dest++, src++; + if (*src) *++dest = 0; - for (it = 0; it < n - 1 && src[it]; it++) { - dest[it] = src[it]; - } - - dest[it] = 0; - - // Compute how many bytes were not copied - for (loss = it; src[loss]; loss++); - - return loss - it; + return (char *)src; } // @@ -276,17 +267,13 @@ char *strcat(char *restrict dest, const char *restrict src) // char *strncat(char *restrict dest, const char *restrict src, size_t n) { - size_t it, off = 0; + char *base = dest; - while (dest[off]) off++; + while (*dest) dest++; + while (n-- && (*dest++ = *src++)); + while (n--) *dest++ = 0; - for (it = 0; it < n && src[it]; it++) { - dest[it+off] = src[it]; - } - - while (it++ < n) dest[it+off] = 0; - - return dest; + return base; } // @@ -294,24 +281,18 @@ char *strncat(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 NOT written, not counting null-terminators +// Returns a pointer to the last character of src copied +// (In particular it points to src's null-terminator if +// and only if every character of src was successfuly copied) // -size_t strnzcat(char *restrict dest, const char *restrict src, size_t n) +char *strnzcat(char *restrict dest, const char *restrict src, size_t n) { - size_t it, loss, off = 0; + while (*dest) dest++; - while (dest[off]) off++; + while (n-- > 1 && (*dest = *src)) dest++, src++; + if (*src) *++dest = 0; - for (it = 0; it < n - 1 && src[it]; it++) { - dest[it+off] = src[it]; - } - - dest[it+off] = 0; - - // Compute how many bytes were not copied - for (loss = it; src[loss+off]; loss++); - - return loss - it; + return (char *)src; } // diff --git a/kaleid/extras/argv.c b/kaleid/extras/argv.c index 70b1704..9af8ff2 100644 --- a/kaleid/extras/argv.c +++ b/kaleid/extras/argv.c @@ -67,7 +67,7 @@ size_t KalComputeArgVecSize(const char *argv[]) // 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 +// which is the POSIX minimum; the current ARG_MAX guarantees 16KB available // // TODO long escape sequences // get program command line if cmdLine == NULL @@ -112,6 +112,8 @@ error_t KalCmdLineToArgVecEx(const char *cmdLine, // Make sure we don't go beyond ARG_MAX bytes if (written >= ARG_MAX - (1 + sizeof(char *))) { + // Sanity check + KalAssert(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 @@ -168,7 +170,6 @@ error_t KalCmdLineToArgVecEx(const char *cmdLine, if (!quotes && !started) { quotes = *cmdLine; started = true; - continue; } @@ -176,7 +177,6 @@ error_t KalCmdLineToArgVecEx(const char *cmdLine, if (quotes == *cmdLine && ISBLANK(cmdLine[1])) { quotes = 0; started = false; - NULLTERM_AND_SAVE; continue; } diff --git a/kaleid/include/base/assert.h b/kaleid/include/base/assert.h index 9f0ca0d..a6986d2 100644 --- a/kaleid/include/base/assert.h +++ b/kaleid/include/base/assert.h @@ -100,14 +100,6 @@ noreturn void __assert_handler(const char *, const char *, int, const char *); #else -#ifndef NDEBUG -#define NDEBUG 1 -#endif - -#ifndef _NO_DEBUG -#define _NO_DEBUG 1 -#endif - #ifndef KalAssert #define KalAssert(x) ((void)0) #endif diff --git a/kaleid/include/base/bdefs.h b/kaleid/include/base/bdefs.h index 4cd4379..0229f41 100644 --- a/kaleid/include/base/bdefs.h +++ b/kaleid/include/base/bdefs.h @@ -59,6 +59,17 @@ //------------------------------------------// +#if defined(_NO_DEBUG) || defined(NDEBUG) +#ifndef NDEBUG +#define NDEBUG 1 +#endif +#ifndef _NO_DEBUG +#define _NO_DEBUG 1 +#endif +#endif + +//------------------------------------------// + #ifndef __alignof_is_defined #define __alignof_is_defined #define alignof _Alignof @@ -69,19 +80,26 @@ #define alignas _Alignas #endif +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + #ifndef __bool_true_false_are_defined #define __bool_true_false_are_defined +#ifndef __cplusplus # define bool _Bool # define true 1 # define false 0 -# ifndef TRUE -# define TRUE 1 -# endif -# ifndef FALSE -# define FALSE 0 -# endif +#else +# define bool bool +# define true true +# define false false +#endif #endif - //------------------------------------------// #ifndef _PACKED diff --git a/kaleid/include/base/crtlib.h b/kaleid/include/base/crtlib.h index 9e3ac86..04654af 100644 --- a/kaleid/include/base/crtlib.h +++ b/kaleid/include/base/crtlib.h @@ -46,13 +46,13 @@ typedef unsigned long size_t; typedef __builtin_va_list va_list; #endif -#ifndef __div_t_defined -#define __div_t_defined +#ifndef __osk_div_t_defined +#define __osk_div_t_defined typedef struct { int quot, rem; } div_t; #endif -#ifndef __ldiv_t_defined -#define __ldiv_t_defined +#ifndef __osk_ldiv_t_defined +#define __osk_ldiv_t_defined typedef struct { long quot, rem; } ldiv_t; #endif @@ -150,36 +150,36 @@ 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 *strcpy(char *restrict, const char *restrict); +char *strncpy(char *restrict, const char *restrict, size_t); +char *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 *strcat(char *restrict, const char *restrict); +char *strncat(char *restrict, const char *restrict, size_t); +char *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); +size_t sprintf(char *, const char *, ...); +size_t snprintf(char *, size_t, const char *, ...); +size_t vsprintf(char *, const char *, va_list); +size_t vsnprintf(char *, size_t, const char *, va_list); //------------------------------------------// -char *itoa(int, char *, int); -char *ltoa(long, char *, int); -char *utoa(unsigned int, char *, int); -char *ultoa(unsigned long, char *, int); +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 *); +int atoi(const char *); +long atol(const char *); +long strtol(const char *restrict, char **restrict, int); -long strtol (const char *restrict, char **restrict, int); -unsigned long strtoul(const char *restrict, char **restrict, int); +unsigned int atou(const char *); +unsigned long atoul(const char *); +unsigned long strtoul(const char *restrict, char **restrict, int); //------------------------------------------// @@ -193,26 +193,67 @@ char *strsignal(int); //------------------------------------------// +int toupper(int); +int tolower(int); + +static inline int isascii(int __c) +{ return !(__c & ~0xff); } + +//------------------------------------------// + +extern int __ctype[]; + +#define _SH(x) (1 << (x)) + +enum +{ + _CT = _SH(0), // control + _PR = _SH(1), // printing + _GR = _SH(2), // graphical + _DX = _SH(3), // hex digit + _DG = _SH(4), // decimal digit + _SP = _SH(5), // space + _BK = _SH(6), // blank + _PT = _SH(7), // punctuation + _AL = _SH(8), // alpha + _UP = _SH(9), // upper alpha + _LW = _SH(10), // lower alpha +}; + +#define DEC_CTYPE_FUNC(name, flag) \ +static inline bool name(int __c) \ +{ return isascii(__c) ? !!(__ctype[__c] & flag) : 0; } + +DEC_CTYPE_FUNC(iscntrl, _CT); +DEC_CTYPE_FUNC(isprint, _PR); +DEC_CTYPE_FUNC(isgraph, _GR); +DEC_CTYPE_FUNC(isdigit, _DG); +DEC_CTYPE_FUNC(isspace, _SP); +DEC_CTYPE_FUNC(isblank, _BK); +DEC_CTYPE_FUNC(ispunct, _PT); +DEC_CTYPE_FUNC(isalpha, _AL); +DEC_CTYPE_FUNC(isupper, _UP); +DEC_CTYPE_FUNC(islower, _LW); +DEC_CTYPE_FUNC(isxdigit, _DX); +DEC_CTYPE_FUNC(isalnum, (_AL|_DG)); + +//------------------------------------------// + #ifndef __abs_defined #define __abs_defined static inline int abs(int __x) -{ - return __x < 0 ? -__x : __x; -} +{ return __x < 0 ? -__x : __x; } #endif #ifndef __labs_defined #define __labs_defined static inline long labs(long __x) -{ - return __x < 0 ? -__x : __x; -} +{ return __x < 0 ? -__x : __x; } #endif #ifndef __div_defined #define __div_defined -static inline div_t div(int __x, int __y) -{ +static inline div_t div(int __x, int __y) { div_t __res; __res.quot = __x/__y; __res.rem = __x%__y; @@ -222,8 +263,7 @@ static inline div_t div(int __x, int __y) #ifndef __ldiv_defined #define __ldiv_defined -static inline ldiv_t ldiv(long __x, long __y) -{ +static inline ldiv_t ldiv(long __x, long __y) { ldiv_t __res; __res.quot = __x/__y; __res.rem = __x%__y; diff --git a/kaleid/include/base/masks.h b/kaleid/include/base/masks.h index 5166275..38d3ae7 100644 --- a/kaleid/include/base/masks.h +++ b/kaleid/include/base/masks.h @@ -25,6 +25,11 @@ #ifndef _KALBASE_MASKS_H #define _KALBASE_MASKS_H +// +// This file is only used for testing purposes +// It will be deleted at some point +// + //------------------------------------------// #define div_t _osk_div_t @@ -121,6 +126,27 @@ //------------------------------------------// +#define toupper _osk_toupper +#define tolower _osk_tolower + +#define isascii _osk_isascii +#define iscntrl _osk_iscntrl +#define isprint _osk_isprint +#define isgraph _osk_isgraph +#define isdigit _osk_isdigit +#define isspace _osk_isspace +#define isblank _osk_isblank +#define ispunct _osk_ispunct +#define isalpha _osk_isalpha +#define isupper _osk_isupper +#define islower _osk_islower +#define isalnum _osk_isalnum +#define isxdigit _osk_isxdigit + +#define __ctype __osk_ctype + +//------------------------------------------// + #define abs _osk_abs #define labs _osk_labs @@ -130,9 +156,6 @@ #define max _osk_max #define lmax _osk_lmax -#define __div -#define __ldiv - #define div _osk_div #define ldiv _osk_ldiv diff --git a/kaleid/include/base/types.h b/kaleid/include/base/types.h index 27d947f..0a1815a 100644 --- a/kaleid/include/base/types.h +++ b/kaleid/include/base/types.h @@ -65,6 +65,11 @@ typedef signed int wchar_t; typedef unsigned long off_t; #endif +#ifndef __time_t_defined +#define __time_t_defined +typedef unsigned long time_t; +#endif + //------------------------------------------// #ifndef __ptrdiff_t_defined @@ -99,13 +104,13 @@ typedef unsigned long uintmax_t; typedef __builtin_va_list va_list; #endif -#ifndef __div_t_defined -#define __div_t_defined +#ifndef __osk_div_t_defined +#define __osk_div_t_defined typedef struct { int quot, rem; } div_t; #endif -#ifndef __ldiv_t_defined -#define __ldiv_t_defined +#ifndef __osk_ldiv_t_defined +#define __osk_ldiv_t_defined typedef struct { long quot, rem; } ldiv_t; #endif diff --git a/kaleid/include/extras/argv.h b/kaleid/include/extras/argv.h index 32f67f4..84b2954 100644 --- a/kaleid/include/extras/argv.h +++ b/kaleid/include/extras/argv.h @@ -26,13 +26,6 @@ #include #endif -#ifdef _KALEID_KERNEL -#define FILE FILE -typedef void* FILE; -#else -#include -#endif - #ifndef _KALEXTRAS_ARGV_H #define _KALEXTRAS_ARGV_H @@ -46,6 +39,7 @@ typedef enum CmdParserReturn_t CmdParserReturn_t; typedef struct CmdOption_t CmdOption_t; typedef struct CmdDocStrings_t CmdDocStrings_t; +typedef struct CmdParserState_t CmdParserState_t; //------------------------------------------// @@ -54,7 +48,7 @@ typedef struct CmdDocStrings_t CmdDocStrings_t; // the pointed-to strings and their null-terminators // This is a 32-bit integer // -#define ARG_MAX (1 << 16) // 16 KB +#define ARG_MAX (1 << 16) // 64 KB //------------------------------------------// @@ -103,7 +97,7 @@ enum CmdParserFlags_t // Use KalGetProgName() instead of argv[0] // as program name - KALOPT_USE_ARGV0 = (1 << 5), + KALOPT_DONT_USE_ARGV0 = (1 << 5), // Call argument parser for non-options // Non-options arguments will be indicated by @@ -202,7 +196,7 @@ struct CmdDocStrings_t // // The state variable passed to the parser containing useful infos // -typedef struct { +struct CmdParserState_t { // Option we're currently parsing const CmdOption_t *option; @@ -217,14 +211,14 @@ typedef struct { bool shownHelp; bool shownVersion; - // Standard output streams - FILE *outStream; - FILE *errStream; + // Output streams (may be NULL) + /*FILE*/ void *outStream; + /*FILE*/ void *errStream; // Private, internal data; do not touch void *priv; -} CmdParserState_t; +}; // // The argument parser function @@ -242,7 +236,7 @@ int KalComputeArgCount(const char **argv); size_t KalComputeArgVecSize(const char **argv); // -// Command line to argument vector utility +// Command line to argument vector // error_t KalCmdLineToArgVecEx(const char *cmdLine, int *argcPtr, @@ -255,10 +249,9 @@ error_t KalCmdLineToArgVecEx(const char *cmdLine, error_t KalCmdLineToArgVec(const char *cmdLine, int *argcPtr, char **argv); -/* // -// Argument vector to command line utility +// Argument vector to command line // error_t KalArgVecToCmdLineEx(char *cmdLine, size_t lengthMax, @@ -285,8 +278,8 @@ error_t KalParseArgVecEx(int argc, const CmdDocStrings_t *docStrings, CmdParserFlags_t *flags, CmdParser_t *parser, - FILE *outStream, - FILE *errStream); + /*FILE*/ void *outStream, + /*FILE*/ void *errStream); // // KalParseArgVecEx(argc, argv, options, docString, stdin, stdout, parser, NULL) // @@ -297,8 +290,6 @@ error_t KalParseArgVec(int argc, CmdParserFlags_t *flags, CmdParser_t *parser); -*/ - //------------------------------------------// #ifdef __cplusplus diff --git a/kaleid/include/extras/list.h b/kaleid/include/extras/list.h index 46ce377..c8c62c6 100644 --- a/kaleid/include/extras/list.h +++ b/kaleid/include/extras/list.h @@ -52,18 +52,18 @@ typedef struct ListNode_t ListNode_t; struct ListHead_t { - Lock_t *lock; - ulong length; - ListNode_t *first; - ListNode_t *last; + Lock_t *lock; + ulong length; + ListNode_t *first; + ListNode_t *last; }; struct ListNode_t { - void *data; - ListHead_t *head; - ListNode_t *prev; - ListNode_t *next; + void *data; + ListHead_t *head; + ListNode_t *prev; + ListNode_t *next; }; //------------------------------------------// diff --git a/kaleid/include/extras/malloc.h b/kaleid/include/extras/malloc.h index 694aefc..4e2d30a 100644 --- a/kaleid/include/extras/malloc.h +++ b/kaleid/include/extras/malloc.h @@ -1,7 +1,7 @@ //----------------------------------------------------------------------------// // GNU GPL OS/K // // // -// Desc: Memory allocation function // +// Desc: Memory allocation functions // // // // // // Copyright © 2018-2019 The OS/K Team // diff --git a/kaleid/include/kaleid.h b/kaleid/include/kaleid.h index 791447c..0d953f0 100644 --- a/kaleid/include/kaleid.h +++ b/kaleid/include/kaleid.h @@ -35,12 +35,6 @@ #include #endif -#ifdef _KALEID_KERNEL -#ifndef _KALKERN_H -#include -#endif -#endif - //------------------------------------------// #endif diff --git a/kaleid/include/kalkern.h b/kaleid/include/kalkern.h deleted file mode 100644 index 6b97706..0000000 --- a/kaleid/include/kalkern.h +++ /dev/null @@ -1,56 +0,0 @@ -//----------------------------------------------------------------------------// -// GNU GPL OS/K // -// // -// Desc: Includes all Kaleid Kernel include files // -// // -// // -// Copyright © 2018-2019 The OS/K Team // -// // -// This file is part of OS/K. // -// // -// OS/K is free software: you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation, either version 3 of the License, or // -// any later version. // -// // -// OS/K is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY//without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with OS/K. If not, see . // -//----------------------------------------------------------------------------// - -#ifndef _KALBASE_H -#include -#endif - -#ifndef _KALEXT_H -#include -#endif - -//------------------------------------------// - -#ifndef _KALKERN_H -#define _KALKERN_H - -//------------------------------------------// -// Kernel headers // -//------------------------------------------// - -#ifndef _KALKERN_BASE_H -#include -#endif - -#ifndef _KALKERN_TERM_H -#include -#endif - -#ifndef _KALKERN_SCHED_H -#include -#endif - -//------------------------------------------// - -#endif diff --git a/kaleid/include/kernel/base.h b/kaleid/include/kernel/base.h index d0b70ea..507a7ce 100644 --- a/kaleid/include/kernel/base.h +++ b/kaleid/include/kernel/base.h @@ -27,7 +27,7 @@ #endif #ifdef __cplusplus -#error "Kaleid's kernel won't compile in C++ :(" +#error "Kaleid's kernel won't compile in C++" #endif #ifndef _KALKERN_BASE_H @@ -41,6 +41,7 @@ typedef struct Process_t Process_t; typedef struct Terminal_t Terminal_t; typedef struct ListHead_t ListHead_t; typedef struct ListNode_t ListNode_t; +typedef struct Processor_t Processor_t; typedef enum ProcState_t ProcState_t; typedef enum TermColor_t TermColor_t; @@ -50,37 +51,60 @@ typedef enum KernelState_t KernelState_t; // Multiprocessor misc. // //------------------------------------------// -#ifndef INITOK -#define INITOK ((unsigned int)0xCAFEBABE) -#endif - #ifndef NCPUS -#define NCPUS 4 +#define NCPUS 1 #endif -#define GetCurCPU() 0 +// Current CPU number +// Will return a CPU-local variable later +#define _GetCurCPU() 0 + +// Get Process_t structure of current CPU +#define GetCurCPU() (cpuTable[_GetCurCPU()]) + +//------------------------------------------// // -// Declare an (extern) CPU-local variable +// Holds all CPU-local variables // -#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); } +struct Processor_t +{ + // CPU number, index in CPU list + int index; -#define DECLARE_PER_CPU(_X, _Tp) \ - __DECLARE_PER_CPU(_X, _Tp, extern) + // Panic string + char panicStr[1024]; -#define LOCAL_DEC_PER_CPU(_X, _Tp) \ - __DECLARE_PER_CPU(_X, _Tp, static) + // Number of ticks since boot time + ulong ticks; -// -// Actually creates a CPU-local variable -// -#define CREATE_PER_CPU(_X, _Tp) \ - _Tp __ ## _X [NCPUS] = { (_Tp) 0 } + // Current process & thread + Process_t *process; + Thread_t *thread; + + // Need re-schedule? + bool needReSched; + + // Is preemption ON? ("PREEMPT_ON" in sched.h) + ulong preemptCount; + + // List heads for the four priority classes + ListHead_t *idlePrioProcs; + ListHead_t *reglPrioProcs; + ListHead_t *servPrioProcs; + ListHead_t *timeCritProcs; +}; + +//------------------------------------------// + +extern int cpuCount; +extern Processor_t cpuTable[NCPUS]; + +//------------------------------------------// + +#define DEC_PER_CPU(name, field, type) \ + static inline type Get##name() { return GetCurCPU().field; } \ + static inline void _Set##name(type __val) { GetCurCPU().field = __val; } //------------------------------------------// @@ -92,3 +116,4 @@ typedef enum KernelState_t KernelState_t; //------------------------------------------// #endif + diff --git a/kaleid/include/kernel/panic.h b/kaleid/include/kernel/panic.h index 0c90810..4c7607b 100644 --- a/kaleid/include/kernel/panic.h +++ b/kaleid/include/kernel/panic.h @@ -31,7 +31,9 @@ //------------------------------------------// -DECLARE_PER_CPU(PanicStr, const char *); +// Can't use the macro because panicStr is an array +static inline char *GetPanicStr(void) +{ return GetCurCPU().panicStr; } //------------------------------------------// @@ -58,7 +60,7 @@ DECLARE_PER_CPU(PanicStr, const char *); //------------------------------------------// -noreturn void StartPanic(const char *); +noreturn void StartPanic(const char *, ...); noreturn void CrashSystem(void); //------------------------------------------// diff --git a/kaleid/include/kernel/proc.h b/kaleid/include/kernel/proc.h index b591aed..e7de0b7 100644 --- a/kaleid/include/kernel/proc.h +++ b/kaleid/include/kernel/proc.h @@ -77,8 +77,8 @@ struct Process_t //------------------------------------------// -DECLARE_PER_CPU(CurProc, Process_t *); -DECLARE_PER_CPU(CurThread, Thread_t *); +DEC_PER_CPU(CurProc, process, Process_t *); +DEC_PER_CPU(CurThread, thread, Thread_t *); //------------------------------------------// diff --git a/kaleid/include/kernel/sched.h b/kaleid/include/kernel/sched.h index 5c4e2d6..27ad978 100644 --- a/kaleid/include/kernel/sched.h +++ b/kaleid/include/kernel/sched.h @@ -34,7 +34,7 @@ // // Value of the preemption count indicating that preemption is activated // -enum { PREEMPT_ON }; +enum { PREEMPT_ON = 0 }; // Time in ticks a process should be run enum @@ -57,15 +57,13 @@ extern const char *PrioClassesNames[]; //------------------------------------------// -DECLARE_PER_CPU(ReSchedFlag, bool); -DECLARE_PER_CPU(PreemptCount, ulong); +DEC_PER_CPU(ReSchedFlag, needReSched, bool); +DEC_PER_CPU(PreemptCount, preemptCount, ulong); -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[]; +DEC_PER_CPU(IdlePrioProcs, idlePrioProcs, ListHead_t *); +DEC_PER_CPU(ReglPrioProcs, reglPrioProcs, ListHead_t *); +DEC_PER_CPU(ServPrioProcs, servPrioProcs, ListHead_t *); +DEC_PER_CPU(TimeCritProcs, timeCritProcs, ListHead_t *); //------------------------------------------// diff --git a/kaleid/include/kernel/term.h b/kaleid/include/kernel/term.h index bae24c0..83d2bb2 100644 --- a/kaleid/include/kernel/term.h +++ b/kaleid/include/kernel/term.h @@ -74,6 +74,7 @@ struct Terminal_t TermColor_t fgColor; TermColor_t bgColor; + // Defined in driver error_t (*ClearTermUnlocked)(Terminal_t *); error_t (*PutOnTermUnlocked)(Terminal_t *, char); error_t (*PrintOnTermUnlocked)(Terminal_t *, const char *); @@ -87,27 +88,30 @@ error_t PutOnTerm(Terminal_t *, char); error_t PrintOnTerm(Terminal_t *, const char *); error_t ChTermColor(Terminal_t *, TermColor_t, TermColor_t); +error_t KernLog(const char *, ...); //------------------------------------------// -DECLARE_PER_CPU(_StdOut, Terminal_t *); -DECLARE_PER_CPU(_StdDbg, Terminal_t *); - -//------------------------------------------// - -#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) +extern Terminal_t *stdOut; +#define GetStdOut() (stdOut) +#define SetStdOut(x) (stdOut = (x)) //------------------------------------------// #ifndef _NO_DEBUG -# define DebugLog(...) PrintOnTerm(GetStdDbg(), __VA_ARGS__) -#else -# define DebugLog(...) ((void)0) + +extern Terminal_t *stdDbg; +#define GetStdDbg() (stdDbg) +#define SetStdDbg(x) (stdDbg = (x)) + +error_t DebugLog(const char *, ...); + +#else // _NO_DEBUG + +#define GetStdDbg() NULL +#define SetStdDbg(x) ((void)0) +#define DebugLog(fmt, ...) EOK + #endif //------------------------------------------// diff --git a/kaleid/kernel/init/init.c b/kaleid/kernel/init/init.c index cc7c438..d28a79d 100644 --- a/kaleid/kernel/init/init.c +++ b/kaleid/kernel/init/init.c @@ -1,7 +1,7 @@ //----------------------------------------------------------------------------// // GNU GPL OS/K // // // -// Desc: Kernel entry point // +// Desc: Kernel entry point // // // // // // Copyright © 2018-2019 The OS/K Team // diff --git a/kaleid/kernel/init/table.c b/kaleid/kernel/init/table.c index d753b30..273105a 100644 --- a/kaleid/kernel/init/table.c +++ b/kaleid/kernel/init/table.c @@ -24,14 +24,8 @@ #include -CREATE_PER_CPU(PanicStr, const char *); +int cpuCount = 1; +Processor_t cpuTable[NCPUS] = {0}; -CREATE_PER_CPU(_StdOut, Terminal_t *); -CREATE_PER_CPU(_StdDbg, Terminal_t *); - -CREATE_PER_CPU(CurProc, Process_t *); -CREATE_PER_CPU(CurThread, Thread_t *); - -CREATE_PER_CPU(PreemptCount, ulong); -CREATE_PER_CPU(ReSchedFlag, bool); +Terminal_t *stdOut, *stdDbg; diff --git a/kaleid/kernel/ke/panic.c b/kaleid/kernel/ke/panic.c index c71f790..3127321 100644 --- a/kaleid/kernel/ke/panic.c +++ b/kaleid/kernel/ke/panic.c @@ -37,16 +37,18 @@ noreturn void __assert_handler(const char *msg, (void)file; (void)line; (void)func; - // XXX sprintf() to create a proper panicstr - StartPanic(msg); + StartPanic("cpu%d: In function '%s', from %s line %s - assert() failed: '%s'", + _GetCurCPU(), func, file, line, msg); } // // Your best boy panic() // This is CPU local... // -noreturn void StartPanic(const char *str) +noreturn void StartPanic(const char *fmt, ...) { + va_list ap; + DisableIRQs(); if (GetCurProc()) _SetCurProc(NULL); @@ -54,19 +56,21 @@ noreturn void StartPanic(const char *str) GetStdOut()->ClearTermUnlocked(GetStdOut()); - if (str == NULL) { - str = "(no message given)"; + if (fmt == NULL) { + fmt = "(no message given)"; } if (GetPanicStr()) { - GetStdOut()->PrintOnTermUnlocked(GetStdOut(), "\nDouble panic!\n"); + GetStdOut()->PrintOnTermUnlocked(GetStdOut(), "\ndouble panic!"); HaltCPU(); } - _SetPanicStr(str); + va_start(ap, fmt); + vsnprintf(GetPanicStr(), sizeof GetPanicStr(), fmt, ap); + va_end(ap); - GetStdOut()->PrintOnTermUnlocked(GetStdOut(), "PANIC! - "); - GetStdOut()->PrintOnTermUnlocked(GetStdOut(), str); + GetStdOut()->PrintOnTermUnlocked(GetStdOut(), "\npanic!\n\n"); + GetStdOut()->PrintOnTermUnlocked(GetStdOut(), GetPanicStr()); HaltCPU(); } diff --git a/kaleid/kernel/proc/sched.c b/kaleid/kernel/proc/sched.c index 6dffd89..d8ba70d 100644 --- a/kaleid/kernel/proc/sched.c +++ b/kaleid/kernel/proc/sched.c @@ -82,7 +82,6 @@ void SchedUnlock(void) { // // The four priority classes of OS/2 // - CREATE_PER_CPU(TimeCritProcs, ListHead_t *); CREATE_PER_CPU(ServPrioProcs, ListHead_t *); CREATE_PER_CPU(ReglPrioProcs, ListHead_t *);