Merge branch 'main' of https://github.com/bumbread/ciabatta into main

This commit is contained in:
NeGate 2022-06-07 21:46:47 -04:00
commit 454a2cc78d
22 changed files with 338 additions and 131 deletions

View File

@ -16,7 +16,7 @@ shift /1
set CIABATTA_OPTIONS=-Iinc -Wall -g -gcodeview -nodefaultlibs -D_CRT_SECURE_NO_WARNINGS set CIABATTA_OPTIONS=-Iinc -Wall -g -gcodeview -nodefaultlibs -D_CRT_SECURE_NO_WARNINGS
set PLATFORM=win set PLATFORM=win
if "%1"=="fast" ( if "%1"=="test" (
goto :skip_crt_compilation goto :skip_crt_compilation
) )
:: For each C file in code/ we check whether it's OS-dependent. :: For each C file in code/ we check whether it's OS-dependent.

View File

@ -20,5 +20,5 @@ extern void _assert_error(
} }
printf("\tFile: %s\n", file); printf("\tFile: %s\n", file);
printf("\tLine: %s\n", line); printf("\tLine: %s\n", line);
_compiler_brk(); abort();
} }

View File

@ -1,2 +0,0 @@
#include <stdlib.h>

View File

@ -1,10 +1,12 @@
#include <_os.h>
#include <locale.h> #include <locale.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include "win32.h" #include "win.h"
extern int main(int argc, char** argv); extern int main(int argc, char** argv);
@ -71,6 +73,7 @@ void mainCRTStartup() {
srand(0); srand(0);
setlocale(LC_ALL, "C"); setlocale(LC_ALL, "C");
_os_init_eh();
int exit_code = main(arg_count, args); int exit_code = main(arg_count, args);
ExitProcess(exit_code); ExitProcess(exit_code);

9
code/os/win/win_env.c Normal file
View File

@ -0,0 +1,9 @@
#include <stdlib.h>
#include "win.h"
_Noreturn void _os_exit(int code)
{
ExitProcess(code);
}

56
code/os/win/win_except.c Normal file
View File

@ -0,0 +1,56 @@
#include <_os.h>
#define WIN32_LEAN_AND_MEAN
#include<Windows.h>
#include <signal.h>
#include <stddef.h>
#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);
}
}

14
code/os/win/win_io.c Normal file
View File

@ -0,0 +1,14 @@
#include "win.h"
// It's just mapped directly to HANDLE
struct FILE {
int unused;
};
void _os_file_write(void* ctx, size_t n, const char str[]) {
DWORD written = 0;
WriteFile((HANDLE) ctx, str, n, &written, NULL);
}

View File

@ -3,7 +3,7 @@
#include <limits.h> #include <limits.h>
#include <stdbool.h> #include <stdbool.h>
#include "win32.h" #include "win.h"
// TODO: lock the heap before allocation (?) // TODO: lock the heap before allocation (?)

View File

@ -75,6 +75,12 @@ inline static int FMT_FUNC_NAME (void *ctx, OutputFunc out, const FMT_CHAR_TYPE
FMT_CHAR_TYPE ch = *fmt++; FMT_CHAR_TYPE ch = *fmt++;
switch (ch) { switch (ch) {
case 'c': {
const char chr = va_arg(args, int);
out(ctx, 1, &chr);
full_length ++;
break;
}
case 's': { case 's': {
const FMT_CHAR_TYPE *str = va_arg(args, FMT_CHAR_TYPE*); const FMT_CHAR_TYPE *str = va_arg(args, FMT_CHAR_TYPE*);
size_t len = FMT_STRLEN_S(str, precision ? precision : SIZE_MAX); size_t len = FMT_STRLEN_S(str, precision ? precision : SIZE_MAX);

46
code/signal.c Normal file
View File

@ -0,0 +1,46 @@
#include <_os.h>
#include <signal.h>
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;
}

View File

@ -7,6 +7,8 @@
#define __STDC_WANT_LIB_EXT1__ 1 #define __STDC_WANT_LIB_EXT1__ 1
#include <string.h> #include <string.h>
#include <_os.h>
typedef void(*OutputFunc)(void* ctx, size_t n, const char str[]); 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) #define FMT_STRLEN_S(s, maxsize) strnlen_s(s, maxsize)
#include "printf.h" #include "printf.h"
///////////////////////////////////////////////
// Platform dependent
///////////////////////////////////////////////
#if defined(_os_win)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
// 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 { typedef struct {
size_t used, capacity; size_t used, capacity;
char* string; 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, ...) { 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; return result;
} }
int printf(const char *restrict fmt, ...) { 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; 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) { 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) { 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) { int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list args) {

21
code/stdlib/env.c Normal file
View File

@ -0,0 +1,21 @@
#include <stdlib.h>
#include <signal.h>
#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);
}

View File

@ -20,8 +20,7 @@ void *memcpy(void *restrict s1, const void *restrict s2, size_t n) {
return s1; 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); void *buffer = malloc(n);
memcpy(buffer, s2, n); memcpy(buffer, s2, n);
memcpy(s1, buffer, n); memcpy(s1, buffer, n);
@ -29,16 +28,7 @@ void *memmove(void *s1, const void *s2, size_t n)
return s1; return s1;
} }
void *memset(void *s, int c, size_t n) { char *strcpy(char *restrict s1, const char *restrict s2) {
byte *restrict buf = s;
while (n--) {
*buf++ = c;
}
return s;
}
char *strcpy(char *restrict s1, const char *restrict s2)
{
while(*s2 != 0) { while(*s2 != 0) {
*s1++ = *s2++; *s1++ = *s2++;
} }
@ -46,25 +36,26 @@ char *strcpy(char *restrict s1, const char *restrict s2)
return s1; return s1;
} }
char *strncpy(char *restrict s1, const char *restrict s2, size_t n) char *strncpy(char *restrict s1, const char *restrict s2, size_t n) {
{ size_t i = 0;
while(n-->0 && *s2 != 0) { for(; i < n && *s2 != 0; ++ i) {
*s1++ = *s2++; *s1++ = *s2++;
} }
while(n-->0) { for(; i < n; ++i) {
*s1++ = 0; *s1++ = 0;
} }
return s1; 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); size_t start = strlen(s1);
for(size_t i = 0; i != n && *s2 != 0; ++i) { return strcpy(s1+start, s2);
s1[start+i] = s2[i];
} }
s1[start+n] = 0;
char *strncat(char *restrict s1, const char *restrict s2, size_t n) {
size_t start = strlen(s1);
strncpy(s1+start, s2, n);
return s1; return s1;
} }
@ -78,6 +69,14 @@ int memcmp(const void *s1, const void *s2, size_t n) {
return 0; 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 strcmp(const char *s1, const char *s2) {
int diff; int diff;
do { do {
@ -86,8 +85,7 @@ int strcmp(const char *s1, const char *s2) {
return diff; 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; int diff = 0;
size_t i = 0; size_t i = 0;
if(n != 0) do { if(n != 0) do {
@ -96,15 +94,13 @@ int strncmp(const char *s1, const char *s2, size_t n)
return diff; return diff;
} }
// fuck locales int strcoll(const char *s1, const char *s2) {
int strcoll(const char *s1, const char *s2)
{
return strcmp(s1, s2); return strcmp(s1, s2);
} }
// fuck bad implementation of strcoll // TODO: I don't quite understand the intent nor use behind this function
size_t strxfrm(char *restrict s1, const char *restrict s2, size_t n) // 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); size_t len = strlen(s2);
if(s1 != NULL && n != 0) { if(s1 != NULL && n != 0) {
for(size_t i = 0; i != n; ++i) { 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; return len;
} }
void *memchr(const void *ptr, int c, size_t n) void *memchr(const void *ptr, int c, size_t n) {
{ const char *s = ptr;
const byte *s = ptr; for(size_t i = 0; i != n; ++i) {
size_t i = 0; if(s[i] == c) {
for(; i != n && *s != c; ++i, ++s) { // Casting away const because clang warnings
++s; return (void *)(s+i);
} }
if(i == n) return NULL; }
return (void *)s; // fuck clang return NULL;
} }
char *strchr(const char *s, int c) char *strchr(const char *s, int c) {
{ do {
while(*s && *s != c) ++s; if(*s == c) return (char *)s;
if(*s != c) return NULL; } while(*s++);
return (void *)s; // fuck clang return NULL;
} }
size_t strcspn(const char *s1, const char *s2) size_t strspn(const char *s1, const char *s2) {
{
size_t i = 0; size_t i = 0;
while(*s1) { for(; *s1; ++s1) {
if(strchr(s2, *s1) != NULL) { if(strchr(s2, *s1) == NULL) {
break; break;
} }
++s1;
++i; ++i;
} }
return 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) { while(*s1) {
if(strchr(s2, *s1) == NULL) { if(strchr(s2, *s1) == NULL) {
break; break;
@ -156,26 +160,47 @@ char *strpbrk(const char *s1, const char *s2)
return (char *)s1; return (char *)s1;
} }
char *strstr(const char *s1, const char *s2) char *strrchr(const char *s, int c) {
{ char const *last = NULL;
if(!*s2) return (char *)s1; 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); size_t len = strlen(s2);
while(*s1 != 0) { for(; *s1 != 0; ++s1) {
bool match = true; if(strncmp(s1, s2, len) == 0) return (char *)s1;
for(size_t i = 0; i != len; ++i) {
if(!*s1 || s1[i] != s2[i]) {
match = false;
break;
}
}
++s1;
if(match) return (char *)s1;
} }
return NULL; 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) { switch(errnum) {
case 0: return "No errors"; case 0: return "No errors";
case EDOM: return "Value is out of domain of the function"; case EDOM: return "Value is out of domain of the function";

View File

@ -6,3 +6,4 @@
#define _con(a,b) a ## b #define _con(a,b) a ## b
#define _countof(arr) (sizeof (arr) / sizeof ((arr)[0]))

View File

@ -13,3 +13,9 @@
|| defined(_os_linux)) || defined(_os_linux))
#error "Unsupported OS" #error "Unsupported OS"
#endif #endif
// OS-dependent IO Functions
void _os_file_write(void* ctx, size_t n, const char str[]);
_Noreturn void _os_exit(int code);
void _os_init_eh();
typedef struct FILE FILE;

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "_compiler.h" #include "_compiler.h"
#include "_macros.h"
extern void _assert_error( extern void _assert_error(
char *cond, char *cond,

View File

@ -3,19 +3,24 @@
typedef int sig_atomic_t; typedef int sig_atomic_t;
// TODO: implement this // TODO: idk about SIG_ERR, for now this
#define SIG_DFL 0 #define SIG_ERR ((void(*)(int))0)
#define SIG_ERR 1 #define SIG_DFL _signal_default_handler
#define SIG_IGN 2 #define SIG_IGN _signal_ignore_handler
// not sure why but windows picked these, we can change it later // Note(bumbread): from the impl standpoint the numbers are arbitrary
#define SIGINT 2 #define _SIG_MIN 0
#define SIGILL 4 #define SIGINT 1
#define SIGFPE 8 #define SIGILL 2
#define SIGSEGV 11 #define SIGFPE 3
#define SIGTERM 15 #define SIGSEGV 4
#define SIGBREAK 21 #define SIGTERM 5
#define SIGABRT 22 #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); void (*signal(int sig, void (*func)(int)))(int);
int raise(int sig); int raise(int sig);

View File

@ -6,6 +6,10 @@
typedef struct FILE FILE; typedef struct FILE FILE;
typedef int64_t fpos_t; typedef int64_t fpos_t;
#if !defined(NULL)
#define NULL ((void *)0)
#endif
#if !defined(__STDC_LIB_EXT1__) #if !defined(__STDC_LIB_EXT1__)
#define __STDC_LIB_EXT1__ #define __STDC_LIB_EXT1__
typedef int errno_t; typedef int errno_t;
@ -40,7 +44,11 @@ typedef int64_t fpos_t;
#define SEEK_END 2 #define SEEK_END 2
#define SEEK_SET 0 #define SEEK_SET 0
#ifdef _os_win
#define TMP_MAX SHORT_MAX
#else
#define TMP_MAX INT_MAX #define TMP_MAX INT_MAX
#endif
extern FILE *stdout, *stderr, *stdin; extern FILE *stdout, *stderr, *stdin;

View File

@ -12,6 +12,9 @@
#endif #endif
#endif #endif
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
// typedef struct div_t { // typedef struct div_t {
// int quot; // int quot;
// int rem; // int rem;
@ -55,11 +58,11 @@ void free(void *ptr);
void *malloc(size_t size); void *malloc(size_t size);
void *realloc(void *ptr, size_t size); void *realloc(void *ptr, size_t size);
// _Noreturn void abort(void); _Noreturn void abort(void);
// int atexit(void (*func)(void)); // int atexit(void (*func)(void));
// int at_quick_exit(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); // char *getenv(const char *name);
// _Noreturn void quick_exit(int status); // _Noreturn void quick_exit(int status);
// int system(const char *string); // int system(const char *string);

View File

@ -1,6 +1,11 @@
#pragma once #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 <stddef.h>
#if !defined(NULL) #if !defined(NULL)
#define NULL ((void *)0) #define NULL ((void *)0)
#endif #endif

View File

@ -4,10 +4,31 @@
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <stdbool.h>
#include <inttypes.h> #include <inttypes.h>
#include <string.h>
#include <signal.h>
int test() {
static int a = 2;
a += 1;
return a;
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
uint64_t mynumber = 4; test();
printf("Hello, guys %"PRIu64"\n", mynumber); 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; return 0;
} }