From f6ea17d9e07727b1f144d6f397194bc0ed15ef3d Mon Sep 17 00:00:00 2001 From: Julian Barathieu Date: Tue, 25 Dec 2018 19:09:58 +0100 Subject: [PATCH] Expanded standard library --- src/Makefile | 51 +++++++++++----------- src/kaleid/common/assert.h | 27 +++++++----- src/kaleid/common/atomic.h | 4 ++ src/kaleid/common/common.h | 39 +++++++++++------ src/kaleid/common/convert.h | 24 +++++++++++ src/kaleid/common/lib/convert.c | 52 +++++++++++++++++++++++ src/kaleid/common/lib/memory.c | 11 +++++ src/kaleid/common/lib/sprintf.c | 75 +++++++++++++++++++++++++++++++++ src/kaleid/common/lib/string.c | 30 ++++++++++++- src/kaleid/common/memory.h | 18 ++++++++ src/kaleid/common/status.h | 13 ++++-- src/kaleid/common/string.h | 22 ++++++++++ src/kaleid/common/types.h | 38 +++++++++++------ src/kaleid/kernel/init.c | 4 ++ src/kaleid/kernel/init.h | 2 - src/kaleid/linux/test-common.c | 45 ++++++++++++++++++++ 16 files changed, 384 insertions(+), 71 deletions(-) create mode 100644 src/kaleid/common/convert.h create mode 100644 src/kaleid/common/lib/convert.c create mode 100644 src/kaleid/common/lib/memory.c create mode 100644 src/kaleid/common/lib/sprintf.c create mode 100644 src/kaleid/common/memory.h create mode 100644 src/kaleid/linux/test-common.c diff --git a/src/Makefile b/src/Makefile index 4c61f15..79c8836 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,13 +8,15 @@ #----------------------------------------------------------------------------# CCNAME="/opt/cross-cc/bin/x86_64-elf-gcc" +CC2NAME=gcc # compiler for testing CLDSCR=-T kernel.ld CWARNS= -pedantic -Wall -Wextra -Werror CFLAGS=-nostdlib -ffreestanding -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -CDEFINES=-D_KALEID_KERNEL CINCLUDES=-I./kaleid +CDEFINES= -CC=$(CCNAME) $(CWARNS) $(CLDSCR) $(CFLAGS) $(CDEFINES) $(CINCLUDES) +CC=$(CCNAME) $(CWARNS) $(CFLAGS) $(CDEFINES) $(CINCLUDES) +KCC=$(CC) -D_KALEID_KERNEL ASM=nasm ASMFLAGS= @@ -27,6 +29,7 @@ BOOTDIR=boot COMMDIR=kaleid/common KERNDIR=kaleid/kernel SYSTDIR=kaleid/system +LINXDIR=kaleid/linux all: bootloader @@ -53,44 +56,40 @@ testing: bootloader pseudo_kern # COMMON MAKEFILE COBJDIR=$(OBJDIR)/$(COMMDIR) +LOBJDIR=$(OBJDIR)/$(LINXDIR) COMMDEPS=$(COMMDIR)/common.h $(COMMDIR)/assert.h $(COMMDIR)/atomic.h $(COMMDIR)/config.h \ $(COMMDIR)/status.h -COBJECTS=$(COBJDIR)/lib/string.o $(COBJDIR)/lib/status.o +COMMOBJS=$(COBJDIR)/lib/string.o $(COBJDIR)/lib/status.o -common: common.lib.string.c common.lib.status.c +common: $(COMMDEPS) $(COMMDIR)/lib/string.c $(COMMDIR)/lib/status.c + $(KCC) -c $(COMMDIR)/lib/string.c -o $(COBJDIR)/lib/string.o + $(KCC) -c $(COMMDIR)/lib/status.c -o $(COBJDIR)/lib/status.o -common.lib.string.c: $(COMMDIR)/lib/string.c $(COMMDEPS) - $(CC) -c $(COMMDIR)/lib/string.c -o $(COBJDIR)/lib/string.o +CCC=$(CC2NAME) $(CWARNS) $(CDEFINES) $(CINCLUDES) -common.lib.status.c: $(COMMDIR)/lib/status.c $(COMMDEPS) - $(CC) -c $(COMMDIR)/lib/status.c -o $(COBJDIR)/lib/status.o +common-test: + $(CCC) -c $(COMMDIR)/lib/string.c -o $(COBJDIR)/lib/string.o + $(CCC) -c $(COMMDIR)/lib/status.c -o $(COBJDIR)/lib/status.o + $(CCC) -c $(LINXDIR)/test-common.c -o $(LOBJDIR)/test-common.o + $(CCC) $(COMMOBJS) $(LOBJDIR)/test-common.o -o $(BINDIR)/kaleid-common.elf #----------------------------------------------------------------------------# # KERNEL MAKEFILE KOBJDIR=$(OBJDIR)/$(KERNDIR) -KERNDEPS=$(COMMDEPS) $(KERNDIR)/init.h $(KERNDIR)/io/terminal.h $(KERNDIR)/io/ports.h $(KERNDIR)/ke/panic.h +KERNDEPS=common $(KERNDIR)/init.h $(KERNDIR)/io/terminal.h $(KERNDIR)/io/ports.h $(KERNDIR)/ke/panic.h +KERNSRCS=$(KERNDIR)/init.c $(KERNDIR)/ke/panic.c $(KERNDIR)/io/ports.c $(KERNDIR)/io/terminal.c +KERNOBJS=$(KOBJDIR)/init.o $(KOBJDIR)/ke/panic.o $(KOBJDIR)/io/ports.o $(KOBJDIR)/io/terminal.o -kernel: common kernel.io.terminal.c kernel.init.c kernel.io.ports.c kernel.ke.panic.c - $(CC) -o $(BINDIR)/kaleid-kernel.elf \ - $(COBJECTS) $(KOBJDIR)/init.o $(KOBJDIR)/ke/panic.o \ - $(KOBJDIR)/io/terminal.o $(KOBJDIR)/io/ports.o - - -kernel.init.c: $(KERNDIR)/init.c $(KERNDEPS) - $(CC) -c $(KERNDIR)/init.c -o $(KOBJDIR)/init.o - -kernel.io.ports.c: $(KERNDIR)/io/ports.c $(KERNDEPS) - $(CC) -c $(KERNDIR)/io/ports.c -o $(KOBJDIR)/io/ports.o - -kernel.io.terminal.c: $(KERNDIR)/io/terminal.c $(KERNDEPS) - $(CC) -c $(KERNDIR)/io/terminal.c -o $(KOBJDIR)/io/terminal.o - -kernel.ke.panic.c: $(KERNDIR)/ke/panic.c $(KERNDEPS) - $(CC) -c $(KERNDIR)/ke/panic.c -o $(KOBJDIR)/ke/panic.o +kernel: common $(KERNSRCS) + $(KCC) -c $(KERNDIR)/init.c -o $(KOBJDIR)/init.o + $(KCC) -c $(KERNDIR)/ke/panic.c -o $(KOBJDIR)/ke/panic.o + $(KCC) -c $(KERNDIR)/io/ports.c -o $(KOBJDIR)/io/ports.o + $(KCC) -c $(KERNDIR)/io/terminal.c -o $(KOBJDIR)/io/terminal.o + $(KCC) $(CLDSCR) $(COMMOBJS) $(KERNOBJS) -o $(BINDIR)/kaleid-kernel.elf #----------------------------------------------------------------------------# diff --git a/src/kaleid/common/assert.h b/src/kaleid/common/assert.h index 98aadcc..da80ace 100644 --- a/src/kaleid/common/assert.h +++ b/src/kaleid/common/assert.h @@ -10,19 +10,18 @@ #ifndef _KALCOMM_ASSERT_H #define _KALCOMM_ASSERT_H +#ifndef _KALCOMM_COMMON_H +#error "don't include common/types.h without common/common.h" +#endif + +#ifdef _OSK_SOURCE + #if !defined(_NO_DEBUG) && !defined(NDEBUG) // uses panic() in kernel, abort() in system noreturn void ___assert_handler(const char *, const char *, int, const char *); -#define assert(x) do{if(!(x))___assert_handler(#x, __FILE__, __LINE__, __func__);}while(0); - -/* -#define assert_never_used(x) do{static bool __##x##_init = FALSE; \ - assert(__##x##_init == FALSE); __##x##_init = TRUE;}while(0); - -#define assert_used_once(x) do{static bool __##x##_init; assert(__##x##_init == TRUE);} while(0); -*/ +#define assert(x) do{if(unlikely(!(x)))___assert_handler(#x, __FILE__, __LINE__, __func__);}while(0); #else // not debugging @@ -35,8 +34,16 @@ noreturn void ___assert_handler(const char *, const char *, int, const char *); #endif #define assert(x) -#define assert_used_once(x) -#define assert_never_used(x) + +#endif + +#else // !defined(_OSK_SOURCE) + +#if defined(_NO_DEBUG) && !defined(NDEBUG) +#define NDEBUG 1 +#endif + +#include #endif diff --git a/src/kaleid/common/atomic.h b/src/kaleid/common/atomic.h index bb4bf04..a1daef3 100644 --- a/src/kaleid/common/atomic.h +++ b/src/kaleid/common/atomic.h @@ -10,6 +10,10 @@ #ifndef _KALCOMM_ATOMIC_H #define _KALCOMM_ATOMIC_H +#ifndef _KALCOMM_COMMON_H +#error "don't include common/types.h without common/common.h" +#endif + // atomic_t defined in common/types.h #ifdef _KALEID_KERNEL diff --git a/src/kaleid/common/common.h b/src/kaleid/common/common.h index 9c06922..9c9dd6a 100644 --- a/src/kaleid/common/common.h +++ b/src/kaleid/common/common.h @@ -7,28 +7,39 @@ // Desc: Standard include file for both kernel/ and system/ // //----------------------------------------------------------------------------// - #ifndef _KALCOMM_COMMON_H #define _KALCOMM_COMMON_H -#define true 1 -#define TRUE 1 -#define YES 1 +#if !defined(_OSK_SOURCE) && (defined(_KALEID_KERNEL) || defined(_KALEID_SYSTEM)) +#define _OSK_SOURCE 1 +#endif -#define false 0 -#define FALSE 0 -#define NO 0 +#if !defined(TRUE) && !defined(FALSE) +# define TRUE 1 +# define FALSE 0 +#endif -#define NULL ((void*)0) +#ifdef _OSK_SOURCE +# define YES 1 +# define NO 0 +#endif -#define PACKED __attribute__((packed)) -#define noreturn __attribute__((noreturn)) +#ifndef NULL +# define NULL ((void*)0) +#endif -#define THROWS(...) -#define ERRS(...) +#ifndef PACKED +# define PACKED __attribute__((packed)) +#endif -#define likely(x) __builtin_expect((x), 1) -#define unlikely(x) __builtin_expect((x), 0) +#ifndef noreturn +# define noreturn __attribute__((noreturn)) +#endif + +#if !defined(likely) && !defined(unlikely) +# define likely(x) __builtin_expect((x), 1) +# define unlikely(x) __builtin_expect((x), 0) +#endif #include "common/types.h" #include "common/config.h" diff --git a/src/kaleid/common/convert.h b/src/kaleid/common/convert.h new file mode 100644 index 0000000..737f016 --- /dev/null +++ b/src/kaleid/common/convert.h @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Conversion utilities // +//----------------------------------------------------------------------------// + +#ifndef _KALCOMM_CONVERT_H +#define _KALCOMM_CONVERT_H + +#ifndef _KALCOMM_COMMON_H +#include "common/common.h" +#endif + +#ifndef _OSK_SOURCE +# define itoa _osk_itoa +# define atoi _osk_atoi +#endif + +char *itoa(int, char *, int); + +#endif diff --git a/src/kaleid/common/lib/convert.c b/src/kaleid/common/lib/convert.c new file mode 100644 index 0000000..2731900 --- /dev/null +++ b/src/kaleid/common/lib/convert.c @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Conversion utilities // +//----------------------------------------------------------------------------// + +#include "common/convert.h" + +// +// Digits table for bases <=36 +// +static const char digits[36] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +// +// Integer to string in any base between 2 and 36 (included) +// +char *itoa(int i, char *str, int base) +{ + int neg = 0; + char *orig = str; + + if (base < 2 || base > 36) + return NULL; + + // deal with negatives + if (i < 0) { + neg = 1; + i = -i; + } + + // deal with zero separatly + if (i == 0) { + *str++ = '0'; + } + + // compute digits... in reverse order (XXX?) + while (i > 0) { + *str++ = digits[i % base]; + i /= base; + } + + if (neg) *str++ = '-'; + *str = '\0'; + + return reverse(orig); +} + + diff --git a/src/kaleid/common/lib/memory.c b/src/kaleid/common/lib/memory.c new file mode 100644 index 0000000..3ebe6ee --- /dev/null +++ b/src/kaleid/common/lib/memory.c @@ -0,0 +1,11 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: mem*() functions // +//----------------------------------------------------------------------------// + +#include "common/memory.h" + diff --git a/src/kaleid/common/lib/sprintf.c b/src/kaleid/common/lib/sprintf.c new file mode 100644 index 0000000..1785a01 --- /dev/null +++ b/src/kaleid/common/lib/sprintf.c @@ -0,0 +1,75 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: sprintf()-related functions // +//----------------------------------------------------------------------------// + +#include "common/string.h" + +// +// Format str according to fmt using ellipsed arguments +// +int sprintf(char *str, const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap); + ret = vsnprintf(str, SIZE_T_MAX, fmt, ap); + va_end(ap); + + return ret; +} + +// +// Format str according to fmt, using the va_list ap +// +int vsprintf(char *str, const char *fmt, va_list ap) +{ + return vsnprintf(str, SIZE_T_MAX, fmt, ap); +} + +// +// sprintf() but with a size limit: no more than n bytes are written in str +// XXX null termination behavior? +// +int snprintf(char *str, size_t n, const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap); + ret = vsnprintf(str, n, fmt, ap) + va_end(ap); + + return ret; +} + +// +// snprintf() but arguments +// +int vsnprintf(char *str, size_t n, const char *fmt, va_list ap) +{ + int ret = 0; + + while (*fmt && ret < n) { + if (*fmt != '%') { + *str++ = *fmt++; + ret++; + continue; + } + + switch (*fmt) { + case 'd': + default: + break; + } + } + + return ret; +} + + diff --git a/src/kaleid/common/lib/string.c b/src/kaleid/common/lib/string.c index 083f269..f81f60c 100644 --- a/src/kaleid/common/lib/string.c +++ b/src/kaleid/common/lib/string.c @@ -11,15 +11,21 @@ // TODO multibyte, assembly +// +// Returns str's length +// size_t strlen(const char *str) { const char *base = str; - while (str) str++; + while (*str++); - return (str - base); + return (str - base - 1); } +// +// Copy the string src into dest +// char *strcpy(char *dest, const char *src) { char *base = dest; @@ -27,6 +33,9 @@ char *strcpy(char *dest, const char *src) return base; } +// +// strcpy() but safer +// char *strncpy(char *dest, const char *src, size_t n) { size_t i; @@ -39,3 +48,20 @@ char *strncpy(char *dest, const char *src, size_t n) return dest; } +// +// Reverses a string +// +char *reverse(char *str) +{ + char ch, *orig = str; + size_t n = strlen(str); + char *temp = str + n - 1; + + while (temp > str) { + ch = *temp; + *temp-- = *str; + *str++ = ch; + } + + return orig; +} diff --git a/src/kaleid/common/memory.h b/src/kaleid/common/memory.h new file mode 100644 index 0000000..a877e1a --- /dev/null +++ b/src/kaleid/common/memory.h @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: mem*() functions // +//----------------------------------------------------------------------------// + +#ifndef _KALCOMM_MEMORY_H +#define _KALCOMM_MEMORY_H + +#ifndef _KALCOMM_COMMON_H +#include "common/common.h" +#endif + +#endif + diff --git a/src/kaleid/common/status.h b/src/kaleid/common/status.h index ee9516e..82387da 100644 --- a/src/kaleid/common/status.h +++ b/src/kaleid/common/status.h @@ -7,16 +7,23 @@ // Desc: Values for status_t // //----------------------------------------------------------------------------// - #ifndef _KALCOMM_STATUS_H #define _KALCOMM_STATUS_H -#define STATUS_FAILED(x) ((x) < 0)) -#define STATUS_SUCCESS(x) (!STATUS_FAILED(x)) +#ifndef _KALCOMM_COMMON_H +#error "don't include common/types.h without common/common.h" +#endif + +#ifndef _OSK_SOURCE +# define describe_status _osk_describe_status +#endif // see in common/lib/status.c for status messages const char *describe_status(status_t); +#define STATUS_FAILED(x) ((x) < 0)) +#define STATUS_SUCCESS(x) (!STATUS_FAILED(x)) + #define SUCCESS (0) // everything went fine #define FAILED (-1) diff --git a/src/kaleid/common/string.h b/src/kaleid/common/string.h index bf5fdf3..0f8542d 100644 --- a/src/kaleid/common/string.h +++ b/src/kaleid/common/string.h @@ -11,11 +11,33 @@ #ifndef _KALCOMM_STRING_H #define _KALCOMM_STRING_H +#ifndef _KALCOMM_COMMON_H #include "common/common.h" +#endif + +#ifndef _OSK_SOURCE + +# define strlen _osk_strlen +# define strcpy _osk_strcpy +# define strncpy _osk_strncpy +# define reverse _osk_reverse + +# define sprintf _osk_sprintf +# define snprintf _osk_snprintf +# define vsprintf _osk_vsprintf +# define vsnprintf _osk_vsnprintf + +#endif size_t strlen(const char *); char *strcpy(char *, const char *); char *strncpy(char *, const char *, size_t); +char *reverse(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); #endif diff --git a/src/kaleid/common/types.h b/src/kaleid/common/types.h index abe48a5..fb7d4ff 100644 --- a/src/kaleid/common/types.h +++ b/src/kaleid/common/types.h @@ -11,21 +11,31 @@ #ifndef _KALCOMM_TYPES_H #define _KALCOMM_TYPES_H -typedef _Bool bool; -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef long double ldouble; -typedef short status_t; -typedef short port_t; -typedef uint wchar_t; -typedef ulong size_t; -typedef long ssize_t; -typedef size_t off_t; +#ifndef _KALCOMM_COMMON_H +#error "don't include common/types.h without common/common.h" +#endif -typedef int atomic_t; -typedef ulong pid_t; +#ifndef KEEP_KALCOMM_TYPES_MINIMAL +typedef _Bool bool; +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef long long llong; +typedef unsigned long long ullong; +typedef long double ldouble; +typedef uint wchar_t; +typedef ullong size_t; +typedef llong ssize_t; +typedef size_t off_t; +typedef int atomic_t; +typedef ulong pid_t; +typedef void *va_list; +#endif + +typedef short port_t; +typedef short status_t; +// XXX limits #endif diff --git a/src/kaleid/kernel/init.c b/src/kaleid/kernel/init.c index 2ea9311..b6f268a 100644 --- a/src/kaleid/kernel/init.c +++ b/src/kaleid/kernel/init.c @@ -8,8 +8,12 @@ //----------------------------------------------------------------------------// #include "kernel/init.h" +#include "kernel/ke/panic.h" #include "kernel/io/terminal.h" +// +// Entry point of kaleid-kernel.elf +// void kstart(void) { kterm_init(); diff --git a/src/kaleid/kernel/init.h b/src/kaleid/kernel/init.h index 8238842..bb80788 100644 --- a/src/kaleid/kernel/init.h +++ b/src/kaleid/kernel/init.h @@ -11,8 +11,6 @@ #define _KALKERN_INIT_H #include "common/common.h" -#include "common/string.h" -#include "kernel/ke/panic.h" // kernel entry point void kstart(void); diff --git a/src/kaleid/linux/test-common.c b/src/kaleid/linux/test-common.c new file mode 100644 index 0000000..a8c746e --- /dev/null +++ b/src/kaleid/linux/test-common.c @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Test file for common/ // +//----------------------------------------------------------------------------// + +#include +#include +#include + +#define KEEP_KALCOMM_TYPES_MINIMAL + +#include "common/common.h" +#include "common/string.h" + +int main(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + + const char *test1 = "test string\n"; + char *test2 = malloc(strlen(test1)); + char *test3 = malloc(strlen(test1)); + + printf("1\n"); + + #undef strlen + assert(strlen("test string") == _osk_strlen("test string")); + + #undef strcpy + assert(strcmp(strcpy(test2, test1), _osk_strcpy(test3, test1)) == 0); + + + // tests done + printf("2\n"); + + free(test2); + free(test3); + + return 0; +} +