diff --git a/code/os/win/win.h b/code/os/win/win.h index 8a0186c..e0abec8 100644 --- a/code/os/win/win.h +++ b/code/os/win/win.h @@ -1,6 +1,8 @@ #pragma once +#include <_os.h> + #define WIN32_LEAN_AND_MEAN #include diff --git a/code/os/win/win_io.c b/code/os/win/win_io.c index f7bb2af..49d0834 100644 --- a/code/os/win/win_io.c +++ b/code/os/win/win_io.c @@ -1,11 +1,84 @@ #include "win.h" +#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); diff --git a/code/stdio.c b/code/stdio.c index 21f69a4..d97e1e7 100644 --- a/code/stdio.c +++ b/code/stdio.c @@ -1,13 +1,71 @@ #include #include #include +#include #include <_os.h> #define __STDC_WANT_LIB_EXT1__ 1 #include -#include <_os.h> +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; +} typedef void(*OutputFunc)(void* ctx, size_t n, const char str[]); @@ -28,10 +86,10 @@ typedef struct { FILE *stdout, *stderr, *stdin; #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) + va_list args; \ + va_start(args, fmt); \ + int result = fmt_func(ctx, out, fmt, args); \ + va_end(args) static void string_write(void *ctx, size_t n, const char *restrict str) { StrPrintCtx *c = ctx; diff --git a/inc/_os.h b/inc/_os.h index 8a1860b..e3caa33 100644 --- a/inc/_os.h +++ b/inc/_os.h @@ -15,7 +15,24 @@ #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(); + +// 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; +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_init_eh(); + +_Noreturn void _os_exit(int code);