sprintf family, ctype, better panic, better terminals, better kernel/base.h & other stuff (#29)
This commit is contained in:
parent
bbb4931238
commit
cd0913ed13
|
@ -23,7 +23,7 @@ multiboot.pdf
|
||||||
grub.log
|
grub.log
|
||||||
Makefile.out.2
|
Makefile.out.2
|
||||||
build/bin/s**
|
build/bin/s**
|
||||||
.stylehlp
|
#.stylehlp
|
||||||
|
|
||||||
# Linker output
|
# Linker output
|
||||||
*.ilk
|
*.ilk
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
// GNU GPL OS/K //
|
// GNU GPL OS/K //
|
||||||
// //
|
// //
|
||||||
// Desc: Arithmetic functions //
|
// Desc: //
|
||||||
// //
|
// //
|
||||||
// //
|
// //
|
||||||
// Copyright © 2018-2019 The OS/K Team //
|
// Copyright © 2018-2019 The OS/K Team //
|
||||||
|
@ -22,27 +22,5 @@
|
||||||
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
|
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
// do not mask anything
|
//------------------------------------------//
|
||||||
#define _KALEID_UNMASKED
|
|
||||||
#include <kalbase.h>
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
CCNAME="/opt/cross-cc/bin/x86_64-elf-gcc"
|
CCNAME="/opt/cross-cc/bin/x86_64-elf-gcc"
|
||||||
CC2NAME=gcc
|
CC2NAME=gcc
|
||||||
COPTIM=-O2
|
COPTIM=-O2
|
||||||
CWARNS=-Wall -Wextra -Werror=implicit-function-declaration
|
CWARNS=-Wall -Wextra // -Werror=implicit-function-declaration
|
||||||
CINCLUDES=-Ikaleid/include
|
CINCLUDES=-Ikaleid/include
|
||||||
|
|
||||||
CFLAGS1=-nostdlib -ffreestanding -mcmodel=large // -std=gnu11
|
CFLAGS1=-nostdlib -ffreestanding -mcmodel=large // -std=gnu11
|
||||||
|
@ -63,10 +63,10 @@ testing: bootloader pseudo_kern
|
||||||
COBJDIR=$(OBJDIR)/$(COMMDIR)
|
COBJDIR=$(OBJDIR)/$(COMMDIR)
|
||||||
LOBJDIR=$(OBJDIR)/$(LINXDIR)
|
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)
|
TCC=$(CC2NAME) $(COPTIM) $(CWARNS) $(CINCLUDES)
|
||||||
KCC=$(CC) -D_KALEID_KERNEL
|
KCC=$(CC) -D_OSK_SOURCE -D_KALEID_KERNEL
|
||||||
|
|
||||||
comm-convert:
|
comm-convert:
|
||||||
COMPILE_CONVRT1(itoa) -D_NEED_ITOA
|
COMPILE_CONVRT1(itoa) -D_NEED_ITOA
|
||||||
|
@ -80,11 +80,12 @@ comm-convert:
|
||||||
|
|
||||||
common: comm-convert
|
common: comm-convert
|
||||||
COMPILE_COMMON(rand)
|
COMPILE_COMMON(rand)
|
||||||
COMPILE_COMMON(arith)
|
COMPILE_COMMON(ctype)
|
||||||
COMPILE_COMMON(string)
|
COMPILE_COMMON(string)
|
||||||
COMPILE_COMMON(status)
|
COMPILE_COMMON(status)
|
||||||
COMPILE_COMMON(memory) -fno-strict-aliasing
|
COMPILE_COMMON(memory) -fno-strict-aliasing
|
||||||
COMPILE_COMMON(strtol)
|
COMPILE_COMMON(strtol)
|
||||||
|
COMPILE_COMMON(sprintf)
|
||||||
COMPILE_COMMON(../extras/prog)
|
COMPILE_COMMON(../extras/prog)
|
||||||
COMPILE_COMMON(../extras/argv)
|
COMPILE_COMMON(../extras/argv)
|
||||||
|
|
||||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>. //
|
||||||
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
#include <kalbase.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ static const char digits[] =
|
||||||
|
|
||||||
//
|
//
|
||||||
// Integer to string in any base between 2 and 36 (included)
|
// Integer to string in any base between 2 and 36 (included)
|
||||||
|
// Returns str
|
||||||
//
|
//
|
||||||
#if defined(_NEED_ITOA)
|
#if defined(_NEED_ITOA)
|
||||||
|
|
||||||
|
|
|
@ -22,27 +22,34 @@
|
||||||
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
|
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO integer modifiers
|
||||||
|
//
|
||||||
|
|
||||||
#include <kalbase.h>
|
#include <kalbase.h>
|
||||||
|
|
||||||
//
|
//
|
||||||
// Format str according to fmt using ellipsed arguments
|
// Format str according to fmt using ellipsed arguments
|
||||||
//
|
//
|
||||||
// BE CAREFUL when using this
|
// Standard is dumb so we won't follow it:
|
||||||
// you need to know for sure an overflow won't happen
|
// 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;
|
int ret;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap);
|
va_start(ap, fmt);
|
||||||
ret = vsnprintf(str, SIZE_T_MAX, fmt, ap);
|
ret = vsnprintf(str, SIZE_T_MAX, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return ret;
|
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);
|
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
|
// (v)sprintf() but with a size limit: no more than n bytes are written in str
|
||||||
// Always null-terminate 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;
|
int ret;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap);
|
va_start(ap, fmt);
|
||||||
ret = vsnprintf(str, n, fmt, ap)
|
ret = vsnprintf(str, n, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
|
// Size of the buffer is for convertions
|
||||||
{
|
#define CONVBUF 4096
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
// Go throught the format string
|
size_t vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
|
||||||
while (*fmt) {
|
{
|
||||||
|
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 != '%') {
|
if (*fmt != '%') {
|
||||||
// Even if we don't have any more room we still increase ret
|
|
||||||
if (ret++ < n) {
|
|
||||||
*str++ = *fmt++;
|
*str++ = *fmt++;
|
||||||
}
|
ret++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (*fmt) {
|
// Found a '%'
|
||||||
case 'd':
|
while (1) {
|
||||||
default:
|
mod = *++fmt;
|
||||||
|
|
||||||
|
if (mod == '%') {
|
||||||
|
*str++ = '%';
|
||||||
|
ret++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mod == '#') {
|
||||||
|
altflag = 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Null-terminate no matter what
|
||||||
|
*str = 0;
|
||||||
|
|
||||||
|
return ret + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
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++) {
|
while (n-- && (*dest++ = *src++));
|
||||||
dest[it] = src[it];
|
while (n--) *dest++ = 0;
|
||||||
}
|
|
||||||
|
|
||||||
while (it < n) dest[it++] = 0;
|
return base;
|
||||||
|
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -242,22 +239,16 @@ char *strncpy(char *restrict dest, const char *restrict src, size_t n)
|
||||||
// Always null-terminates dest, but doesn't fill
|
// Always null-terminates dest, but doesn't fill
|
||||||
// dest's contents past the null-terminator
|
// 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++) {
|
return (char *)src;
|
||||||
dest[it] = src[it];
|
|
||||||
}
|
|
||||||
|
|
||||||
dest[it] = 0;
|
|
||||||
|
|
||||||
// Compute how many bytes were not copied
|
|
||||||
for (loss = it; src[loss]; loss++);
|
|
||||||
|
|
||||||
return loss - it;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -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)
|
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++) {
|
return base;
|
||||||
dest[it+off] = src[it];
|
|
||||||
}
|
|
||||||
|
|
||||||
while (it++ < n) dest[it+off] = 0;
|
|
||||||
|
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -294,24 +281,18 @@ char *strncat(char *restrict dest, const char *restrict src, size_t n)
|
||||||
// Always null-terminates dest, but doesn't fill
|
// Always null-terminates dest, but doesn't fill
|
||||||
// dest's contents past the null-terminator
|
// 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++) {
|
return (char *)src;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -67,7 +67,7 @@ size_t KalComputeArgVecSize(const char *argv[])
|
||||||
// ARG_MAX bytes are available
|
// ARG_MAX bytes are available
|
||||||
//
|
//
|
||||||
// That available space, however, remains strictly higher than 4KB,
|
// 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
|
// TODO long escape sequences
|
||||||
// get program command line if cmdLine == NULL
|
// 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
|
// Make sure we don't go beyond ARG_MAX bytes
|
||||||
if (written >= ARG_MAX - (1 + sizeof(char *))) {
|
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
|
// 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
|
// 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) {
|
if (!quotes && !started) {
|
||||||
quotes = *cmdLine;
|
quotes = *cmdLine;
|
||||||
started = true;
|
started = true;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +177,6 @@ error_t KalCmdLineToArgVecEx(const char *cmdLine,
|
||||||
if (quotes == *cmdLine && ISBLANK(cmdLine[1])) {
|
if (quotes == *cmdLine && ISBLANK(cmdLine[1])) {
|
||||||
quotes = 0;
|
quotes = 0;
|
||||||
started = false;
|
started = false;
|
||||||
|
|
||||||
NULLTERM_AND_SAVE;
|
NULLTERM_AND_SAVE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,14 +100,6 @@ noreturn void __assert_handler(const char *, const char *, int, const char *);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
#define NDEBUG 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _NO_DEBUG
|
|
||||||
#define _NO_DEBUG 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef KalAssert
|
#ifndef KalAssert
|
||||||
#define KalAssert(x) ((void)0)
|
#define KalAssert(x) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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
|
#ifndef __alignof_is_defined
|
||||||
#define __alignof_is_defined
|
#define __alignof_is_defined
|
||||||
#define alignof _Alignof
|
#define alignof _Alignof
|
||||||
|
@ -69,19 +80,26 @@
|
||||||
#define alignas _Alignas
|
#define alignas _Alignas
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __bool_true_false_are_defined
|
|
||||||
#define __bool_true_false_are_defined
|
|
||||||
# define bool _Bool
|
|
||||||
# define true 1
|
|
||||||
# define false 0
|
|
||||||
#ifndef TRUE
|
#ifndef TRUE
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef FALSE
|
#ifndef FALSE
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#ifndef __bool_true_false_are_defined
|
||||||
|
#define __bool_true_false_are_defined
|
||||||
|
#ifndef __cplusplus
|
||||||
|
# define bool _Bool
|
||||||
|
# define true 1
|
||||||
|
# define false 0
|
||||||
|
#else
|
||||||
|
# define bool bool
|
||||||
|
# define true true
|
||||||
|
# define false false
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
#ifndef _PACKED
|
#ifndef _PACKED
|
||||||
|
|
|
@ -46,13 +46,13 @@ typedef unsigned long size_t;
|
||||||
typedef __builtin_va_list va_list;
|
typedef __builtin_va_list va_list;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __div_t_defined
|
#ifndef __osk_div_t_defined
|
||||||
#define __div_t_defined
|
#define __osk_div_t_defined
|
||||||
typedef struct { int quot, rem; } div_t;
|
typedef struct { int quot, rem; } div_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __ldiv_t_defined
|
#ifndef __osk_ldiv_t_defined
|
||||||
#define __ldiv_t_defined
|
#define __osk_ldiv_t_defined
|
||||||
typedef struct { long quot, rem; } ldiv_t;
|
typedef struct { long quot, rem; } ldiv_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -152,19 +152,19 @@ char *strtok_r(char *restrict, const char *restrict, char **restrict);
|
||||||
|
|
||||||
char *strcpy(char *restrict, const char *restrict);
|
char *strcpy(char *restrict, const char *restrict);
|
||||||
char *strncpy(char *restrict, const char *restrict, size_t);
|
char *strncpy(char *restrict, const char *restrict, size_t);
|
||||||
size_t strnzcpy(char *restrict, const char *restrict, size_t);
|
char *strnzcpy(char *restrict, const char *restrict, size_t);
|
||||||
|
|
||||||
char *strcat(char *restrict, const char *restrict);
|
char *strcat(char *restrict, const char *restrict);
|
||||||
char *strncat(char *restrict, const char *restrict, size_t);
|
char *strncat(char *restrict, const char *restrict, size_t);
|
||||||
size_t strnzcat(char *restrict, const char *restrict, size_t);
|
char *strnzcat(char *restrict, const char *restrict, size_t);
|
||||||
|
|
||||||
char *strrev(char *restrict, const char *restrict);
|
char *strrev(char *restrict, const char *restrict);
|
||||||
char *strrev2(char *);
|
char *strrev2(char *);
|
||||||
|
|
||||||
int sprintf(char *, const char *, ...);
|
size_t sprintf(char *, const char *, ...);
|
||||||
int snprintf(char *, size_t, const char *, ...);
|
size_t snprintf(char *, size_t, const char *, ...);
|
||||||
int vsprintf(char *, const char *, va_list);
|
size_t vsprintf(char *, const char *, va_list);
|
||||||
int vsnprintf(char *, size_t, const char *, va_list);
|
size_t vsnprintf(char *, size_t, const char *, va_list);
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
|
@ -175,10 +175,10 @@ char *ultoa(unsigned long, char *, int);
|
||||||
|
|
||||||
int atoi(const char *);
|
int atoi(const char *);
|
||||||
long atol(const char *);
|
long atol(const char *);
|
||||||
|
long strtol(const char *restrict, char **restrict, int);
|
||||||
|
|
||||||
unsigned int atou(const char *);
|
unsigned int atou(const char *);
|
||||||
unsigned long atoul(const char *);
|
unsigned long atoul(const char *);
|
||||||
|
|
||||||
long strtol (const char *restrict, char **restrict, int);
|
|
||||||
unsigned long strtoul(const char *restrict, char **restrict, int);
|
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
|
#ifndef __abs_defined
|
||||||
#define __abs_defined
|
#define __abs_defined
|
||||||
static inline int abs(int __x)
|
static inline int abs(int __x)
|
||||||
{
|
{ return __x < 0 ? -__x : __x; }
|
||||||
return __x < 0 ? -__x : __x;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __labs_defined
|
#ifndef __labs_defined
|
||||||
#define __labs_defined
|
#define __labs_defined
|
||||||
static inline long labs(long __x)
|
static inline long labs(long __x)
|
||||||
{
|
{ return __x < 0 ? -__x : __x; }
|
||||||
return __x < 0 ? -__x : __x;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __div_defined
|
#ifndef __div_defined
|
||||||
#define __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;
|
div_t __res;
|
||||||
__res.quot = __x/__y;
|
__res.quot = __x/__y;
|
||||||
__res.rem = __x%__y;
|
__res.rem = __x%__y;
|
||||||
|
@ -222,8 +263,7 @@ static inline div_t div(int __x, int __y)
|
||||||
|
|
||||||
#ifndef __ldiv_defined
|
#ifndef __ldiv_defined
|
||||||
#define __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;
|
ldiv_t __res;
|
||||||
__res.quot = __x/__y;
|
__res.quot = __x/__y;
|
||||||
__res.rem = __x%__y;
|
__res.rem = __x%__y;
|
||||||
|
|
|
@ -25,6 +25,11 @@
|
||||||
#ifndef _KALBASE_MASKS_H
|
#ifndef _KALBASE_MASKS_H
|
||||||
#define _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
|
#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 abs _osk_abs
|
||||||
#define labs _osk_labs
|
#define labs _osk_labs
|
||||||
|
|
||||||
|
@ -130,9 +156,6 @@
|
||||||
#define max _osk_max
|
#define max _osk_max
|
||||||
#define lmax _osk_lmax
|
#define lmax _osk_lmax
|
||||||
|
|
||||||
#define __div
|
|
||||||
#define __ldiv
|
|
||||||
|
|
||||||
#define div _osk_div
|
#define div _osk_div
|
||||||
#define ldiv _osk_ldiv
|
#define ldiv _osk_ldiv
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,11 @@ typedef signed int wchar_t;
|
||||||
typedef unsigned long off_t;
|
typedef unsigned long off_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __time_t_defined
|
||||||
|
#define __time_t_defined
|
||||||
|
typedef unsigned long time_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
#ifndef __ptrdiff_t_defined
|
#ifndef __ptrdiff_t_defined
|
||||||
|
@ -99,13 +104,13 @@ typedef unsigned long uintmax_t;
|
||||||
typedef __builtin_va_list va_list;
|
typedef __builtin_va_list va_list;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __div_t_defined
|
#ifndef __osk_div_t_defined
|
||||||
#define __div_t_defined
|
#define __osk_div_t_defined
|
||||||
typedef struct { int quot, rem; } div_t;
|
typedef struct { int quot, rem; } div_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __ldiv_t_defined
|
#ifndef __osk_ldiv_t_defined
|
||||||
#define __ldiv_t_defined
|
#define __osk_ldiv_t_defined
|
||||||
typedef struct { long quot, rem; } ldiv_t;
|
typedef struct { long quot, rem; } ldiv_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,6 @@
|
||||||
#include <kalbase.h>
|
#include <kalbase.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _KALEID_KERNEL
|
|
||||||
#define FILE FILE
|
|
||||||
typedef void* FILE;
|
|
||||||
#else
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _KALEXTRAS_ARGV_H
|
#ifndef _KALEXTRAS_ARGV_H
|
||||||
#define _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 CmdOption_t CmdOption_t;
|
||||||
typedef struct CmdDocStrings_t CmdDocStrings_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
|
// the pointed-to strings and their null-terminators
|
||||||
// This is a 32-bit integer
|
// 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]
|
// Use KalGetProgName() instead of argv[0]
|
||||||
// as program name
|
// as program name
|
||||||
KALOPT_USE_ARGV0 = (1 << 5),
|
KALOPT_DONT_USE_ARGV0 = (1 << 5),
|
||||||
|
|
||||||
// Call argument parser for non-options
|
// Call argument parser for non-options
|
||||||
// Non-options arguments will be indicated by
|
// Non-options arguments will be indicated by
|
||||||
|
@ -202,7 +196,7 @@ struct CmdDocStrings_t
|
||||||
//
|
//
|
||||||
// The state variable passed to the parser containing useful infos
|
// The state variable passed to the parser containing useful infos
|
||||||
//
|
//
|
||||||
typedef struct {
|
struct CmdParserState_t {
|
||||||
|
|
||||||
// Option we're currently parsing
|
// Option we're currently parsing
|
||||||
const CmdOption_t *option;
|
const CmdOption_t *option;
|
||||||
|
@ -217,14 +211,14 @@ typedef struct {
|
||||||
bool shownHelp;
|
bool shownHelp;
|
||||||
bool shownVersion;
|
bool shownVersion;
|
||||||
|
|
||||||
// Standard output streams
|
// Output streams (may be NULL)
|
||||||
FILE *outStream;
|
/*FILE*/ void *outStream;
|
||||||
FILE *errStream;
|
/*FILE*/ void *errStream;
|
||||||
|
|
||||||
// Private, internal data; do not touch
|
// Private, internal data; do not touch
|
||||||
void *priv;
|
void *priv;
|
||||||
|
|
||||||
} CmdParserState_t;
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// The argument parser function
|
// The argument parser function
|
||||||
|
@ -242,7 +236,7 @@ int KalComputeArgCount(const char **argv);
|
||||||
size_t KalComputeArgVecSize(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,
|
error_t KalCmdLineToArgVecEx(const char *cmdLine,
|
||||||
int *argcPtr,
|
int *argcPtr,
|
||||||
|
@ -255,10 +249,9 @@ error_t KalCmdLineToArgVecEx(const char *cmdLine,
|
||||||
error_t KalCmdLineToArgVec(const char *cmdLine,
|
error_t KalCmdLineToArgVec(const char *cmdLine,
|
||||||
int *argcPtr,
|
int *argcPtr,
|
||||||
char **argv);
|
char **argv);
|
||||||
/*
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Argument vector to command line utility
|
// Argument vector to command line
|
||||||
//
|
//
|
||||||
error_t KalArgVecToCmdLineEx(char *cmdLine,
|
error_t KalArgVecToCmdLineEx(char *cmdLine,
|
||||||
size_t lengthMax,
|
size_t lengthMax,
|
||||||
|
@ -285,8 +278,8 @@ error_t KalParseArgVecEx(int argc,
|
||||||
const CmdDocStrings_t *docStrings,
|
const CmdDocStrings_t *docStrings,
|
||||||
CmdParserFlags_t *flags,
|
CmdParserFlags_t *flags,
|
||||||
CmdParser_t *parser,
|
CmdParser_t *parser,
|
||||||
FILE *outStream,
|
/*FILE*/ void *outStream,
|
||||||
FILE *errStream);
|
/*FILE*/ void *errStream);
|
||||||
//
|
//
|
||||||
// KalParseArgVecEx(argc, argv, options, docString, stdin, stdout, parser, NULL)
|
// KalParseArgVecEx(argc, argv, options, docString, stdin, stdout, parser, NULL)
|
||||||
//
|
//
|
||||||
|
@ -297,8 +290,6 @@ error_t KalParseArgVec(int argc,
|
||||||
CmdParserFlags_t *flags,
|
CmdParserFlags_t *flags,
|
||||||
CmdParser_t *parser);
|
CmdParser_t *parser);
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
// GNU GPL OS/K //
|
// GNU GPL OS/K //
|
||||||
// //
|
// //
|
||||||
// Desc: Memory allocation function //
|
// Desc: Memory allocation functions //
|
||||||
// //
|
// //
|
||||||
// //
|
// //
|
||||||
// Copyright © 2018-2019 The OS/K Team //
|
// Copyright © 2018-2019 The OS/K Team //
|
||||||
|
|
|
@ -35,12 +35,6 @@
|
||||||
#include <kalext.h>
|
#include <kalext.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _KALEID_KERNEL
|
|
||||||
#ifndef _KALKERN_H
|
|
||||||
#include <kalkern.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>. //
|
|
||||||
//----------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
#ifndef _KALBASE_H
|
|
||||||
#include <kalbase.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _KALEXT_H
|
|
||||||
#include <kalext.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------//
|
|
||||||
|
|
||||||
#ifndef _KALKERN_H
|
|
||||||
#define _KALKERN_H
|
|
||||||
|
|
||||||
//------------------------------------------//
|
|
||||||
// Kernel headers //
|
|
||||||
//------------------------------------------//
|
|
||||||
|
|
||||||
#ifndef _KALKERN_BASE_H
|
|
||||||
#include <kernel/base.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _KALKERN_TERM_H
|
|
||||||
#include <kernel/term.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _KALKERN_SCHED_H
|
|
||||||
#include <kernel/sched.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------//
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -27,7 +27,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#error "Kaleid's kernel won't compile in C++ :("
|
#error "Kaleid's kernel won't compile in C++"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _KALKERN_BASE_H
|
#ifndef _KALKERN_BASE_H
|
||||||
|
@ -41,6 +41,7 @@ typedef struct Process_t Process_t;
|
||||||
typedef struct Terminal_t Terminal_t;
|
typedef struct Terminal_t Terminal_t;
|
||||||
typedef struct ListHead_t ListHead_t;
|
typedef struct ListHead_t ListHead_t;
|
||||||
typedef struct ListNode_t ListNode_t;
|
typedef struct ListNode_t ListNode_t;
|
||||||
|
typedef struct Processor_t Processor_t;
|
||||||
|
|
||||||
typedef enum ProcState_t ProcState_t;
|
typedef enum ProcState_t ProcState_t;
|
||||||
typedef enum TermColor_t TermColor_t;
|
typedef enum TermColor_t TermColor_t;
|
||||||
|
@ -50,37 +51,60 @@ typedef enum KernelState_t KernelState_t;
|
||||||
// Multiprocessor misc. //
|
// Multiprocessor misc. //
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
#ifndef INITOK
|
|
||||||
#define INITOK ((unsigned int)0xCAFEBABE)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NCPUS
|
#ifndef NCPUS
|
||||||
#define NCPUS 4
|
#define NCPUS 1
|
||||||
#endif
|
#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) \
|
struct Processor_t
|
||||||
_Qual _Tp __ ## _X [NCPUS]; \
|
{
|
||||||
static inline _Tp Get ## _X (void) \
|
// CPU number, index in CPU list
|
||||||
{ return __ ## _X [GetCurCPU()]; } \
|
int index;
|
||||||
static inline void _Set ## _X (_Tp _Y) \
|
|
||||||
{ (__ ## _X [GetCurCPU()] = _Y); }
|
|
||||||
|
|
||||||
#define DECLARE_PER_CPU(_X, _Tp) \
|
// Panic string
|
||||||
__DECLARE_PER_CPU(_X, _Tp, extern)
|
char panicStr[1024];
|
||||||
|
|
||||||
#define LOCAL_DEC_PER_CPU(_X, _Tp) \
|
// Number of ticks since boot time
|
||||||
__DECLARE_PER_CPU(_X, _Tp, static)
|
ulong ticks;
|
||||||
|
|
||||||
//
|
// Current process & thread
|
||||||
// Actually creates a CPU-local variable
|
Process_t *process;
|
||||||
//
|
Thread_t *thread;
|
||||||
#define CREATE_PER_CPU(_X, _Tp) \
|
|
||||||
_Tp __ ## _X [NCPUS] = { (_Tp) 0 }
|
// 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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -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);
|
noreturn void CrashSystem(void);
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
|
@ -77,8 +77,8 @@ struct Process_t
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
DECLARE_PER_CPU(CurProc, Process_t *);
|
DEC_PER_CPU(CurProc, process, Process_t *);
|
||||||
DECLARE_PER_CPU(CurThread, Thread_t *);
|
DEC_PER_CPU(CurThread, thread, Thread_t *);
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
//
|
//
|
||||||
// Value of the preemption count indicating that preemption is activated
|
// 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
|
// Time in ticks a process should be run
|
||||||
enum
|
enum
|
||||||
|
@ -57,15 +57,13 @@ extern const char *PrioClassesNames[];
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
DECLARE_PER_CPU(ReSchedFlag, bool);
|
DEC_PER_CPU(ReSchedFlag, needReSched, bool);
|
||||||
DECLARE_PER_CPU(PreemptCount, ulong);
|
DEC_PER_CPU(PreemptCount, preemptCount, ulong);
|
||||||
|
|
||||||
DECLARE_PER_CPU(IdlePrioProcs, ListHead_t *);
|
DEC_PER_CPU(IdlePrioProcs, idlePrioProcs, ListHead_t *);
|
||||||
DECLARE_PER_CPU(ReglPrioProcs, ListHead_t *);
|
DEC_PER_CPU(ReglPrioProcs, reglPrioProcs, ListHead_t *);
|
||||||
DECLARE_PER_CPU(ServPrioProcs, ListHead_t *);
|
DEC_PER_CPU(ServPrioProcs, servPrioProcs, ListHead_t *);
|
||||||
DECLARE_PER_CPU(TimeCritProcs, ListHead_t *);
|
DEC_PER_CPU(TimeCritProcs, timeCritProcs, ListHead_t *);
|
||||||
|
|
||||||
extern const char *PrioClassesNames[];
|
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@ struct Terminal_t
|
||||||
TermColor_t fgColor;
|
TermColor_t fgColor;
|
||||||
TermColor_t bgColor;
|
TermColor_t bgColor;
|
||||||
|
|
||||||
|
// Defined in driver
|
||||||
error_t (*ClearTermUnlocked)(Terminal_t *);
|
error_t (*ClearTermUnlocked)(Terminal_t *);
|
||||||
error_t (*PutOnTermUnlocked)(Terminal_t *, char);
|
error_t (*PutOnTermUnlocked)(Terminal_t *, char);
|
||||||
error_t (*PrintOnTermUnlocked)(Terminal_t *, const 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 PrintOnTerm(Terminal_t *, const char *);
|
||||||
error_t ChTermColor(Terminal_t *, TermColor_t, TermColor_t);
|
error_t ChTermColor(Terminal_t *, TermColor_t, TermColor_t);
|
||||||
|
|
||||||
|
error_t KernLog(const char *, ...);
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
DECLARE_PER_CPU(_StdOut, Terminal_t *);
|
extern Terminal_t *stdOut;
|
||||||
DECLARE_PER_CPU(_StdDbg, Terminal_t *);
|
#define GetStdOut() (stdOut)
|
||||||
|
#define SetStdOut(x) (stdOut = (x))
|
||||||
//------------------------------------------//
|
|
||||||
|
|
||||||
#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)
|
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
#ifndef _NO_DEBUG
|
#ifndef _NO_DEBUG
|
||||||
# define DebugLog(...) PrintOnTerm(GetStdDbg(), __VA_ARGS__)
|
|
||||||
#else
|
extern Terminal_t *stdDbg;
|
||||||
# define DebugLog(...) ((void)0)
|
#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
|
#endif
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
|
@ -24,14 +24,8 @@
|
||||||
|
|
||||||
#include <kernel/base.h>
|
#include <kernel/base.h>
|
||||||
|
|
||||||
CREATE_PER_CPU(PanicStr, const char *);
|
int cpuCount = 1;
|
||||||
|
Processor_t cpuTable[NCPUS] = {0};
|
||||||
|
|
||||||
CREATE_PER_CPU(_StdOut, Terminal_t *);
|
Terminal_t *stdOut, *stdDbg;
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
|
@ -37,16 +37,18 @@ noreturn void __assert_handler(const char *msg,
|
||||||
|
|
||||||
(void)file; (void)line; (void)func;
|
(void)file; (void)line; (void)func;
|
||||||
|
|
||||||
// XXX sprintf() to create a proper panicstr
|
StartPanic("cpu%d: In function '%s', from %s line %s - assert() failed: '%s'",
|
||||||
StartPanic(msg);
|
_GetCurCPU(), func, file, line, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Your best boy panic()
|
// Your best boy panic()
|
||||||
// This is CPU local...
|
// This is CPU local...
|
||||||
//
|
//
|
||||||
noreturn void StartPanic(const char *str)
|
noreturn void StartPanic(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
DisableIRQs();
|
DisableIRQs();
|
||||||
|
|
||||||
if (GetCurProc()) _SetCurProc(NULL);
|
if (GetCurProc()) _SetCurProc(NULL);
|
||||||
|
@ -54,19 +56,21 @@ noreturn void StartPanic(const char *str)
|
||||||
|
|
||||||
GetStdOut()->ClearTermUnlocked(GetStdOut());
|
GetStdOut()->ClearTermUnlocked(GetStdOut());
|
||||||
|
|
||||||
if (str == NULL) {
|
if (fmt == NULL) {
|
||||||
str = "(no message given)";
|
fmt = "(no message given)";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetPanicStr()) {
|
if (GetPanicStr()) {
|
||||||
GetStdOut()->PrintOnTermUnlocked(GetStdOut(), "\nDouble panic!\n");
|
GetStdOut()->PrintOnTermUnlocked(GetStdOut(), "\ndouble panic!");
|
||||||
HaltCPU();
|
HaltCPU();
|
||||||
}
|
}
|
||||||
|
|
||||||
_SetPanicStr(str);
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(GetPanicStr(), sizeof GetPanicStr(), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
GetStdOut()->PrintOnTermUnlocked(GetStdOut(), "PANIC! - ");
|
GetStdOut()->PrintOnTermUnlocked(GetStdOut(), "\npanic!\n\n");
|
||||||
GetStdOut()->PrintOnTermUnlocked(GetStdOut(), str);
|
GetStdOut()->PrintOnTermUnlocked(GetStdOut(), GetPanicStr());
|
||||||
|
|
||||||
HaltCPU();
|
HaltCPU();
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,6 @@ void SchedUnlock(void) {
|
||||||
//
|
//
|
||||||
// The four priority classes of OS/2
|
// The four priority classes of OS/2
|
||||||
//
|
//
|
||||||
|
|
||||||
CREATE_PER_CPU(TimeCritProcs, ListHead_t *);
|
CREATE_PER_CPU(TimeCritProcs, ListHead_t *);
|
||||||
CREATE_PER_CPU(ServPrioProcs, ListHead_t *);
|
CREATE_PER_CPU(ServPrioProcs, ListHead_t *);
|
||||||
CREATE_PER_CPU(ReglPrioProcs, ListHead_t *);
|
CREATE_PER_CPU(ReglPrioProcs, ListHead_t *);
|
||||||
|
|
Loading…
Reference in New Issue