From aa247b3d4ba1e5e6329163214e04694b5b20d88c Mon Sep 17 00:00:00 2001 From: bumbread Date: Tue, 7 Jun 2022 13:57:57 +1100 Subject: [PATCH 1/4] Separate out platform dependent stuff --- code/os/win/io.c | 15 +++++++++++++++ code/stdio.c | 33 ++++++--------------------------- inc/_os.h | 4 ++++ inc/stdio.h | 14 +++++++++++--- 4 files changed, 36 insertions(+), 30 deletions(-) create mode 100644 code/os/win/io.c diff --git a/code/os/win/io.c b/code/os/win/io.c new file mode 100644 index 0000000..795659a --- /dev/null +++ b/code/os/win/io.c @@ -0,0 +1,15 @@ + +#define WIN32_LEAN_AND_MEAN +#include + +// It's just mapped directly to HANDLE +struct FILE { + int unused; +}; + +void _file_write(void* ctx, size_t n, const char str[]) { + DWORD written = 0; + WriteFile((HANDLE) ctx, str, n, &written, NULL); +} + + diff --git a/code/stdio.c b/code/stdio.c index 1db2ec8..4ffde74 100644 --- a/code/stdio.c +++ b/code/stdio.c @@ -7,6 +7,8 @@ #define __STDC_WANT_LIB_EXT1__ 1 #include +#include <_os.h> + typedef void(*OutputFunc)(void* ctx, size_t n, const char str[]); /////////////////////////////////////////////// @@ -18,29 +20,6 @@ typedef void(*OutputFunc)(void* ctx, size_t n, const char str[]); #define FMT_STRLEN_S(s, maxsize) strnlen_s(s, maxsize) #include "printf.h" -/////////////////////////////////////////////// -// Platform dependent -/////////////////////////////////////////////// -#if defined(_os_win) -#define WIN32_LEAN_AND_MEAN -#include - -// It's just mapped directly to HANDLE -struct FILE { - int unused; -}; - -static void file_write(void* ctx, size_t n, const char str[]) { - DWORD written = 0; - WriteFile((HANDLE) ctx, str, n, &written, NULL); -} -#else -#error "TODO: Implement this" -#endif - -/////////////////////////////////////////////// -// Platform indenpendent -/////////////////////////////////////////////// typedef struct { size_t used, capacity; char* string; @@ -61,12 +40,12 @@ static void string_write(void *ctx, size_t n, const char *restrict str) { } int fprintf(FILE *file, const char *restrict fmt, ...) { - CALL_PRINTF(fmt_print_char, file, file_write, fmt); + CALL_PRINTF(fmt_print_char, file, _file_write, fmt); return result; } int printf(const char *restrict fmt, ...) { - CALL_PRINTF(fmt_print_char, stdout, file_write, fmt); + CALL_PRINTF(fmt_print_char, stdout, _file_write, fmt); return result; } @@ -83,11 +62,11 @@ int sprintf(char *restrict s, const char *restrict fmt, ...) { } int vfprintf(FILE *file, const char *restrict fmt, va_list args) { - return fmt_print_char(file, file_write, fmt, args); + return fmt_print_char(file, _file_write, fmt, args); } int vprintf(const char *restrict fmt, va_list args) { - return fmt_print_char(stdout, file_write, fmt, args); + return fmt_print_char(stdout, _file_write, fmt, args); } int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list args) { diff --git a/inc/_os.h b/inc/_os.h index cc49a99..253bdc6 100644 --- a/inc/_os.h +++ b/inc/_os.h @@ -13,3 +13,7 @@ || defined(_os_linux)) #error "Unsupported OS" #endif + +// OS-dependent IO Functions +void _file_write(void* ctx, size_t n, const char str[]); +typedef struct FILE FILE; diff --git a/inc/stdio.h b/inc/stdio.h index b2f59a9..e867634 100644 --- a/inc/stdio.h +++ b/inc/stdio.h @@ -6,6 +6,10 @@ typedef struct FILE FILE; typedef int64_t fpos_t; +#if !defined(NULL) + #define NULL ((void *)0) +#endif + #if !defined(__STDC_LIB_EXT1__) #define __STDC_LIB_EXT1__ typedef int errno_t; @@ -29,9 +33,9 @@ typedef int64_t fpos_t; #define FOPEN_MAX 20 #ifdef _os_win -#define FILENAME_MAX 260 + #define FILENAME_MAX 260 #else -#define FILENAME_MAX 4096 + #define FILENAME_MAX 4096 #endif #define L_tmpnam FILENAME_MAX @@ -40,7 +44,11 @@ typedef int64_t fpos_t; #define SEEK_END 2 #define SEEK_SET 0 -#define TMP_MAX INT_MAX +#ifdef _os_win + #define TMP_MAX SHORT_MAX +#else + #define TMP_MAX INT_MAX +#endif extern FILE *stdout, *stderr, *stdin; From 3252f1f10a725452cd7e6e3c319c91e0cd00c7be Mon Sep 17 00:00:00 2001 From: bumbread Date: Tue, 7 Jun 2022 17:02:23 +1100 Subject: [PATCH 2/4] signal --- bake.cmd | 2 +- code/assert.c | 2 +- code/os/win/entry.c | 3 ++ code/os/win/env.c | 8 +++++ code/os/win/except.c | 57 +++++++++++++++++++++++++++++++++ code/os/win/io.c | 2 +- code/os/win/{memory.c => mem.c} | 0 code/signal.c | 46 ++++++++++++++++++++++++++ code/stdio.c | 8 ++--- inc/_macros.h | 1 + inc/_os.h | 4 ++- inc/assert.h | 1 + inc/signal.h | 29 ++++++++++------- test/test.c | 15 +++++++-- 14 files changed, 156 insertions(+), 22 deletions(-) create mode 100644 code/os/win/except.c rename code/os/win/{memory.c => mem.c} (100%) create mode 100644 code/signal.c diff --git a/bake.cmd b/bake.cmd index 15e4ac2..fa0fdfd 100644 --- a/bake.cmd +++ b/bake.cmd @@ -16,7 +16,7 @@ shift /1 set CIABATTA_OPTIONS=-Iinc -Wall -g -gcodeview -nodefaultlibs -D_CRT_SECURE_NO_WARNINGS set PLATFORM=win -if "%1"=="fast" ( +if "%1"=="test" ( goto :skip_crt_compilation ) :: For each C file in code/ we check whether it's OS-dependent. diff --git a/code/assert.c b/code/assert.c index 00ddc71..47d3636 100644 --- a/code/assert.c +++ b/code/assert.c @@ -20,5 +20,5 @@ extern void _assert_error( } printf("\tFile: %s\n", file); printf("\tLine: %s\n", line); - _compiler_brk(); + abort(); } diff --git a/code/os/win/entry.c b/code/os/win/entry.c index 500d69e..eb538b3 100644 --- a/code/os/win/entry.c +++ b/code/os/win/entry.c @@ -1,4 +1,6 @@ +#include <_os.h> + #include #include #include @@ -71,6 +73,7 @@ void mainCRTStartup() { srand(0); setlocale(LC_ALL, "C"); + _os_init_eh(); int exit_code = main(arg_count, args); ExitProcess(exit_code); diff --git a/code/os/win/env.c b/code/os/win/env.c index c97a4f3..8688081 100644 --- a/code/os/win/env.c +++ b/code/os/win/env.c @@ -1,2 +1,10 @@ #include + +#define WIN32_LEAN_AND_MEAN +#include + +void _os_exit(int code) +{ + ExitProcess(code); +} diff --git a/code/os/win/except.c b/code/os/win/except.c new file mode 100644 index 0000000..9a1d38d --- /dev/null +++ b/code/os/win/except.c @@ -0,0 +1,57 @@ + +#include <_os.h> + +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include +#include <_macros.h> + +typedef struct SignalMapping { + DWORD code; + int signal; +} SignalMapping; + +static SignalMapping map[] = { + {EXCEPTION_ACCESS_VIOLATION, SIGSEGV}, + {EXCEPTION_IN_PAGE_ERROR, SIGSEGV}, + {EXCEPTION_ARRAY_BOUNDS_EXCEEDED, SIGSEGV}, + {EXCEPTION_DATATYPE_MISALIGNMENT, SIGALIGN}, + {EXCEPTION_BREAKPOINT, SIGBREAK}, + {EXCEPTION_FLT_DENORMAL_OPERAND, SIGFPE}, + {EXCEPTION_FLT_DIVIDE_BY_ZERO, SIGFPE}, + {EXCEPTION_FLT_INEXACT_RESULT, SIGFPE}, + {EXCEPTION_FLT_INVALID_OPERATION, SIGFPE}, + {EXCEPTION_FLT_OVERFLOW, SIGFPE}, + {EXCEPTION_FLT_STACK_CHECK, SIGFPE}, + {EXCEPTION_FLT_UNDERFLOW, SIGFPE}, + {EXCEPTION_ILLEGAL_INSTRUCTION, SIGILL}, + {EXCEPTION_INT_DIVIDE_BY_ZERO, SIGFPE}, + {EXCEPTION_INT_OVERFLOW, SIGFPE}, + {EXCEPTION_PRIV_INSTRUCTION, SIGILL}, + {EXCEPTION_SINGLE_STEP, SIGSTEP}, +}; + +static LONG _win32_handler(EXCEPTION_POINTERS *ExceptionInfo) +{ + EXCEPTION_RECORD *exception = ExceptionInfo->ExceptionRecord; + DWORD code = exception->ExceptionCode; + int signal = -1; + for(int mapping = 0; mapping != _countof(map); ++mapping) { + if(code == map[mapping].code) { + signal = map[mapping].signal; + } + } + if(signal != -1) { + raise(signal); + } + return EXCEPTION_CONTINUE_SEARCH; +} + +void _os_init_eh() { + void *res = AddVectoredExceptionHandler(1, &_win32_handler); + if(res == NULL) { + ExitProcess(-69420); + } +} diff --git a/code/os/win/io.c b/code/os/win/io.c index 795659a..edea935 100644 --- a/code/os/win/io.c +++ b/code/os/win/io.c @@ -7,7 +7,7 @@ struct FILE { int unused; }; -void _file_write(void* ctx, size_t n, const char str[]) { +void _os_file_write(void* ctx, size_t n, const char str[]) { DWORD written = 0; WriteFile((HANDLE) ctx, str, n, &written, NULL); } diff --git a/code/os/win/memory.c b/code/os/win/mem.c similarity index 100% rename from code/os/win/memory.c rename to code/os/win/mem.c diff --git a/code/signal.c b/code/signal.c new file mode 100644 index 0000000..7b9c196 --- /dev/null +++ b/code/signal.c @@ -0,0 +1,46 @@ + +#include <_os.h> +#include + +void _signal_default_handler(int sig) +{ + +} + +void _signal_ignore_handler(int sig) +{ + // ignore :kekw: +} + +static void (*(handlers[]))(int) = { + [SIGINT] = _signal_ignore_handler, + [SIGILL] = _signal_ignore_handler, + [SIGFPE] = _signal_ignore_handler, + [SIGSEGV] = _signal_ignore_handler, + [SIGTERM] = _signal_ignore_handler, + [SIGABRT] = _signal_ignore_handler, + [SIGBREAK] = _signal_ignore_handler, + [SIGALIGN] = _signal_ignore_handler, + [SIGSTEP] = _signal_ignore_handler, +}; + +void (*signal(int sig, void (*func)(int)))(int) +{ + if(_SIG_MIN <= sig && sig <= _SIG_MAX) { + handlers[sig] = func; + return func; + } + return SIG_ERR; +} + +int raise(int sig) +{ + if(_SIG_MIN <= sig && sig <= _SIG_MAX) { + handlers[sig](sig); + if(sig == SIGFPE || sig == SIGILL || sig == SIGSEGV) { + _os_exit(-69420); + } + return 1; + } + return 0; +} diff --git a/code/stdio.c b/code/stdio.c index 4ffde74..21f69a4 100644 --- a/code/stdio.c +++ b/code/stdio.c @@ -40,12 +40,12 @@ static void string_write(void *ctx, size_t n, const char *restrict str) { } int fprintf(FILE *file, const char *restrict fmt, ...) { - CALL_PRINTF(fmt_print_char, file, _file_write, fmt); + CALL_PRINTF(fmt_print_char, file, _os_file_write, fmt); return result; } int printf(const char *restrict fmt, ...) { - CALL_PRINTF(fmt_print_char, stdout, _file_write, fmt); + CALL_PRINTF(fmt_print_char, stdout, _os_file_write, fmt); return result; } @@ -62,11 +62,11 @@ int sprintf(char *restrict s, const char *restrict fmt, ...) { } int vfprintf(FILE *file, const char *restrict fmt, va_list args) { - return fmt_print_char(file, _file_write, fmt, args); + return fmt_print_char(file, _os_file_write, fmt, args); } int vprintf(const char *restrict fmt, va_list args) { - return fmt_print_char(stdout, _file_write, fmt, args); + return fmt_print_char(stdout, _os_file_write, fmt, args); } int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list args) { diff --git a/inc/_macros.h b/inc/_macros.h index 0f4e977..fa90589 100644 --- a/inc/_macros.h +++ b/inc/_macros.h @@ -6,3 +6,4 @@ #define _con(a,b) a ## b +#define _countof(arr) (sizeof (arr) / sizeof ((arr)[0])) diff --git a/inc/_os.h b/inc/_os.h index 253bdc6..37c46d0 100644 --- a/inc/_os.h +++ b/inc/_os.h @@ -15,5 +15,7 @@ #endif // OS-dependent IO Functions -void _file_write(void* ctx, size_t n, const char str[]); +void _os_file_write(void* ctx, size_t n, const char str[]); +void _os_exit(int code); +void _os_init_eh(); typedef struct FILE FILE; diff --git a/inc/assert.h b/inc/assert.h index 478f8ba..dd950b8 100644 --- a/inc/assert.h +++ b/inc/assert.h @@ -1,5 +1,6 @@ #pragma once #include "_compiler.h" +#include "_macros.h" extern void _assert_error( char *cond, diff --git a/inc/signal.h b/inc/signal.h index c3016c8..e8a00c6 100644 --- a/inc/signal.h +++ b/inc/signal.h @@ -3,19 +3,24 @@ typedef int sig_atomic_t; -// TODO: implement this -#define SIG_DFL 0 -#define SIG_ERR 1 -#define SIG_IGN 2 +// TODO: idk about SIG_ERR, for now this +#define SIG_ERR ((void(*)(int))0) +#define SIG_DFL _signal_default_handler +#define SIG_IGN _signal_ignore_handler -// not sure why but windows picked these, we can change it later -#define SIGINT 2 -#define SIGILL 4 -#define SIGFPE 8 -#define SIGSEGV 11 -#define SIGTERM 15 -#define SIGBREAK 21 -#define SIGABRT 22 +// Note(bumbread): from the impl standpoint the numbers are arbitrary +#define _SIG_MIN 0 +#define SIGINT 1 +#define SIGILL 2 +#define SIGFPE 3 +#define SIGSEGV 4 +#define SIGTERM 5 +#define SIGABRT 6 +// These guys are impl defined +#define SIGBREAK 7 +#define SIGALIGN 8 +#define SIGSTEP 9 +#define _SIG_MAX 9 void (*signal(int sig, void (*func)(int)))(int); int raise(int sig); diff --git a/test/test.c b/test/test.c index afde00a..4ee6606 100644 --- a/test/test.c +++ b/test/test.c @@ -4,10 +4,21 @@ #include #include +#include #include +#include + +void my_va_handler(int a) { + printf("NULLPTR deref or something idk not an expert in signals\n"); +} + int main(int argc, char** argv) { - uint64_t mynumber = 4; - printf("Hello, guys %"PRIu64"\n", mynumber); + signal(SIGSEGV, my_va_handler); + signal(SIGFPE, my_va_handler); + + int a = INT_MAX; + a /= 0; + return 0; } \ No newline at end of file From a8d1afdea24d7484118b76f37916e605a3d13cd4 Mon Sep 17 00:00:00 2001 From: bumbread Date: Tue, 7 Jun 2022 17:15:47 +1100 Subject: [PATCH 3/4] make assert do abort --- code/os/win/env.c | 10 ---------- code/os/win/{win32.h => win.h} | 0 code/os/win/{entry.c => win_entry.c} | 2 +- code/os/win/win_env.c | 9 +++++++++ code/os/win/{except.c => win_except.c} | 3 +-- code/os/win/{io.c => win_io.c} | 3 +-- code/os/win/{mem.c => win_mem.c} | 2 +- code/stdlib/env.c | 21 +++++++++++++++++++++ inc/_os.h | 2 +- inc/stdlib.h | 9 ++++++--- test/test.c | 13 +++++-------- 11 files changed, 46 insertions(+), 28 deletions(-) delete mode 100644 code/os/win/env.c rename code/os/win/{win32.h => win.h} (100%) rename code/os/win/{entry.c => win_entry.c} (99%) create mode 100644 code/os/win/win_env.c rename code/os/win/{except.c => win_except.c} (96%) rename code/os/win/{io.c => win_io.c} (81%) rename code/os/win/{mem.c => win_mem.c} (98%) create mode 100644 code/stdlib/env.c diff --git a/code/os/win/env.c b/code/os/win/env.c deleted file mode 100644 index 8688081..0000000 --- a/code/os/win/env.c +++ /dev/null @@ -1,10 +0,0 @@ - -#include - -#define WIN32_LEAN_AND_MEAN -#include - -void _os_exit(int code) -{ - ExitProcess(code); -} diff --git a/code/os/win/win32.h b/code/os/win/win.h similarity index 100% rename from code/os/win/win32.h rename to code/os/win/win.h diff --git a/code/os/win/entry.c b/code/os/win/win_entry.c similarity index 99% rename from code/os/win/entry.c rename to code/os/win/win_entry.c index eb538b3..314fe29 100644 --- a/code/os/win/entry.c +++ b/code/os/win/win_entry.c @@ -6,7 +6,7 @@ #include #include -#include "win32.h" +#include "win.h" extern int main(int argc, char** argv); diff --git a/code/os/win/win_env.c b/code/os/win/win_env.c new file mode 100644 index 0000000..76c3ecf --- /dev/null +++ b/code/os/win/win_env.c @@ -0,0 +1,9 @@ + +#include + +#include "win.h" + +_Noreturn void _os_exit(int code) +{ + ExitProcess(code); +} diff --git a/code/os/win/except.c b/code/os/win/win_except.c similarity index 96% rename from code/os/win/except.c rename to code/os/win/win_except.c index 9a1d38d..0e4c131 100644 --- a/code/os/win/except.c +++ b/code/os/win/win_except.c @@ -33,8 +33,7 @@ static SignalMapping map[] = { {EXCEPTION_SINGLE_STEP, SIGSTEP}, }; -static LONG _win32_handler(EXCEPTION_POINTERS *ExceptionInfo) -{ +static LONG _win32_handler(EXCEPTION_POINTERS *ExceptionInfo) { EXCEPTION_RECORD *exception = ExceptionInfo->ExceptionRecord; DWORD code = exception->ExceptionCode; int signal = -1; diff --git a/code/os/win/io.c b/code/os/win/win_io.c similarity index 81% rename from code/os/win/io.c rename to code/os/win/win_io.c index edea935..4059204 100644 --- a/code/os/win/io.c +++ b/code/os/win/win_io.c @@ -1,6 +1,5 @@ -#define WIN32_LEAN_AND_MEAN -#include +#include "win.h" // It's just mapped directly to HANDLE struct FILE { diff --git a/code/os/win/mem.c b/code/os/win/win_mem.c similarity index 98% rename from code/os/win/mem.c rename to code/os/win/win_mem.c index 0b218bc..6675287 100644 --- a/code/os/win/mem.c +++ b/code/os/win/win_mem.c @@ -3,7 +3,7 @@ #include #include -#include "win32.h" +#include "win.h" // TODO: lock the heap before allocation (?) diff --git a/code/stdlib/env.c b/code/stdlib/env.c new file mode 100644 index 0000000..9e8b349 --- /dev/null +++ b/code/stdlib/env.c @@ -0,0 +1,21 @@ + +#include +#include + +#include <_os.h> + +_Noreturn void abort(void) { + raise(SIGABRT); + _os_exit(-69); +} + +// TODO: at_exit handling + +_Noreturn void exit(int status) { + _os_exit(status); +} + +_Noreturn void _Exit(int status) { + _os_exit(status); +} + diff --git a/inc/_os.h b/inc/_os.h index 37c46d0..8a1860b 100644 --- a/inc/_os.h +++ b/inc/_os.h @@ -16,6 +16,6 @@ // OS-dependent IO Functions void _os_file_write(void* ctx, size_t n, const char str[]); -void _os_exit(int code); +_Noreturn void _os_exit(int code); void _os_init_eh(); typedef struct FILE FILE; diff --git a/inc/stdlib.h b/inc/stdlib.h index 3ca5496..bffb106 100644 --- a/inc/stdlib.h +++ b/inc/stdlib.h @@ -15,6 +15,9 @@ #endif #endif +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 + // typedef struct div_t { // int quot; // int rem; @@ -58,11 +61,11 @@ void free(void *ptr); void *malloc(size_t size); void *realloc(void *ptr, size_t size); -// _Noreturn void abort(void); +_Noreturn void abort(void); // int atexit(void (*func)(void)); // int at_quick_exit(void (*func)(void)); -// _Noreturn void exit(int status); -// _Noreturn void _Exit(int status); +_Noreturn void exit(int status); +_Noreturn void _Exit(int status); // char *getenv(const char *name); // _Noreturn void quick_exit(int status); // int system(const char *string); diff --git a/test/test.c b/test/test.c index 4ee6606..c214f30 100644 --- a/test/test.c +++ b/test/test.c @@ -9,16 +9,13 @@ #include -void my_va_handler(int a) { - printf("NULLPTR deref or something idk not an expert in signals\n"); +void onabort(int a) { + printf("I don't want to live anymore\n"); + exit(-69); } int main(int argc, char** argv) { - signal(SIGSEGV, my_va_handler); - signal(SIGFPE, my_va_handler); - - int a = INT_MAX; - a /= 0; - + signal(SIGABRT, onabort); + assert(0 != 0); return 0; } \ No newline at end of file From 3c0baa113f5af677e4045af9c8aa3a96426c97b1 Mon Sep 17 00:00:00 2001 From: bumbread Date: Tue, 7 Jun 2022 20:26:13 +1100 Subject: [PATCH 4/4] strtok and some changes to string.h --- code/printf.h | 6 ++ code/string.c | 155 +++++++++++++++++++++++++++++--------------------- inc/string.h | 31 +++++----- test/test.c | 23 ++++++-- 4 files changed, 132 insertions(+), 83 deletions(-) diff --git a/code/printf.h b/code/printf.h index 5e68ca1..f097aa3 100644 --- a/code/printf.h +++ b/code/printf.h @@ -75,6 +75,12 @@ inline static int FMT_FUNC_NAME (void *ctx, OutputFunc out, const FMT_CHAR_TYPE FMT_CHAR_TYPE ch = *fmt++; switch (ch) { + case 'c': { + const char chr = va_arg(args, int); + out(ctx, 1, &chr); + full_length ++; + break; + } case 's': { const FMT_CHAR_TYPE *str = va_arg(args, FMT_CHAR_TYPE*); size_t len = FMT_STRLEN_S(str, precision ? precision : SIZE_MAX); diff --git a/code/string.c b/code/string.c index 938cfef..a2713fd 100644 --- a/code/string.c +++ b/code/string.c @@ -20,8 +20,7 @@ void *memcpy(void *restrict s1, const void *restrict s2, size_t n) { return s1; } -void *memmove(void *s1, const void *s2, size_t n) -{ +void *memmove(void *s1, const void *s2, size_t n) { void *buffer = malloc(n); memcpy(buffer, s2, n); memcpy(s1, buffer, n); @@ -29,16 +28,7 @@ void *memmove(void *s1, const void *s2, size_t n) return s1; } -void *memset(void *s, int c, size_t n) { - byte *restrict buf = s; - while (n--) { - *buf++ = c; - } - return s; -} - -char *strcpy(char *restrict s1, const char *restrict s2) -{ +char *strcpy(char *restrict s1, const char *restrict s2) { while(*s2 != 0) { *s1++ = *s2++; } @@ -46,25 +36,26 @@ char *strcpy(char *restrict s1, const char *restrict s2) return s1; } -char *strncpy(char *restrict s1, const char *restrict s2, size_t n) -{ - while(n-->0 && *s2 != 0) { +char *strncpy(char *restrict s1, const char *restrict s2, size_t n) { + size_t i = 0; + for(; i < n && *s2 != 0; ++ i) { *s1++ = *s2++; } - while(n-->0) { + for(; i < n; ++i) { *s1++ = 0; } return s1; } -char *strncat(char *restrict s1, const char *restrict s2, size_t n) -{ +char *strcat(char *restrict s1, const char *restrict s2) { size_t start = strlen(s1); - for(size_t i = 0; i != n && *s2 != 0; ++i) { - s1[start+i] = s2[i]; - } - s1[start+n] = 0; + return strcpy(s1+start, s2); +} + +char *strncat(char *restrict s1, const char *restrict s2, size_t n) { + size_t start = strlen(s1); + strncpy(s1+start, s2, n); return s1; } @@ -78,6 +69,14 @@ int memcmp(const void *s1, const void *s2, size_t n) { return 0; } +void *memset(void *s, int c, size_t n) { + byte *restrict buf = s; + while (n--) { + *buf++ = c; + } + return s; +} + int strcmp(const char *s1, const char *s2) { int diff; do { @@ -86,8 +85,7 @@ int strcmp(const char *s1, const char *s2) { return diff; } -int strncmp(const char *s1, const char *s2, size_t n) -{ +int strncmp(const char *s1, const char *s2, size_t n) { int diff = 0; size_t i = 0; if(n != 0) do { @@ -96,15 +94,13 @@ int strncmp(const char *s1, const char *s2, size_t n) return diff; } -// fuck locales -int strcoll(const char *s1, const char *s2) -{ +int strcoll(const char *s1, const char *s2) { return strcmp(s1, s2); } -// fuck bad implementation of strcoll -size_t strxfrm(char *restrict s1, const char *restrict s2, size_t n) -{ +// TODO: I don't quite understand the intent nor use behind this function +// so I'm just going to ignore locales for now. +size_t strxfrm(char *restrict s1, const char *restrict s2, size_t n) { size_t len = strlen(s2); if(s1 != NULL && n != 0) { for(size_t i = 0; i != n; ++i) { @@ -114,39 +110,47 @@ size_t strxfrm(char *restrict s1, const char *restrict s2, size_t n) return len; } -void *memchr(const void *ptr, int c, size_t n) -{ - const byte *s = ptr; - size_t i = 0; - for(; i != n && *s != c; ++i, ++s) { - ++s; +void *memchr(const void *ptr, int c, size_t n) { + const char *s = ptr; + for(size_t i = 0; i != n; ++i) { + if(s[i] == c) { + // Casting away const because clang warnings + return (void *)(s+i); + } } - if(i == n) return NULL; - return (void *)s; // fuck clang + return NULL; } -char *strchr(const char *s, int c) -{ - while(*s && *s != c) ++s; - if(*s != c) return NULL; - return (void *)s; // fuck clang +char *strchr(const char *s, int c) { + do { + if(*s == c) return (char *)s; + } while(*s++); + return NULL; } -size_t strcspn(const char *s1, const char *s2) -{ +size_t strspn(const char *s1, const char *s2) { size_t i = 0; - while(*s1) { - if(strchr(s2, *s1) != NULL) { + for(; *s1; ++s1) { + if(strchr(s2, *s1) == NULL) { break; } - ++s1; ++i; } return i; } -char *strpbrk(const char *s1, const char *s2) -{ +size_t strcspn(const char *s1, const char *s2) { + size_t i = 0; + for(; *s1; ++s1) { + if(strchr(s2, *s1) != NULL) { + break; + } + ++i; + } + return i; +} + +char *strpbrk(const char *s1, const char *s2) { while(*s1) { if(strchr(s2, *s1) == NULL) { break; @@ -156,26 +160,47 @@ char *strpbrk(const char *s1, const char *s2) return (char *)s1; } -char *strstr(const char *s1, const char *s2) -{ - if(!*s2) return (char *)s1; +char *strrchr(const char *s, int c) { + char const *last = NULL; + for(; *s != 0; ++s) { + if(*s == c) last = s; + } + return (char *)last; +} + +char *strstr(const char *s1, const char *s2) { + if(*s2 == 0) return (char *)s1; size_t len = strlen(s2); - while(*s1 != 0) { - bool match = true; - for(size_t i = 0; i != len; ++i) { - if(!*s1 || s1[i] != s2[i]) { - match = false; - break; - } - } - ++s1; - if(match) return (char *)s1; + for(; *s1 != 0; ++s1) { + if(strncmp(s1, s2, len) == 0) return (char *)s1; } return NULL; } -char *strerror(int errnum) -{ +// TODO: there may be restrict-related UB +char *strtok(char *restrict s1, const char *restrict s2) { + static char *restrict str; + if(s1 != NULL) str = s1; + if(str == NULL) return NULL; + + size_t junk_len = strspn(str, s2); + char *tok_start = str+junk_len; + if(*tok_start == 0) { + str = NULL; + return NULL; + } + + size_t tok_len = strcspn(str, s2); + + char *tok_end = tok_start + tok_len; + *tok_end = 0; + str = tok_end+1; + + return tok_start; +} + + +char *strerror(int errnum) { switch(errnum) { case 0: return "No errors"; case EDOM: return "Value is out of domain of the function"; diff --git a/inc/string.h b/inc/string.h index e9f0f0d..774499a 100644 --- a/inc/string.h +++ b/inc/string.h @@ -1,6 +1,11 @@ #pragma once +// Technically all we should have here is typedef for size_t. +// but I can't get that without macro shittery so +// for now I'm just doing this, which is not quite correct +#include + #if !defined(NULL) #define NULL ((void *)0) #endif @@ -19,17 +24,17 @@ // int _wcsicmp(const wchar_t *string1, const wchar_t *string2); -void *memcpy(void * restrict s1, const void * restrict s2, size_t n); +void *memcpy(void *restrict s1, const void *restrict s2, size_t n); void *memmove(void *s1, const void *s2, size_t n); -char *strcpy(char * restrict s1, const char * restrict s2); -char *strncpy(char * restrict s1, const char * restrict s2, size_t n); -char *strcat(char * restrict s1, const char * restrict s2); -char *strncat(char * restrict s1, const char * restrict s2, size_t n); +char *strcpy(char *restrict s1, const char *restrict s2); +char *strncpy(char *restrict s1, const char *restrict s2, size_t n); +char *strcat(char *restrict s1, const char *restrict s2); +char *strncat(char *restrict s1, const char *restrict s2, size_t n); int memcmp(const void *s1, const void *s2, size_t n); int strcmp(const char *s1, const char *s2); int strcoll(const char *s1, const char *s2); int strncmp(const char *s1, const char *s2, size_t n); -size_t strxfrm(char * restrict s1, const char * restrict s2, size_t n); +size_t strxfrm(char *restrict s1, const char *restrict s2, size_t n); void *memchr(const void *s, int c, size_t n); char *strchr(const char *s, int c); size_t strcspn(const char *s1, const char *s2); @@ -37,19 +42,19 @@ char *strpbrk(const char *s1, const char *s2); char *strrchr(const char *s, int c); size_t strspn(const char *s1, const char *s2); char *strstr(const char *s1, const char *s2); -char *strtok(char * restrict s1, const char * restrict s2); +char *strtok(char *restrict s1, const char *restrict s2); void *memset(void *s, int c, size_t n); char *strerror(int errnum); size_t strlen(const char *s); #if __STDC_WANT_LIB_EXT1__ == 1 - errno_t memcpy_s(void * restrict s1, rsize_t s1max, const void * restrict s2, rsize_t n); + errno_t memcpy_s(void *restrict s1, rsize_t s1max, const void *restrict s2, rsize_t n); errno_t memmove_s(void *s1, rsize_t s1max, const void *s2, rsize_t n); - errno_t strcpy_s(char * restrict s1, rsize_t s1max, const char * restrict s2); - errno_t strncpy_s(char * restrict s1, rsize_t s1max,const char * restrict s2, rsize_t n); - errno_t strcat_s(char * restrict s1, rsize_t s1max, const char * restrict s2); - errno_t strncat_s(char * restrict s1, rsize_t s1max, const char * restrict s2, rsize_t n); - char *strtok_s(char * restrict s1, rsize_t * restrict s1max, const char * restrict s2, char ** restrict ptr); + errno_t strcpy_s(char *restrict s1, rsize_t s1max, const char *restrict s2); + errno_t strncpy_s(char *restrict s1, rsize_t s1max,const char *restrict s2, rsize_t n); + errno_t strcat_s(char *restrict s1, rsize_t s1max, const char *restrict s2); + errno_t strncat_s(char *restrict s1, rsize_t s1max, const char *restrict s2, rsize_t n); + char *strtok_s(char *restrict s1, rsize_t *restrict s1max, const char *restrict s2, char **restrict ptr); errno_t memset_s(void *s, rsize_t smax, int c, rsize_t n); errno_t strerror_s(char *s, rsize_t maxsize, errno_t errnum); size_t strerrorlen_s(errno_t errnum); diff --git a/test/test.c b/test/test.c index c214f30..d26020f 100644 --- a/test/test.c +++ b/test/test.c @@ -7,15 +7,28 @@ #include #include +#include #include -void onabort(int a) { - printf("I don't want to live anymore\n"); - exit(-69); +int test() { + static int a = 2; + a += 1; + return a; } int main(int argc, char** argv) { - signal(SIGABRT, onabort); - assert(0 != 0); + test(); + char input[] = "A bird came down the walk"; + printf("Parsing the input string '%s'\n", input); + char *token = strtok(input, " "); + while(token) { + printf("%s\n", token); + token = strtok(NULL, " "); + } + + printf("Contents of the input string now: '"); + for(size_t n = 0; n < sizeof input; ++n) + input[n] ? printf("%c", input[n]) : printf("\\0"); + printf("'"); return 0; } \ No newline at end of file