Expanded standard library

This commit is contained in:
Julian Barathieu 2018-12-25 19:09:58 +01:00
parent 003bd3be3c
commit f6ea17d9e0
16 changed files with 384 additions and 71 deletions

View File

@ -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
#----------------------------------------------------------------------------#

View File

@ -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 <assert.h>
#endif

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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);
}

View File

@ -0,0 +1,11 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: mem*() functions //
//----------------------------------------------------------------------------//
#include "common/memory.h"

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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);

View File

@ -0,0 +1,45 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: Test file for common/ //
//----------------------------------------------------------------------------//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}