From 88ef3bf81f80b50c04d7e9328846eb3e53a7cbba Mon Sep 17 00:00:00 2001 From: bumbread Date: Mon, 20 Jun 2022 17:28:03 +1100 Subject: [PATCH] Separate out platform stuff --- bake.cmd | 2 +- inc/_compiler.h | 26 - inc/_os.h | 43 -- inc/_platform.h | 55 -- inc/assert.h | 1 + src/code/assert.c | 21 - src/code/math/round.c | 3 +- src/code/signal.c | 46 -- src/code/stdio/files.c | 65 -- src/code/stdio/fmt_print.h | 723 ---------------------- src/code/stdio/stdio.c | 67 -- src/code/{stdlib.c => stdlib/algorithm.c} | 0 src/code/stdlib/{conv.c => conversion.c} | 0 src/code/stdlib/env.c | 40 -- src/code/stdlib/{rand.c => random.c} | 0 src/win/win.h | 13 +- src/win/win_assert.c | 21 + src/win/win_entry.c | 96 --- src/win/win_env.c | 35 -- src/win/win_environment.c | 147 +++++ src/win/{win_mem.c => win_heap.c} | 30 +- src/win/win_io.c | 134 ---- src/win/{win_except.c => win_signal.c} | 66 +- src/win/win_stack_trace.c | 26 + src/win/win_stdio.c | 58 ++ src/win/{win_mutex.c => win_threads.c} | 4 +- src/win/win_time.c | 22 +- test/test_os.c | 8 + 28 files changed, 334 insertions(+), 1418 deletions(-) delete mode 100644 inc/_compiler.h delete mode 100644 inc/_os.h delete mode 100644 inc/_platform.h delete mode 100644 src/code/assert.c delete mode 100644 src/code/signal.c delete mode 100644 src/code/stdio/files.c delete mode 100644 src/code/stdio/fmt_print.h delete mode 100644 src/code/stdio/stdio.c rename src/code/{stdlib.c => stdlib/algorithm.c} (100%) rename src/code/stdlib/{conv.c => conversion.c} (100%) delete mode 100644 src/code/stdlib/env.c rename src/code/stdlib/{rand.c => random.c} (100%) create mode 100644 src/win/win_assert.c delete mode 100644 src/win/win_entry.c delete mode 100644 src/win/win_env.c create mode 100644 src/win/win_environment.c rename src/win/{win_mem.c => win_heap.c} (75%) delete mode 100644 src/win/win_io.c rename src/win/{win_except.c => win_signal.c} (63%) create mode 100644 src/win/win_stack_trace.c create mode 100644 src/win/win_stdio.c rename src/win/{win_mutex.c => win_threads.c} (98%) create mode 100644 test/test_os.c diff --git a/bake.cmd b/bake.cmd index 88c572e..4c93e61 100644 --- a/bake.cmd +++ b/bake.cmd @@ -31,7 +31,7 @@ mkdir bin\%PLATFORM% del ciabatta.lib 2> nul for /R src\%PLATFORM% %%F in (*.c) do ( echo %%F - clang -c -o bin\%PLATFORM%\%%~nF.obj %%F %CIABATTA_OPTIONS% + clang -Isrc/win -c -o bin\%PLATFORM%\%%~nF.obj %%F %CIABATTA_OPTIONS% ) for /R src\code %%F in (*.c) do ( echo %%F diff --git a/inc/_compiler.h b/inc/_compiler.h deleted file mode 100644 index 44a33cb..0000000 --- a/inc/_compiler.h +++ /dev/null @@ -1,26 +0,0 @@ - -#pragma once - -#if defined(_MSC_VER) && !defined(__clang__) - #define _compiler_msvc -#endif - -#if defined(__GNUC__) && !defined(__clang__) - #define _compiler_gcc -#endif - -#if defined(__clang__) - #define _compiler_clang -#endif - -#if defined(__CUIKC__) - #define _compiler_cuik -#endif - -#if !(defined(_compiler_msvc) \ - || defined(_compiler_gcc) \ - || defined(_compiler_cuik) \ - || defined(_compiler_clang)) - #error "Unsupported Compiler" -#endif - diff --git a/inc/_os.h b/inc/_os.h deleted file mode 100644 index 96c8468..0000000 --- a/inc/_os.h +++ /dev/null @@ -1,43 +0,0 @@ - -#pragma once -#include - -#if defined(_WIN32) - #define _os_win -#endif - -#if defined(__linux__) && !defined(__ANDROID__) - #define _os_linux -#endif - -#if !(defined(_os_win) \ - || defined(_os_linux)) - #error "Unsupported OS" -#endif - -// OS-dependent IO Functions - -// TODO: see if we need this or will it be easier for linux to just pass -// the mode string. -typedef struct _OS_ModeFlags { - int base_mode; - int binary; - int update; - int exclusive; -} _OS_ModeFlags; - -typedef struct FILE FILE; - -void _os_print_stack_trace(); - -int _os_del_file(char const *filename); -int _os_mov_file(char const *old, char const *new); -char *_os_tmpname(char *buffer); -FILE *_os_fopen(char const *restrict name, _OS_ModeFlags flags); -int _os_fclose(FILE *file); -void _os_file_write(void* ctx, size_t n, const char str[]); -void _os_file_write_char(void* ctx, char ch); - -void _os_init_eh(); - -_Noreturn void _os_exit(int code); diff --git a/inc/_platform.h b/inc/_platform.h deleted file mode 100644 index 78a67f1..0000000 --- a/inc/_platform.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -#include -#include -#include - -// Microsoft uses this to refer to the secure functions so we'll allow it -#ifdef __STDC_WANT_SECURE_LIB__ - #define __STDC_WANT_LIB_EXT1__ 1 -#endif - -// Compiler Identification - -#if defined(_MSC_VER) && !defined(__clang__) - #define _compiler_msvc -#endif - -#if defined(__GNUC__) && !defined(__clang__) - #define _compiler_gnu -#endif - -#if defined(__clang__) - #define _compiler_clang -#endif - -#if defined(__CUIKC__) - #define _compiler_cuik -#endif - -#if !(defined(_compiler_msvc) \ - || defined(_compiler_gnu) \ - || defined(_compiler_cuik) \ - || defined(_compiler_clang)) - #error "Unsupported Compiler" -#endif - -// OS Identification - -#if defined(_WIN32) - #define _os_win -#endif - -#if defined(__linux__) && !defined(__ANDROID__) - #define _os_linux -#endif - -#if !(defined(_os_win) \ - || defined(_os_linux)) - #error "Unsupported OS" -#endif - -#ifdef __STDC_WANT_LIB_EXT1__ - typedef int errno_t; - typedef size_t rsize_t; -#endif - diff --git a/inc/assert.h b/inc/assert.h index 02dd3d8..c321100 100644 --- a/inc/assert.h +++ b/inc/assert.h @@ -1,3 +1,4 @@ + #pragma once #if !defined(__func__) diff --git a/src/code/assert.c b/src/code/assert.c deleted file mode 100644 index 4446259..0000000 --- a/src/code/assert.c +++ /dev/null @@ -1,21 +0,0 @@ - -#include - -#include // printf -#include // abort -#include <_os.h> // stack trace - -void _Noreturn _assert( - char const *cond, - char const *func, - char const *file, - int line -) { - printf("Assertion failed: %s\n", cond); - printf(" Function: %s\n", func); - printf(" File: %s\n", file); - printf(" Line: %d\n", line); - printf("Trace:\n"); - _os_print_stack_trace(); - abort(); -} diff --git a/src/code/math/round.c b/src/code/math/round.c index 96a6659..230d138 100644 --- a/src/code/math/round.c +++ b/src/code/math/round.c @@ -8,8 +8,7 @@ #define asuint64(x) ((union {double f; uint64_t i;}){x}).i #define asdouble(x) ((union {double f; uint64_t i;}){x}).f -#include <_compiler.h> -#if defined(_compiler_clang) || defined(_compiler_gcc) +#if defined(__GNUC__) || defined(__clang__) #define just_do_it(t) __attribute__((unused)) volatile t #else #define just_do_it(t) volatile t diff --git a/src/code/signal.c b/src/code/signal.c deleted file mode 100644 index 7b9c196..0000000 --- a/src/code/signal.c +++ /dev/null @@ -1,46 +0,0 @@ - -#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/src/code/stdio/files.c b/src/code/stdio/files.c deleted file mode 100644 index bca958b..0000000 --- a/src/code/stdio/files.c +++ /dev/null @@ -1,65 +0,0 @@ - -#include -#include <_os.h> - -FILE *stdout; -FILE *stderr; -FILE *stdin; - -int remove(const char *filename) -{ - return _os_del_file(filename); -} - -int rename(const char *old, const char *new) -{ - return _os_mov_file(old, new); -} - -char *tmpnam(char *s) { - static char static_buffer[L_tmpnam]; - char *buffer = s; - if(s == NULL) buffer = static_buffer; - return _os_tmpname(buffer); -} - -FILE *fopen(const char *restrict filename, const char *restrict mode) -{ - // Basically defined UB here by introducing missing modes - // It is simpler to implement that way I think. - int base_mode = mode[0]; - int binary = 0; - int exclusive = 0; - int update = 0; - for(; *mode != 0; ++mode) { - if(*mode == 'x') exclusive = 1; - if(*mode == 'b') binary = 1; - if(*mode == '+') update = 1; - } - if(base_mode == 'r' && exclusive) return NULL; - if(base_mode == 'a' && exclusive) return NULL; - - _OS_ModeFlags mode_flags = { - .base_mode = base_mode, - .binary = binary, - .update = update, - .exclusive = exclusive, - }; - - return _os_fopen(filename, mode_flags); -} - -int fclose(FILE *stream) -{ - return _os_fclose(stream); -} - -// TODO:kekw: -FILE *freopen( - const char *restrict filename, - const char *restrict mode, - FILE *restrict stream) -{ - fclose(stream); - return NULL; -} diff --git a/src/code/stdio/fmt_print.h b/src/code/stdio/fmt_print.h deleted file mode 100644 index 3f993b9..0000000 --- a/src/code/stdio/fmt_print.h +++ /dev/null @@ -1,723 +0,0 @@ - -#include -#include -#include -#include -#include -#include - -// This stuff is kinda related to what's going on in this file, so I left it -// in a rather ugly manner here. -#if !defined(once) - #define once - - #define countof(arr) (sizeof(arr)/sizeof(arr[0])) - - #define CALL_PRINTF(fmt_func, ctx, out, fmt) \ - va_list args; \ - va_start(args, fmt); \ - int result = fmt_func(ctx, out, fmt, args); \ - va_end(args) - - enum ArgLength { - LEN_HH, - LEN_H, - LEN_I, - LEN_L, - LEN_LL, - LEN_J, - LEN_Z, - LEN_T, - } typedef ArgLength; - - enum ArgConv { - CONV_INT, - CONV_FLT, - CONV_EXP, - CONV_SCI, - CONV_CHAR, - CONV_STR, - CONV_PTR, - CONV_N, - CONV_PERCENT, - } typedef ArgConv; - - struct Format typedef Format; - struct Format { - bool flag_left; - bool flag_sign; - bool flag_space; - bool flag_form; - bool flag_zero; - bool flag_upper; - bool flag_unsigned; - int base; - int width; - int prec; - ArgLength arg_len; - ArgConv arg_conv; - }; - - inline static uint64_t get_int_arg( - Format *fmt, - va_list *args, - bool *signp - ) { - bool sign = 0; - uint64_t num = 0; - - // Read the integer from the args and split it into tuple of (sign, digits) - // If we've got HH or H we need to parse as int, and do the necessary conv - // to unsigned if needed. - if(fmt->arg_len < LEN_I) { - int ch = va_arg(*args, int); - if(ch < 0) { - if(fmt->flag_unsigned) { - num = ch + (fmt->arg_len == LEN_HH? UCHAR_MAX : USHRT_MAX); - } - else { - num = -ch; - sign = 1; - } - } - } - // Otherwise we see whether the number is signed or unsigned. For unsigned - // numbers we just parse according to the length, for signed we do that - // plus handle the sign - else if(fmt->flag_unsigned) { - switch(fmt->arg_len) { - case LEN_I: num = va_arg(*args, unsigned int); break; - case LEN_L: num = va_arg(*args, unsigned long); break; - case LEN_LL: num = va_arg(*args, unsigned long long); break; - case LEN_J: num = va_arg(*args, uintmax_t); break; - case LEN_Z: num = va_arg(*args, size_t); break; - case LEN_T: num = va_arg(*args, size_t); break; - default:; - } - } - else { - // TODO: signed size_t - int64_t i = 0; - switch(fmt->arg_len) { - case LEN_I: i = va_arg(*args, int); break; - case LEN_L: i = va_arg(*args, long); break; - case LEN_LL: i = va_arg(*args, long long); break; - case LEN_J: i = va_arg(*args, uintmax_t); break; - case LEN_Z: i = va_arg(*args, int64_t); break; - case LEN_T: i = va_arg(*args, ptrdiff_t); break; - default:; - } - if(i < 0) { - num = -i; - sign = 1; - } - else { - num = i; - } - } - - *signp = sign; - return num; - } -#endif - -// Generic printf function that is used to print to stdout, strings and files. -// The basic idea is to make generic printf that uses output function as -// parameter and that function is distinct for printing to files, strings etc. -// Furthermore, this generic printf is abbstracted over character type, and -// depending on the macro fchar it could print in char's or wchar_t's. - -typedef void (suffix(out_func_t))(void* ctx, fchar ch); - -inline static int suffix(fmt_atoi)(fchar const *str, int *value) { - int i = 0; - int val = 0; - while('0' <= str[i] && str[i] <= '9') { - int digit = str[i] - '0'; - if(val > (INT_MAX - digit) / 10) { - return -1; - } - val = 10*val + digit; - ++i; - } - *value = val; - return i; -} - -inline static int suffix(fmt_parse)( - Format *format, - fchar const *str, - va_list *args -) { - *format = (Format){0}; - // Parse flags - int i = 0; - for(;;) { - if (str[i] == '-') format->flag_left = true; - else if(str[i] == '+') format->flag_sign = true; - else if(str[i] == ' ') format->flag_space = true; - else if(str[i] == '#') format->flag_form = true; - else if(str[i] == '0') format->flag_zero = true; - else break; - ++i; - } - // Optional width specifier - int width = 0; - if(str[i] == '*') { - ++i; - width = va_arg(*args, int); - if(width < 0) { - width = -width; - format->flag_zero = true; - } - } - else { - int width_len = suffix(fmt_atoi)(str+i, &width); - if(width_len < 0) return -1; - i += width_len; - } - // Optional precision specifier - int prec = 0; - if(str[i] == '.') { - ++i; - if(str[i] == '*') { - ++i; - prec = va_arg(*args, int); - if(prec < 0) { - prec = 0; - } - } - else { - int prec_len = suffix(fmt_atoi)(str+i, &prec); - if(prec_len < 0) return -1; - i += prec_len; - } - } - format->width = width; - format->prec = prec; - // Optional length modifier - format->arg_len = LEN_I; - if(str[i] == 'h') { - ++i; - format->arg_len = LEN_H; - if(str[i] == 'h') { - ++i; - format->arg_len = LEN_HH; - } - } - else if(str[i] == 'l') { - ++i; - format->arg_len = LEN_L; - if(str[i] == 'l') { - ++i; - format->arg_len = LEN_LL; - } - } - else if(str[i] == 'j') { - ++i; - format->arg_len = LEN_J; - } - else if(str[i] == 'z') { - ++i; - format->arg_len = LEN_Z; - } - else if(str[i] == 't') { - ++i; - format->arg_len = LEN_T; - } - else if(str[i] == 'L') { - ++i; - format->arg_len = LEN_L; - } - // Conversion specifier - switch(str[i]) { - case 'd': - case 'i': - format->arg_conv = CONV_INT; - format->base = 10; - break; - case 'u': - format->arg_conv = CONV_INT; - format->flag_unsigned = true; - format->base = 10; - break; - case 'o': - format->arg_conv = CONV_INT; - format->flag_unsigned = true; - format->base = 8; - break; - case 'x': - format->arg_conv = CONV_INT; - format->flag_unsigned = true; - format->base = 16; - break; - case 'X': - format->arg_conv = CONV_INT; - format->flag_unsigned = true; - format->flag_upper = true; - format->base = 16; - break; - case 'f': - format->arg_conv = CONV_FLT; - format->base = 10; - break; - case 'F': - format->arg_conv = CONV_FLT; - format->flag_upper = true; - format->base = 10; - break; - case 'e': - format->arg_conv = CONV_EXP; - format->base = 10; - break; - case 'E': - format->arg_conv = CONV_EXP; - format->flag_upper = true; - format->base = 10; - break; - case 'g': - format->arg_conv = CONV_SCI; - format->base = 10; - break; - case 'G': - format->arg_conv = CONV_SCI; - format->flag_upper = true; - format->base = 10; - break; - case 'a': - format->arg_conv = CONV_FLT; - format->base = 16; - break; - case 'A': - format->arg_conv = CONV_FLT; - format->flag_upper = true; - format->base = 16; - break; - case 'c': - format->arg_conv = CONV_CHAR; - break; - case 's': - format->arg_conv = CONV_STR; - break; - case 'p': - format->arg_conv = CONV_PTR; - break; - case 'n': - format->arg_conv = CONV_N; - break; - case '%': - format->arg_conv = CONV_PERCENT; - break; - default: return -1; - } - ++i; - // Ignoring flags etc - if(format->flag_sign && format->flag_zero) { - format->flag_zero = 0; - } - if(format->flag_sign && format->flag_space) { - format->flag_space = 0; - } - - if(format->prec != 0) { - format->flag_zero = 0; - } - else if(format->flag_zero) { - // HACK: NOTE: I hate printf formats - format->prec = format->width; - format->width = 0; - } - if(format->arg_conv == CONV_FLT && format->prec == 0) { - format->prec = 6; - } - return i; -} - -inline static int suffix(fmt_fprint_int)( - void *ctx, - suffix(out_func_t) *out, - Format *fmt, - va_list *args -) { - int w = 0; - - bool sign; - uint64_t num = get_int_arg(fmt, args, &sign); - - // Find the actual length the number takes up - int prefix_len = 0; - int digits_num = 0; - if(fmt->flag_space || fmt->flag_sign || sign) { - prefix_len = 1; - } - if(num != 0 && fmt->flag_form) { - if(fmt->base == 16) prefix_len += 2; // 0x - if(fmt->base == 8) digits_num += 1; // 0 - } - - { - uint64_t digits = num; - do { - digits_num += 1; - digits /= fmt->base; - } while(digits != 0); - } - int s_len = prefix_len + digits_num; // length of significant chars - int d_len = s_len; // length of all displayed chars - int zpad = 0; // pre-pad of zeroes from precision - if(digits_num < fmt->prec) { - zpad = fmt->prec - digits_num; - d_len = s_len + zpad; - } - - // See if padding is necessary and extract info about padding - bool left_pad = false; - bool right_pad = true; - char pad_ch = ' '; - int pad_len = 0; - if(!sign && fmt->flag_space) { // make space part of pad - d_len += 1; - pad_len = 1; - } - if(d_len < fmt->width) { - pad_len = fmt->width - d_len; - } - if(fmt->flag_left) { - left_pad = true; - right_pad = false; - } - if(fmt->flag_zero) { - pad_ch = '0'; - } - - // Fill up an array of significant digits - char digits_arr[33] = {0}; - char *digits = digits_arr + countof(digits_arr); - { - uint64_t temp = num; - do { - int digit = temp % fmt->base; - char ch = 0; - if(digit < 10) ch = digit + '0'; - else if(fmt->flag_upper) ch = digit - 10 + 'A'; - else ch = digit - 10 + 'a'; - *--digits = ch; - temp /= fmt->base; - } while(temp != 0); - } - - // Start displaying number - // Left-pad if necessary - if(left_pad) while(pad_len--) { - out(ctx, pad_ch); - ++w; - } - - // Print sign - if(sign) { out(ctx, '-'); ++w; } - else if(fmt->flag_sign) { out(ctx, '+'); ++w; } - else if(fmt->flag_space) { out(ctx, ' '); ++w; } - - // Print 0x, 0X - if(num != 0 && fmt->base == 16 && fmt->flag_form) { - out(ctx, '0'); - if(fmt->flag_upper) out(ctx, 'X'); - else out(ctx, 'x'); - w += 2; - } - - // Print zpad - while(zpad--) { - out(ctx, '0'); - ++ w; - } - - // Print digit string - while(*digits != 0) { - out(ctx, *digits); - ++digits; - ++w; - } - - // Right-pad if necessary - if(right_pad) while(pad_len--) { - out(ctx, pad_ch); - ++w; - } - - return w; -} - -inline static int suffix(fmt_fprint_ptr)( - void *ctx, - suffix(out_func_t) *out, - Format *fmt, - va_list *args -) { - int w = 0; - uintptr_t num = va_arg(*args, uintptr_t); - - int s_len = 2 + 16; // length of significant chars - int d_len = s_len; // length of all displayed chars - int zpad = 0; // pre-pad of zeroes from precision - if(16 < fmt->prec) { - zpad = fmt->prec - 16; - d_len = s_len + zpad; - } - - // See if padding is necessary and extract info about padding - bool left_pad = true; - bool right_pad = false; - char pad_ch = ' '; - int pad_len = 0; - if(d_len < fmt->width) { - pad_len = fmt->width - d_len; - } - if(fmt->flag_left) { - left_pad = false; - right_pad = true; - } - if(fmt->flag_zero) { - pad_ch = '0'; - } - - // Fill up an array of significant digits - char digits_arr[33] = {0}; - char *digits = digits_arr + countof(digits_arr); - { - uint64_t temp = num; - do { - int digit = temp % 16; - char ch = 0; - if(digit < 10) ch = digit + '0'; - else if(fmt->flag_upper) ch = digit - 10 + 'A'; - else ch = digit - 10 + 'a'; - *--digits = ch; - temp /= 16; - } while(s_len-- != 0); - } - - // Start displaying number - // Left-pad if necessary - if(left_pad) while(pad_len--) { - out(ctx, pad_ch); - ++w; - } - - out(ctx, '0'); - out(ctx, 'x'); - w += 2; - - // Print zpad - while(zpad--) { - out(ctx, '0'); - ++ w; - } - - // Print digit string - while(*digits != 0) { - out(ctx, *digits); - ++digits; - ++w; - } - - // Right-pad if necessary - if(right_pad) while(pad_len--) { - out(ctx, pad_ch); - ++w; - } - - return w; -} - -inline static int suffix(fmt_fprint_char)( - void *ctx, - suffix(out_func_t) *out, - Format *fmt, - va_list *args -) { - int w = 0; - bool sign; - uint64_t num = get_int_arg(fmt, args, &sign); - - // Calculate padding - bool left_pad = true; - bool right_pad = false; - uint64_t pad = 0; - if(1 < fmt->width) { - pad = fmt->width - 1; - } - if(fmt->flag_left) { - left_pad = false; - right_pad = true; - } - - // Print left pad - if(left_pad) while(pad--) { - out(ctx, ' '); - ++w; - } - - out(ctx, num); - ++w; - - // Print right pad - if(right_pad) while(pad--) { - out(ctx, ' '); - ++w; - } - - return w; -} - -inline static int suffix(fmt_just_fucking_print_float_someone_improve_this_later)( - void *ctx, - suffix(out_func_t) *out, - Format *fmt, - va_list *args -) { - int w = 0; - double f = va_arg(*args, double); - uint64_t i = (uint64_t)f; - - char digits_arr[33] = {0}; - char *digits = digits_arr + countof(digits_arr); - { - uint64_t t = i; - do { - char ch = (t % 10) + '0'; - *--digits = ch; - t /= 10; - } while(t-- != 0); - } - - while(*digits != 0) { - out(ctx, *digits); - ++digits; - ++w; - } - - f -= i; - uint64_t nprec = fmt->prec; - if(nprec != 0) { - out(ctx, '.'); - w++; - } - - for(int i = 0; i != fmt->prec; ++i) { - f *= 10; - uint64_t digit = (uint64_t)f; - out(ctx, digit + '0'); - ++w; - f -= digit; - } - - return w; -} - - -inline static int suffix(fmt_fprint_str)( - void *ctx, - suffix(out_func_t) *out, - Format *fmt, - va_list *args -) { - int w = 0; - char *str = va_arg(*args, char *); - uint64_t len = strlen(str); - - // Calculate padding - bool left_pad = true; - bool right_pad = false; - uint64_t pad = 0; - if(len < fmt->width) { - pad = fmt->width - len; - } - if(fmt->flag_left) { - left_pad = false; - right_pad = true; - } - - // Print left pad - if(left_pad) while(pad--) { - out(ctx, ' '); - ++w; - } - - while(*str) { - out(ctx, *str++); - ++w; - } - - // Print right pad - if(right_pad) while(pad--) { - out(ctx, ' '); - ++w; - } - - return w; -} - -inline static int suffix(fmt_print)( - void *ctx, - suffix(out_func_t) *out, - const fchar *fmt, - va_list args -) { - int w = 0; // N chars output - int i = 0; // N chars read from fmt - while(fmt[i] != 0) { - if(fmt[i] == '%') { - ++i; - Format format; - int fmt_len = suffix(fmt_parse)(&format, fmt+i, &args); - if(fmt_len < 0) return -1; - i += fmt_len; - int written; - switch(format.arg_conv) { - case CONV_INT: { - written = suffix(fmt_fprint_int)(ctx, out, &format, &args); - } break; - case CONV_FLT: { - written = suffix(fmt_just_fucking_print_float_someone_improve_this_later)(ctx, out, &format, &args); - } break; - case CONV_EXP: { - written = suffix(fmt_just_fucking_print_float_someone_improve_this_later)(ctx, out, &format, &args); - } break; - case CONV_SCI: { - written = suffix(fmt_just_fucking_print_float_someone_improve_this_later)(ctx, out, &format, &args); - } break; - case CONV_CHAR: { - written = suffix(fmt_fprint_char)(ctx, out, &format, &args); - } break; - case CONV_STR: { - written = suffix(fmt_fprint_str)(ctx, out, &format, &args); - } break; - case CONV_PTR: { - written = suffix(fmt_fprint_ptr)(ctx, out, &format, &args); - } break; - case CONV_N: { - int *n = va_arg(args, int *); - *n = w; - written = 0; - } break; - case CONV_PERCENT: { - out(ctx, '%'); - written = 1; - } break; - if(written < 0) { - return -1; - } - w += written; - } - } - // Print non-formatted characters as god intended - else while(fmt[i] != '%' && fmt[i] != 0) { - out(ctx, fmt[i]); - ++i; - ++w; - } - } - return i; -} - diff --git a/src/code/stdio/stdio.c b/src/code/stdio/stdio.c deleted file mode 100644 index b018207..0000000 --- a/src/code/stdio/stdio.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include -#include -#include - -#include <_os.h> - -#define __STDC_WANT_LIB_EXT1__ 1 -#include - -// Instantiate generic printf function for byte strings -// TODO: instantiate wide char variants of print -#define suffix(name) name ## _char -#define fchar char -#define fstrlen(s, maxsize) strnlen_s(s, maxsize) -#include "fmt_print.h" - -typedef struct { - size_t used, capacity; - char* string; -} StrPrintCtx; - -static void string_write(void *ctx, char ch) { - StrPrintCtx *c = ctx; - c->string[c->used++] = ch; -} - -int fprintf(FILE *file, const char *restrict fmt, ...) { - CALL_PRINTF(fmt_print_char, file, _os_file_write_char, fmt); - return result; -} - -int printf(const char *restrict fmt, ...) { - CALL_PRINTF(fmt_print_char, stdout, _os_file_write_char, fmt); - return result; -} - -int snprintf(char *restrict s, size_t n, const char *restrict fmt, ...) { - StrPrintCtx ctx = { 0, n, s }; - CALL_PRINTF(fmt_print_char, &ctx, string_write, fmt); - return result; -} - -int sprintf(char *restrict s, const char *restrict fmt, ...) { - StrPrintCtx ctx = { 0, SIZE_MAX, s }; - CALL_PRINTF(fmt_print_char, &ctx, string_write, fmt); - return result; -} - -int vfprintf(FILE *file, const char *restrict fmt, va_list args) { - return fmt_print_char(file, _os_file_write_char, fmt, args); -} - -int vprintf(const char *restrict fmt, va_list args) { - return fmt_print_char(stdout, _os_file_write_char, fmt, args); -} - -int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list args) { - StrPrintCtx ctx = { 0, n, s }; - return fmt_print_char(&ctx, string_write, fmt, args); -} - -int vsprintf(char *restrict s, const char *restrict fmt, va_list args) { - StrPrintCtx ctx = { 0, SIZE_MAX, s }; - return fmt_print_char(&ctx, string_write, fmt, args); -} diff --git a/src/code/stdlib.c b/src/code/stdlib/algorithm.c similarity index 100% rename from src/code/stdlib.c rename to src/code/stdlib/algorithm.c diff --git a/src/code/stdlib/conv.c b/src/code/stdlib/conversion.c similarity index 100% rename from src/code/stdlib/conv.c rename to src/code/stdlib/conversion.c diff --git a/src/code/stdlib/env.c b/src/code/stdlib/env.c deleted file mode 100644 index d56f136..0000000 --- a/src/code/stdlib/env.c +++ /dev/null @@ -1,40 +0,0 @@ - -#include -#include - -#include <_os.h> - -typedef void (*ExitRoutine)(void); - -// The implementation shall support the registration -// of at least 32 functions. -static ExitRoutine _exit_routines[64]; -static int _exit_routine_count; - -_Noreturn void abort(void) { - raise(SIGABRT); - _os_exit(-69); -} - -int atexit(void (*func)(void)) { - if (_exit_routine_count >= COUNTOF(_exit_routines)) { - return 0; - } - - _exit_routines[_exit_routine_count++] = func; - return 1; -} - -_Noreturn void exit(int status) { - // doing them in reverse seems nicer - for (int i = _exit_routine_count; i--;) { - _exit_routines[i](); - } - - _os_exit(status); -} - -_Noreturn void _Exit(int status) { - // doesn't run atexit routines - _os_exit(status); -} diff --git a/src/code/stdlib/rand.c b/src/code/stdlib/random.c similarity index 100% rename from src/code/stdlib/rand.c rename to src/code/stdlib/random.c diff --git a/src/win/win.h b/src/win/win.h index f12b91b..77e4616 100644 --- a/src/win/win.h +++ b/src/win/win.h @@ -1,13 +1,12 @@ #pragma once -#include <_os.h> - #define WIN32_LEAN_AND_MEAN #include +#include +#include +#include -struct _os_heap { - HANDLE handle; -}; - -void _os_timing_init(void); +void _setup_timer(void); +void _setup_eh(); +void _setup_heap(); diff --git a/src/win/win_assert.c b/src/win/win_assert.c new file mode 100644 index 0000000..3d8563d --- /dev/null +++ b/src/win/win_assert.c @@ -0,0 +1,21 @@ + +#include + +#include +//#include // printf +#include // abort + +void _Noreturn _assert( + char const *cond, + char const *func, + char const *file, + int line +) { + // printf("Assertion failed: %s\n", cond); + // printf(" Function: %s\n", func); + // printf(" File: %s\n", file); + // printf(" Line: %d\n", line); + // printf("Trace:\n"); + // _os_print_stack_trace(); + abort(); +} diff --git a/src/win/win_entry.c b/src/win/win_entry.c deleted file mode 100644 index ed41fb3..0000000 --- a/src/win/win_entry.c +++ /dev/null @@ -1,96 +0,0 @@ - -#include <_os.h> - -#include -#include -#include -#include - -#include "win.h" - -extern int main(int argc, char** argv); - -// Some shell32.lib related crap -DECLSPEC_IMPORT LPWSTR GetCommandLineW(); -DECLSPEC_IMPORT LPWSTR* CommandLineToArgvW(LPCWSTR lpCmdLine, int* pNumArgs); - -int _wcsicmp(wchar_t const* s1, wchar_t const* s2) { - int diff; - do { - diff = *s1 - *s2; - } while(diff != 0 && *s1 != 0 && *s2 != 0); - return diff; -} - -static size_t count_wide_chars(const wchar_t* str) { - size_t len = 0; - while (str[len] != 0) len++; - return len; -} - -static bool convert_wide_chars_to_ansi(char* out, const wchar_t* str, size_t len) { - for (size_t i = 0; i < len; i++) { - wchar_t ch = *str++; - if (ch < 0 || 0x7F >= ch) { - *out++ = 0; - return false; - } - *out++ = ch; - } - - *out++ = 0; - return true; -} - -void mainCRTStartup() { - _os_timing_init(); - - HANDLE heap = GetProcessHeap(); - if (heap == NULL) { - ExitProcess(-42069); - } - - int arg_count; - LPWSTR* args_wide = CommandLineToArgvW(GetCommandLineW(), &arg_count); - if (!args_wide) { - ExitProcess(-69420); - } - - char** args = HeapAlloc(heap, 0, arg_count * sizeof(char*)); - if (arg_count == 0) { - arg_count = 1; - args[0] = ""; - } - - // Convert wide chars into ANSI - for (int i = 0; i < arg_count; i++) { - size_t wide_len = count_wide_chars(args_wide[i]) + 1; - args[i] = HeapAlloc(heap, 0, wide_len); - - convert_wide_chars_to_ansi(args[i], args_wide[i], wide_len); - } - - // Initialize terminal - stdout = (FILE*) GetStdHandle(STD_OUTPUT_HANDLE); - stderr = (FILE*) GetStdHandle(STD_ERROR_HANDLE); - stdin = (FILE*) GetStdHandle(STD_INPUT_HANDLE); - - // Initialize heap - _os_heap heap_data = { - .handle = heap, - }; - _heap_setup(&heap_data); - - srand(0); - setlocale(LC_ALL, "C"); - _os_init_eh(); - - int exit_code = main(arg_count, args); - - // we call exit because we want atexit routines run - exit(exit_code); -} - -// This symbol is required to be present if we're using floating-point -// numbers -int _fltused=0; diff --git a/src/win/win_env.c b/src/win/win_env.c deleted file mode 100644 index f72b20e..0000000 --- a/src/win/win_env.c +++ /dev/null @@ -1,35 +0,0 @@ - -#include - -#include "win.h" - -char *getenv(const char *name) { - // The string pointed to shall not be modified by the program, but may be - // overwritten by a subsequent call to the getenv function - static size_t env_string_cap; - static char* env_string; - - DWORD env_length = GetEnvironmentVariable(name, NULL, 0); - if (env_length == 0) { - return 0; - } - - // Upscale the internal string - if (env_length > env_string_cap) { - char* newstr = realloc(env_string, env_length); - if (newstr == NULL) { - free(env_string); - return 0; - } - - env_string = newstr; - env_string_cap = env_length; - } - - GetEnvironmentVariable(name, env_string, env_length); - return env_string; -} - -_Noreturn void _os_exit(int code) { - ExitProcess(code); -} diff --git a/src/win/win_environment.c b/src/win/win_environment.c new file mode 100644 index 0000000..a30072b --- /dev/null +++ b/src/win/win_environment.c @@ -0,0 +1,147 @@ + +#include +#include +#include +#include +#include + +#include + +// Windows symbols because windows +int _fltused=0; + +extern int main(int argc, char** argv); + +// Exit routines +#define ATEXIT_FUNC_COUNT 64 +static void (*atexit_funcs[ATEXIT_FUNC_COUNT])(void); +static int atexit_func_count; + + +int _wcsicmp(wchar_t const* s1, wchar_t const* s2) { + int diff; + do { + diff = *s1 - *s2; + } while(diff != 0 && *s1 != 0 && *s2 != 0); + return diff; +} + +static size_t count_wide_chars(const wchar_t* str) { + size_t len = 0; + while (str[len] != 0) len++; + return len; +} + +static bool wchar_to_ansi(char* out, const wchar_t* str, size_t len) { + for (size_t i = 0; i < len; i++) { + wchar_t ch = *str++; + if (ch < 0 || ch > 0x7F) { + *out++ = 0; + return false; + } + *out++ = ch; + } + + *out++ = 0; + return true; +} + +static char **get_command_args(int *argc_ptr) { + int argc; + char** args; + + LPCWSTR command_line = GetCommandLineW(); + LPWSTR* args_wide = CommandLineToArgvW(command_line, &argc); + if (!args_wide || argc <= 0) { + ExitProcess(-69420); + } + + args = calloc(argc, sizeof(char*)); + + // Convert wide chars into ANSI + for (int i = 0; i < argc; i++) { + size_t arg_len = count_wide_chars(args_wide[i]); + args[i] = malloc(arg_len+1); + wchar_to_ansi(args[i], args_wide[i], arg_len+1); + } + + *argc_ptr = argc; + return args; +} + + +void mainCRTStartup() { + // Initialize standard pipe handles + stdout = (FILE*) GetStdHandle(STD_OUTPUT_HANDLE); + stderr = (FILE*) GetStdHandle(STD_ERROR_HANDLE); + stdin = (FILE*) GetStdHandle(STD_INPUT_HANDLE); + + // Set-up some platform stuff + _setup_heap(); + _setup_eh(); + _setup_timer(); + + // Set-up CRT stuff + srand(0); + setlocale(LC_ALL, "C"); + + // Parse command-line arguments + int argc; + char **args = get_command_args(&argc); + int exit_code = main(argc, args); + + // we call exit because we want atexit routines run + exit(exit_code); +} + + +_Noreturn void abort(void) { + raise(SIGABRT); + ExitProcess(-69); +} + +int atexit(void (*func)(void)) { + if (atexit_func_count >= ATEXIT_FUNC_COUNT) { + return 0; + } + atexit_funcs[atexit_func_count++] = func; + return 1; +} + +_Noreturn void exit(int status) { + for (int i = atexit_func_count; i--;) { + atexit_funcs[i](); + } + ExitProcess(status); +} + +_Noreturn void _Exit(int status) { + ExitProcess(status); +} + +char *getenv(const char *name) { + // The string pointed to shall not be modified by the program, but may be + // overwritten by a subsequent call to the getenv function + static size_t env_string_cap; + static char* env_string; + + DWORD env_length = GetEnvironmentVariable(name, NULL, 0); + if (env_length == 0) { + return 0; + } + + // Upscale the internal string + if (env_length > env_string_cap) { + char* newstr = realloc(env_string, env_length); + if (newstr == NULL) { + free(env_string); + return 0; + } + + env_string = newstr; + env_string_cap = env_length; + } + + GetEnvironmentVariable(name, env_string, env_length); + return env_string; +} diff --git a/src/win/win_mem.c b/src/win/win_heap.c similarity index 75% rename from src/win/win_mem.c rename to src/win/win_heap.c index eace9fc..ece3e54 100644 --- a/src/win/win_mem.c +++ b/src/win/win_heap.c @@ -1,13 +1,9 @@ -#include -#include +#include #include +#include -#include "win.h" - -// TODO: lock the heap before allocation (?) - -HANDLE _heap; +static HANDLE heap_handle; static bool is_power_of_two(size_t s) { return (s & (s-1)) == 0; @@ -17,8 +13,11 @@ static intptr_t align_forward(intptr_t p, size_t a) { return (p+a-1)&~(a-1); } -void _heap_setup(_os_heap *heap) { - _heap = heap->handle; +void _setup_heap() { + heap_handle = GetProcessHeap(); + if (heap_handle == NULL) { + ExitProcess(-42069); + } } void *aligned_alloc(size_t alignment, size_t size) { @@ -39,7 +38,7 @@ void *aligned_alloc(size_t alignment, size_t size) { if(alignment > 8) { min_req_size += alignment; } - void *block_start = HeapAlloc(_heap, 0, min_req_size); + void *block_start = HeapAlloc(heap_handle, 0, min_req_size); intptr_t block_start_i = (intptr_t)block_start; intptr_t aligned_block_start_i = align_forward(block_start_i, alignment); void *aligned_block_start = (void *)aligned_block_start_i; @@ -53,7 +52,7 @@ void *calloc(size_t nmemb, size_t size) { if(nmemb > SIZE_MAX/size) { return NULL; } - void *block_start = HeapAlloc(_heap, HEAP_ZERO_MEMORY, size*nmemb); + void *block_start = HeapAlloc(heap_handle, HEAP_ZERO_MEMORY, size*nmemb); return block_start; } @@ -61,7 +60,7 @@ void free(void *ptr) { if(ptr == NULL) { return; } - HeapFree(_heap, 0, ptr); + HeapFree(heap_handle, 0, ptr); } void *malloc(size_t size) { @@ -72,11 +71,12 @@ void *realloc(void *ptr, size_t size) { if (ptr == NULL) { if (size == 0) return NULL; - return HeapAlloc(_heap, 0, size); + return HeapAlloc(heap_handle, 0, size); } else if (size == 0) { - HeapFree(_heap, 0, ptr); + HeapFree(heap_handle, 0, ptr); return NULL; } else { - return HeapReAlloc(_heap, 0, ptr, size); + return HeapReAlloc(heap_handle, 0, ptr, size); } } + diff --git a/src/win/win_io.c b/src/win/win_io.c deleted file mode 100644 index fed519a..0000000 --- a/src/win/win_io.c +++ /dev/null @@ -1,134 +0,0 @@ - -#include "win.h" - -#include -#include -#include -#include - -// It's just mapped directly to HANDLE -struct FILE { - int unused; -}; - -int _os_del_file(char const *filename) { - int ok = DeleteFileA(filename); - return ok != 0; -} - -int _os_mov_file(char const *old, char const *new) { - int ok = MoveFileA(old, new); - return ok != 0; -} - -char *_os_tmpname(char *buffer) { - static UINT uniq = 0; - DWORD path_len = GetTempPathA(L_tmpnam, buffer); - if(path_len == 0) return NULL; - UINT ok = GetTempFileNameA(buffer, "", uniq, buffer); - if(ok == 0) return NULL; - return buffer; -} - -FILE *_os_fopen(char const *restrict name, _OS_ModeFlags flags) { - DWORD desaddr = 0; - DWORD share = 0; - DWORD disp = 0; - switch(flags.base_mode) { - case 'r': { - desaddr = GENERIC_READ; - if(!flags.update) { - share = FILE_SHARE_READ; - } - disp = OPEN_EXISTING; - if(flags.update) { - disp = OPEN_ALWAYS; - } - } break; - case 'w': { - desaddr = GENERIC_WRITE; - disp = CREATE_ALWAYS; - } break; - case 'a': { - desaddr = GENERIC_WRITE; - - } break; - } - if(flags.exclusive) { - disp = CREATE_NEW; - } - - HANDLE fileHandle = CreateFileA( - name, - desaddr, - share, - NULL, - disp, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - FILE *file = (FILE *)fileHandle; - if(fileHandle == INVALID_HANDLE_VALUE) { - file = NULL; - } - - return file; -} - -int _os_fclose(FILE *file) { - HANDLE fileHandle = (HANDLE)file; - BOOL ok = CloseHandle(fileHandle); - return ok != 0; -} - -void _os_file_write(void* ctx, size_t n, const char str[]) { - DWORD written = 0; - WriteFile((HANDLE) ctx, str, n, &written, NULL); -} - -void _os_file_write_char(void* ctx, char ch) { - DWORD written = 0; - WriteFile((HANDLE) ctx, &ch, 1, &written, NULL); -} - -int system(const char* string) { - int wchars_required = MultiByteToWideChar(65001 /* UTF8 */, 0, string, -1, NULL, 0); - wchar_t* cmd_line = malloc(sizeof(L"cmd.exe ") + (wchars_required * sizeof(wchar_t))); - if (cmd_line == NULL) { - goto error; - } - - memcpy(cmd_line, L"cmd.exe ", sizeof(L"cmd.exe ")); - MultiByteToWideChar(65001 /* UTF8 */, 0, string, -1, cmd_line + sizeof("cmd.exe ") - 1, wchars_required); - - STARTUPINFOW si = { - .cb = sizeof(STARTUPINFOW), - .dwFlags = STARTF_USESTDHANDLES, - .hStdInput = GetStdHandle(STD_INPUT_HANDLE), - .hStdError = GetStdHandle(STD_ERROR_HANDLE), - .hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE) - }; - PROCESS_INFORMATION pi = {}; - - if (!CreateProcessW(NULL, cmd_line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { - goto error; - } - - // Wait until child process exits. - WaitForSingleObject(pi.hProcess, INFINITE); - - DWORD exit_code; - if (!GetExitCodeProcess(pi.hProcess, &exit_code)) { - goto error; - } - - // Close process and thread handles. - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - free(cmd_line); - return exit_code; - - error: - free(cmd_line); - return -1; -} diff --git a/src/win/win_except.c b/src/win/win_signal.c similarity index 63% rename from src/win/win_except.c rename to src/win/win_signal.c index b10c88a..d4e7627 100644 --- a/src/win/win_except.c +++ b/src/win/win_signal.c @@ -1,10 +1,7 @@ -#include <_os.h> - -#define WIN32_LEAN_AND_MEAN -#include -#include +#include +#include #include #include #include @@ -54,32 +51,45 @@ static LONG _win32_handler(EXCEPTION_POINTERS *ExceptionInfo) { return EXCEPTION_CONTINUE_SEARCH; } -void _os_print_stack_trace() { - HANDLE process = GetCurrentProcess(); - SymInitialize(process, NULL, TRUE); - void *stack[128]; - USHORT frames = CaptureStackBackTrace(2, 128, stack, NULL); - - SYMBOL_INFO* symbol = calloc(sizeof(SYMBOL_INFO)+256, 1); - symbol->MaxNameLen = 255; - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - for(size_t i = 0; i < frames; i++) { - SymFromAddr(process, (DWORD64)stack[i], 0, symbol); - if(strcmp(symbol->Name, "BaseThreadInitThunk") == 0) break; - if(strcmp(symbol->Name, "mainCRTStartup") == 0) break; - printf(" %u: 0x%"PRIx64" (%s)\n", - (int)(frames-i-1), - symbol->Address, - symbol->Name - ); - } - free(symbol); -} - -void _os_init_eh() { +void _setup_eh() { void *res = AddVectoredExceptionHandler(1, &_win32_handler); if(res == NULL) { ExitProcess(-69420); } } + +void _signal_default_handler(int sig){} +void _signal_ignore_handler(int sig){} + +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) { + ExitProcess(-69420); + } + return 1; + } + return 0; +} diff --git a/src/win/win_stack_trace.c b/src/win/win_stack_trace.c new file mode 100644 index 0000000..9f57c79 --- /dev/null +++ b/src/win/win_stack_trace.c @@ -0,0 +1,26 @@ + +#include +#include + +void _os_print_stack_trace() { + HANDLE process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); + + void *stack[128]; + USHORT frames = CaptureStackBackTrace(2, 128, stack, NULL); + + SYMBOL_INFO* symbol = calloc(sizeof(SYMBOL_INFO)+256, 1); + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + for(size_t i = 0; i < frames; i++) { + SymFromAddr(process, (DWORD64)stack[i], 0, symbol); + if(strcmp(symbol->Name, "BaseThreadInitThunk") == 0) break; + if(strcmp(symbol->Name, "mainCRTStartup") == 0) break; + // printf(" %u: 0x%"PRIx64" (%s)\n", + // (int)(frames-i-1), + // symbol->Address, + // symbol->Name + // ); + } + free(symbol); +} diff --git a/src/win/win_stdio.c b/src/win/win_stdio.c new file mode 100644 index 0000000..63995d4 --- /dev/null +++ b/src/win/win_stdio.c @@ -0,0 +1,58 @@ + +#include + +#include +#include +#include +#include + +// It's just mapped directly to HANDLE +struct FILE { + int unused; +}; + +FILE *stdout; +FILE *stdin; +FILE *stderr; + +int system(const char* string) { + int wchars_required = MultiByteToWideChar(65001, 0, string, -1, NULL, 0); + wchar_t* cmd_line = malloc(sizeof(L"cmd.exe ") + (wchars_required * sizeof(wchar_t))); + if (cmd_line == NULL) { + goto error; + } + + memcpy(cmd_line, L"cmd.exe ", sizeof(L"cmd.exe ")); + MultiByteToWideChar(65001, 0, string, -1, cmd_line + sizeof("cmd.exe ") - 1, wchars_required); + + STARTUPINFOW si = { + .cb = sizeof(STARTUPINFOW), + .dwFlags = STARTF_USESTDHANDLES, + .hStdInput = GetStdHandle(STD_INPUT_HANDLE), + .hStdError = GetStdHandle(STD_ERROR_HANDLE), + .hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE) + }; + PROCESS_INFORMATION pi = {}; + + if (!CreateProcessW(NULL, cmd_line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { + goto error; + } + + // Wait until child process exits. + WaitForSingleObject(pi.hProcess, INFINITE); + + DWORD exit_code; + if (!GetExitCodeProcess(pi.hProcess, &exit_code)) { + goto error; + } + + // Close process and thread handles. + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + free(cmd_line); + return exit_code; + + error: + free(cmd_line); + return -1; +} diff --git a/src/win/win_mutex.c b/src/win/win_threads.c similarity index 98% rename from src/win/win_mutex.c rename to src/win/win_threads.c index 8216e19..8a669b5 100644 --- a/src/win/win_mutex.c +++ b/src/win/win_threads.c @@ -5,8 +5,8 @@ // Based on these posts: // https://preshing.com/20120305/implementing-a-recursive-mutex/ // https://preshing.com/20120226/roll-your-own-lightweight-mutex/ -#include "win.h" -#include "threads.h" +#include +#include void mtx_destroy(mtx_t *mtx) { CloseHandle(mtx->semaphore); diff --git a/src/win/win_time.c b/src/win/win_time.c index b84ea34..5fd1abb 100644 --- a/src/win/win_time.c +++ b/src/win/win_time.c @@ -1,11 +1,20 @@ + #include #include -#include "win.h" +#include // Store the time since we started running the process static uint64_t timer_freq; static uint64_t timer_start; +void _setup_timer(void) { + LARGE_INTEGER freq, start; + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&start); + timer_start = start.QuadPart; + timer_freq = freq.QuadPart; +} + int timespec_get(struct timespec *ts, int base) { if (base != TIME_UTC) return 0; @@ -42,14 +51,3 @@ clock_t clock(void) { return scaled_millis; } - -void _os_timing_init(void) { - LARGE_INTEGER freq, start; - if (QueryPerformanceFrequency(&freq) && QueryPerformanceCounter(&start)) { - timer_start = start.QuadPart; - timer_freq = freq.QuadPart; - } else { - // failure... - timer_start = timer_freq = UINT64_MAX; - } -} diff --git a/test/test_os.c b/test/test_os.c new file mode 100644 index 0000000..5f28815 --- /dev/null +++ b/test/test_os.c @@ -0,0 +1,8 @@ + +int main(int argc, char **argv) { + for(int i = 0; i != argc; ++i) { + char *arg = argv[i]; + arg = arg; + } + return 0; +}