From 3fe99b72cbdc59c992f4553cf3f8038df4d07f34 Mon Sep 17 00:00:00 2001 From: bumbread Date: Wed, 15 Feb 2023 18:37:23 +1100 Subject: [PATCH] Temporary files + Some work on threads.h header --- inc/stdio.h | 53 +- inc/threads.h | 115 ++-- src/ciabatta.c | 7 +- src/fmt/fmt.c | 164 ------ src/fmt/fmt.h | 44 -- src/fmt/fmt_stream.h | 13 - src/fmt/fmt_string.h | 74 --- src/fmt/gen_fmt.c | 95 ---- src/fmt/gen_fmt.h | 883 ----------------------------- src/fmt/ints.h | 150 ----- src/os_win/assert.c | 30 +- src/os_win/cookie.c | 2 +- src/os_win/entry.c | 4 +- src/os_win/environment.c | 2 +- src/os_win/{stdio.c => file.c} | 545 ++++++++++-------- src/os_win/{threads.c => thread.c} | 0 src/os_win/win.h | 3 +- test/test_io.c | 29 +- 18 files changed, 416 insertions(+), 1797 deletions(-) delete mode 100644 src/fmt/fmt.c delete mode 100644 src/fmt/fmt.h delete mode 100644 src/fmt/fmt_stream.h delete mode 100644 src/fmt/fmt_string.h delete mode 100644 src/fmt/gen_fmt.c delete mode 100644 src/fmt/gen_fmt.h delete mode 100644 src/fmt/ints.h rename src/os_win/{stdio.c => file.c} (63%) rename src/os_win/{threads.c => thread.c} (100%) diff --git a/inc/stdio.h b/inc/stdio.h index 7929dc3..2ba8d3e 100644 --- a/inc/stdio.h +++ b/inc/stdio.h @@ -3,56 +3,37 @@ #include -#if !defined(NULL) - #define NULL ((void *)0) -#endif +// 7.23.3 p.2: Header version +#define __STDC_VERSION_STDIO_H__ 202311L +// 7.23.3 p.3: Types #if defined(_WIN32) typedef unsigned long long size_t; #else typedef unsigned long size_t; #endif -#if !defined(_mbstate_t_defined) - #define _mbstate_t_defined - typedef struct mbstate_t mbstate_t; - struct mbstate_t { - union { - unsigned short leftover; - unsigned short high_surrogate; - }; - }; -#endif - typedef struct FILE FILE; typedef struct { unsigned long long offset; - mbstate_t mbstate; + union { + unsigned short leftover; + unsigned short high_surrogate; + } mbstate; } fpos_t; +// 7.23.3 p.4: Macros #if !defined(NULL) #define NULL ((void *)0) #endif -#if !defined(__STDC_LIB_EXT1__) - #define __STDC_LIB_EXT1__ - typedef int errno_t; - typedef size_t rsize_t; -#endif - -#ifdef __STDC_WANT_SECURE_LIB__ - #if !defined(__STDC_WANT_LIB_EXT1__) - #define __STDC_WANT_LIB_EXT1__ 1 - #endif -#endif - #define _IONBF 0 #define _IOFBF 1 #define _IOLBF 2 #define BUFSIZ 512 #define EOF (-1) -#define FOPEN_MAX 1024 +#define FOPEN_MAX 32 #ifdef _os_win #define FILENAME_MAX 260 @@ -60,6 +41,8 @@ typedef struct { #define FILENAME_MAX 4096 #endif +#define _PRINTF_NAN_LEN_MAX 20 + #define L_tmpnam FILENAME_MAX #define SEEK_SET 0 @@ -72,17 +55,21 @@ typedef struct { #define TMP_MAX INT_MAX #endif -extern FILE *stdout; -extern FILE *stderr; -extern FILE *stdin; +#define stdout _internal_stdout +#define stderr _internal_stderr +#define stdin _internal_stdin + +extern FILE *_internal_stdout; +extern FILE *_internal_stderr; +extern FILE *_internal_stdin; // File manipulation int remove(const char *filename); int rename(const char *oldname, const char *newname); -FILE *tmpfile(void); -char *tmpnam(char *s); // Opening and closing files +char *tmpnam(char *s); +FILE *tmpfile(void); FILE *fopen (const char *restrict filename, const char *restrict mode); FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *restrict stream); int fclose (FILE *stream); diff --git a/inc/threads.h b/inc/threads.h index 096dcd2..4181199 100644 --- a/inc/threads.h +++ b/inc/threads.h @@ -1,47 +1,59 @@ #pragma once -#define thread_local _Thread_local +// 7.28.1 p.3: Macros #define ONCE_FLAG_INIT 1 #define TSS_DTOR_ITERATIONS 32 +// TODO(bumbread): check the spec for whether thread_local needs to be declared +// in threads.h +#define thread_local _Thread_local + +// 7.28.1 p.4: Types + #if !defined(_timespec_defined) -#define _timespec_defined -typedef unsigned long long time_t; -struct timespec { - time_t tv_sec; - long tv_nsec; -}; + #define _timespec_defined + typedef unsigned long long time_t; + struct timespec { + time_t tv_sec; + long tv_nsec; + }; #endif +// TODO(bumbread): move this out to platform-specific folder #if defined(_WIN32) -typedef struct cnd_t { - int idk_yet; -} cnd_t; + typedef struct cnd_t { + int idk_yet; + } cnd_t; -typedef struct thrd_t { - void* handle; -} thrd_t; + typedef struct thrd_t { + void* handle; + } thrd_t; -typedef struct tss_t { - int idk_yet; -} tss_t; + typedef struct tss_t { + int idk_yet; + } tss_t; -typedef struct mtx_t { - int type; - // Done to handle recursive mutexes - unsigned long recursion; - unsigned long owner; - _Atomic(int) counter; - void* semaphore; -} mtx_t; + typedef struct mtx_t { + int type; + // Done to handle recursive mutexes + unsigned long recursion; + unsigned long owner; + _Atomic(int) counter; + void* semaphore; + } mtx_t; #else -#error "Not implemented" + #error "Not implemented" #endif typedef void(*tss_dtor_t) (void*); typedef int (*thrd_start_t)(void*); -typedef int once_flag; // TODO: change this maybe? + +// TODO(bumbread): this probably should be a mutex or a semaphore +// also probably can be implemented with interlocked increment +typedef int once_flag; + +// 7.28.1 p.5: Enumeration constants enum { mtx_plain = 0, @@ -57,29 +69,7 @@ enum { thrd_nomem }; -void call_once(once_flag *flag, void (*func)(void)); - -int cnd_init (cnd_t *cond); -int cnd_broadcast(cnd_t *cond); -void cnd_destroy (cnd_t *cond); -int cnd_signal (cnd_t *cond); -int cnd_wait (cnd_t *cond, mtx_t *mtx); -int cnd_timedwait( - cnd_t *restrict cond, - mtx_t *restrict mtx, - const struct timespec *restrict ts -); - -void mtx_destroy (mtx_t *mtx); -int mtx_init (mtx_t *mtx, int type); -int mtx_unlock (mtx_t *mtx); -int mtx_trylock (mtx_t *mtx); -int mtx_lock (mtx_t *mtx); -int mtx_timedlock( - mtx_t *restrict mtx, - const struct timespec *restrict ts -); - +// Thread functions thrd_t thrd_current(void); int thrd_create (thrd_t *thr, thrd_start_t func, void *arg); int thrd_detach (thrd_t thr); @@ -92,7 +82,34 @@ int thrd_sleep( ); _Noreturn void thrd_exit(int res); +// Mutex functions +void mtx_destroy (mtx_t *mtx); +int mtx_init (mtx_t *mtx, int type); +int mtx_unlock (mtx_t *mtx); +int mtx_trylock (mtx_t *mtx); +int mtx_lock (mtx_t *mtx); +int mtx_timedlock( + mtx_t *restrict mtx, + const struct timespec *restrict ts +); + +// Thread-local storage functions int tss_create(tss_t *key, tss_dtor_t dtor); void tss_delete(tss_t key); void *tss_get (tss_t key); int tss_set (tss_t key, void *val); + +// Condition functions +int cnd_init (cnd_t *cond); +int cnd_broadcast(cnd_t *cond); +void cnd_destroy (cnd_t *cond); +int cnd_signal (cnd_t *cond); +int cnd_wait (cnd_t *cond, mtx_t *mtx); +int cnd_timedwait( + cnd_t *restrict cond, + mtx_t *restrict mtx, + const struct timespec *restrict ts +); + +// Call once +void call_once(once_flag *flag, void (*func)(void)); diff --git a/src/ciabatta.c b/src/ciabatta.c index 55bee87..5f892a7 100644 --- a/src/ciabatta.c +++ b/src/ciabatta.c @@ -50,7 +50,6 @@ #include "conv/strpfx.c" #include "conv/int.c" #include "conv/float.c" -#include "fmt/fmt.c" #include "stdlib/algorithm.c" #include "stdlib/multibyte.c" #include "stdlib/random.c" @@ -69,11 +68,11 @@ #include "os_win/cookie.c" #include "os_win/assert.c" #include "os_win/cmdline.c" -#include "os_win/entry.c" #include "os_win/environment.c" #include "os_win/heap.c" #include "os_win/signal.c" -#include "os_win/stdio.c" -#include "os_win/threads.c" +#include "os_win/file.c" +#include "os_win/thread.c" #include "os_win/time.c" +#include "os_win/entry.c" #endif diff --git a/src/fmt/fmt.c b/src/fmt/fmt.c deleted file mode 100644 index ace1a88..0000000 --- a/src/fmt/fmt.c +++ /dev/null @@ -1,164 +0,0 @@ - -#define FLAG_ZERO 0x0001 // "0" -#define FLAG_LEFT 0x0002 // "-" -#define FLAG_PLUS 0x0004 // "+" -#define FLAG_SPACE 0x0008 // " " -#define FLAG_HASH 0x0010 // "#" -#define FLAG_PREC 0x0020 // ".precision" -#define FLAG_LONG 0x0040 // "l" -#define FLAG_LLONG 0x0080 // "ll" -#define FLAG_SHORT 0x0100 // "h" -#define FLAG_CHAR 0x0200 // "hh" -#define FLAG_UPPER 0x0400 // for hex digits 0xa-0xf - -struct fmt_t typedef fmt_t; -struct fmt_t { - int prec; - int width; - int flags; -}; - -#define ctype char -#define pfx(f) f -#include "fmt_string.h" -#include "fmt_stream.h" -#include "ints.h" -#include "fmt.h" -#undef ctype -#undef pfx - -#define ctype wchar_t -#define pfx(f) w ## f -#include "fmt_string.h" -#include "fmt_stream.h" -#include "ints.h" -#include "fmt.h" -#undef ctype -#undef pfx - -// fprintf family - -static inline int fstream_outc(void *ctx, char c) { - FILE *file = ctx; - int result = fputc(c, file); - if(result == EOF) { - return -1; - } - return 1; -} - -static inline int fstream_outw(void *ctx, wchar c) { - FILE *file = ctx; - int result = fputc((char)c, file); // TODO: utf8 - if(result == EOF) { - return -1; - } - return 1; -} - -static inline fmt_stream_t fstream_new(FILE *file) { - fmt_stream_t stream; - stream.w = 0; - stream.ctx = file; - stream.out_ctype = fstream_outc; - stream.out_wchar = fstream_outw; - stream.out_char = fstream_outc; - return stream; -} - -int vfprintf(FILE *restrict file, const char *restrict string, va_list va) { - fmt_stream_t stream = fstream_new(file); - return fmt(&stream, string, va); -} - -int vprintf(const char *restrict string, va_list va) { - return vfprintf(stdout, string, va); -} - -int fprintf(FILE *restrict file, const char *restrict string, ...) { - va_list va; - va_start(va, string); - int result = vfprintf(file, string, va); - va_end(va); - return result; -} - -int printf(const char *restrict string, ...) { - va_list va; - va_start(va, string); - int result = vfprintf(stdout, string, va); - va_end(va); - return result; -} - -// s(n)printf family - -struct str_slice_t typedef str_slice_t; -struct str_slice_t { - char *str; - size_t max_size; - size_t written; -}; - -static inline int sstream_outc(void *ctx, char c) { - str_slice_t *slice = ctx; - if(slice->written+1 < slice->max_size) { - return -1; - } - slice->str[slice->written++] = c; - return 1; -} - -static inline int sstream_outw(void *ctx, wchar c) { - str_slice_t *slice = ctx; - // TODO: utf8 - if(slice->written+1 < slice->max_size) { - return -1; - } - slice->str[slice->written++] = c; - return 1; -} - -static inline fmt_stream_t sstream_new(str_slice_t *slice) { - fmt_stream_t stream; - stream.w = 0; - stream.ctx = slice; - stream.out_ctype = sstream_outc; - stream.out_wchar = sstream_outw; - stream.out_char = sstream_outc; - return stream; -} - -int vsnprintf(char *restrict buf, size_t cbbuf, const char *restrict str, va_list va) { - str_slice_t slice; - slice.str = buf; - slice.max_size = cbbuf; - slice.written = 0; - fmt_stream_t stream = sstream_new(&slice); - return fmt(&stream, str, va); -} - -int vsprintf(char *restrict buf, const char *restrict str, va_list va) { - str_slice_t slice; - slice.str = buf; - slice.max_size = SIZE_MAX; - slice.written = 0; - fmt_stream_t stream = sstream_new(&slice); - return fmt(&stream, str, va); -} - -int snprintf(char *restrict buf, size_t cbbuf, const char *restrict str, ...) { - va_list va; - va_start(va, str); - int result = vsnprintf(buf, cbbuf, str, va); - va_end(va); - return result; -} - -int sprintf(char *restrict buf, const char *restrict str, ...) { - va_list va; - va_start(va, str); - int result = vsprintf(buf, str, va); - va_end(va); - return result; -} diff --git a/src/fmt/fmt.h b/src/fmt/fmt.h deleted file mode 100644 index 6d263c7..0000000 --- a/src/fmt/fmt.h +++ /dev/null @@ -1,44 +0,0 @@ - -static inline int pfx(fmt_arg)(fmt_stream_t *stream, ctype const **strp, va_list va) { - ctype const *str = *strp; - fmt_t fmt = {0}; - if(!pfx(fmt_read)(str, &fmt, va)) { - return 0; - } - switch(*str) { - case 'i': - case 'u': - case 'b': - case 'o': - case 'd': - case 'x': - case 'X': - { - int base; - int sign; - u64 abs = pfx(fmt_int_arg)(stream, &fmt, &str, &sign, &base, va); - if(pfx(fmt_int)(stream, fmt, sign, abs, base) == -1) { - return -1; - } - } break; - } - *strp = str; - return 1; -} - -static inline int pfx(fmt)(fmt_stream_t *stream, ctype const *str, va_list va) { - stream->w = 0; - while(*str) { - if(*str == '%') { - ++str; - int ok = pfx(fmt_arg)(stream, &str, va); - if(!ok) { - return -1; - } - } - else { - stream_out(stream, *str++); - } - } - return stream->w; -} diff --git a/src/fmt/fmt_stream.h b/src/fmt/fmt_stream.h deleted file mode 100644 index 22e9a5d..0000000 --- a/src/fmt/fmt_stream.h +++ /dev/null @@ -1,13 +0,0 @@ - -struct pfx(fmt_stream_t) typedef pfx(fmt_stream_t); -struct pfx(fmt_stream_t) { - int w; - void *ctx; - int (*pfx(out_ctype))(void *ctx, ctype ch); - int (*pfx(out_wchar))(void *ctx, wchar ch); - int (*pfx(out_char)) (void *ctx, char ch); -}; - -#define stream_out(s, ch) if((s->w++, !s->out_ctype(s->ctx, ch))) return -1 -#define stream_outc(s, ch) if((s->w++, !s->out_char (s->ctx, ch))) return -1 -#define stream_outw(s, ch) if((s->w++, !s->out_wchar(s->ctx, ch))) return -1 diff --git a/src/fmt/fmt_string.h b/src/fmt/fmt_string.h deleted file mode 100644 index 1c0eb8f..0000000 --- a/src/fmt/fmt_string.h +++ /dev/null @@ -1,74 +0,0 @@ - -static inline int pfx(fmt_isdigit)(ctype ch) { - return '0' <= ch && ch <= '9'; -} - -static inline int pfx(fmt_atoi)(ctype const **sp, int *err) { - int i = 0; - ctype const *s = *sp; - while(pfx(fmt_isdigit(*s))) { - int d = *s-'0'; - if(i > (INT_MAX - d)/10) { - *err = 1; - return 0; - } - i = 10*i + d; - ++s; - } - *sp = s; - return i; -} - -static inline int pfx(fmt_read)(const ctype *str, fmt_t *fmt, va_list va) { - int flags = 0; - // Parse flag field - { - int isflag = 0; - do { - isflag = 1; - switch(*str) { - case '0': flags |= FLAG_ZERO; break; - case '-': flags |= FLAG_LEFT; break; - case '+': flags |= FLAG_PLUS; break; - case ' ': flags |= FLAG_SPACE; break; - case '#': flags |= FLAG_HASH; break; - default: isflag = 0; - } - if(isflag) ++str; - } while(isflag); - // If '-' and '0' are together we just discard '0' - if(flags & FLAG_LEFT) flags &= ~FLAG_ZERO; - } - // Parse width field - int width = 0; - if(pfx(fmt_isdigit(*str))) { - int err = 0; - width = pfx(fmt_atoi(&str, &err)); - if(err) return 0; - } - else if(*str == '*') { - ++str; - width = va_arg(va, int); - if(width < 0) { - width = -width; - flags |= FLAG_LEFT; - } - } - // If present, parse the precision field - int prec = 0; - if(*str == '.') { - flags |= FLAG_PREC; - ++str; - if(pfx(fmt_isdigit(*str))) { - int err = 0; - prec = pfx(fmt_atoi(&str, &err)); - if(err) return -1; - } - else if(*str == '*') { - ++str; - prec = va_arg(va, int); - prec = (prec > 0? prec : 0); - } - } - return 1; -} diff --git a/src/fmt/gen_fmt.c b/src/fmt/gen_fmt.c deleted file mode 100644 index c857ff5..0000000 --- a/src/fmt/gen_fmt.c +++ /dev/null @@ -1,95 +0,0 @@ - -#define ctype char -#define pfx(f) f -#include "gen_fmt.h" -#undef ctype -#undef pfx - -#define ctype wchar_t -#define pfx(f) w ## f -#include "gen_fmt.h" -#undef ctype -#undef pfx - - -static int fprintfcb(void *ctx, char ch) { - FILE *f = ctx; - return fputc(ch, f) != EOF; -} - -struct str_ctx_t typedef str_ctx_t; -struct str_ctx_t { - char *str; - size_t n; - size_t i; -}; - -static int sprintfcb(void *ctx, char ch) { - str_ctx_t *stream = ctx; - stream->str[stream->i++] = ch; - return 1; -} - -static int snprintfcb(void *ctx, char ch) { - str_ctx_t *stream = ctx; - if(stream->i >= stream->n) { - return 0; - } - stream->str[stream->i++] = ch; - return 1; -} - - -int vfprintf(FILE *stream, const char *fmt, va_list args) { - return vprintfcb(stream, fprintfcb, fmt, args); -} - -int vprintf(const char *fmt, va_list args) { - return vprintfcb(stdout, fprintfcb, fmt, args); -} - -int fprintf(FILE *stream, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - int len = vfprintf(stream, fmt, args); - va_end(args); - return len; -} - -int printf(const char *fmt, ...) { - va_list args; - va_start(args, fmt); - int len = vprintf(fmt, args); - va_end(args); - return len; -} - - -int vsprintf(char *buf, char const *fmt, va_list args) { - str_ctx_t ctx = {0}; - ctx.str = buf; - return vprintfcb(&ctx, sprintfcb, fmt, args); -} - -int vsnprintf(char *buf, size_t sz, char const *fmt, va_list args) { - str_ctx_t ctx = {0}; - ctx.str = buf; - ctx.n = sz; - return vprintfcb(&ctx, snprintfcb, fmt, args); -} - -int sprintf(char *buf, char const *fmt, ...) { - va_list args; - va_start(args, fmt); - int len = vsprintf(buf, fmt, args); - va_end(args); - return len; -} - -int snprintf(char *buf, size_t sz, char const *fmt, ...) { - va_list args; - va_start(args, fmt); - int len = vsnprintf(buf, sz, fmt, args); - va_end(args); - return len; -} diff --git a/src/fmt/gen_fmt.h b/src/fmt/gen_fmt.h deleted file mode 100644 index d58723d..0000000 --- a/src/fmt/gen_fmt.h +++ /dev/null @@ -1,883 +0,0 @@ - -typedef int (pfx(cbfn))(void *ctx, ctype ch); - -#define FLAG_ZERO 0x0001 // "0" -#define FLAG_LEFT 0x0002 // "-" -#define FLAG_PLUS 0x0004 // "+" -#define FLAG_SPACE 0x0008 // " " -#define FLAG_HASH 0x0010 // "#" -#define FLAG_PREC 0x0020 // ".precision" -#define FLAG_LONG 0x0040 // "l" -#define FLAG_LLONG 0x0080 // "ll" -#define FLAG_SHORT 0x0100 // "h" -#define FLAG_CHAR 0x0200 // "hh" -#define FLAG_UPPER 0x0400 // for hex digits 0xa-0xf - -// Helper function declaration -static inline int pfx(_isdigit)(ctype ch); -static inline int pfx(_atoi)(ctype const **sp, int *err); -static inline int pfx(_ntoa)( - int w, - void *ctx, - pfx(cbfn) cb, - int neg, - unsigned long long value, - int base, - int prec, - int width, - int flags -); -static inline int pfx(_dtoh)( - int w, - void *ctx, - pfx(cbfn) cb, - double value, - int prec, - int width, - int flags -); -static inline int pfx(_dtoa)( - int w, - void *ctx, - pfx(cbfn) cb, - decfloat_t value, - int prec, - int width, - int flags -); -static inline int pfx(_etoa)( - int w, - void *ctx, - pfx(cbfn) cb, - decfloat_t value, - int prec, - int width, - int flags -); -static inline int pfx(_infnantoa)( - int w, - void *ctx, - pfx(cbfn) cb, - double value, - int prec, - int width, - int flags -); - -#define out(ch) do { if((w++, !cb(ctx, (ch)))) return -1; } while(0) - -#define print_lwidth_spaces(flags, pad) \ - do if(!(flags & FLAG_LEFT) && !(flags & FLAG_ZERO)) while(pad-- > 0) { \ - out(' '); \ - } \ - while(0) - -#define print_lwidth_zeros(flags, pad) \ - do if(!(flags & FLAG_LEFT) && (flags & FLAG_ZERO)) while(pad-- > 0) { \ - out('0'); \ - } \ - while(0) - -#define print_rwidth(flags, pad) \ - if(flags & FLAG_LEFT) while(pad-- > 0) { \ - out(' '); \ - } - -// Generic print -static int pfx(vprintfcb)( - void *ctx, - pfx(cbfn) *cb, - const ctype *fmt, - va_list va -) { - int w = 0; - while(*fmt) { - // Write a character if it's not a '%' sign - while(*fmt && *fmt != '%') { - out(*fmt++); - continue; - } - if(*fmt == '%') { - ++fmt; - } - // Parse flags - int flags = 0; - int isflag = 0; - do { - isflag = 1; - switch(*fmt) { - case '0': flags |= FLAG_ZERO; break; - case '-': flags |= FLAG_LEFT; break; - case '+': flags |= FLAG_PLUS; break; - case ' ': flags |= FLAG_SPACE; break; - case '#': flags |= FLAG_HASH; break; - default: isflag = 0; - } - if(isflag) ++fmt; - } while(isflag); - if(flags & FLAG_LEFT) flags &= ~FLAG_ZERO; - // Parse width field - int width = 0; - if(pfx(_isdigit(*fmt))) { - int err = 0; - width = pfx(_atoi(&fmt, &err)); - if(err) return -1; - } - else if(*fmt == '*') { - ++fmt; - width = va_arg(va, int); - if(width < 0) { - width = -width; - flags |= FLAG_LEFT; - } - } - // If present, parse the precision field - int prec = 0; - if(*fmt == '.') { - flags |= FLAG_PREC; - ++fmt; - if(pfx(_isdigit(*fmt))) { - int err = 0; - prec = pfx(_atoi(&fmt, &err)); - if(err) return -1; - } - else if(*fmt == '*') { - ++fmt; - prec = va_arg(va, int); - prec = (prec > 0? prec : 0); - } - } - // Parse length field - switch(*fmt) { - case 'l': - ++fmt; - flags |= FLAG_LONG; - if(*fmt == 'l') { - ++fmt; - flags |= FLAG_LLONG; - } - break; - case 'h': - ++fmt; - flags |= FLAG_SHORT; - if(*fmt == 'h') { - ++fmt; - flags |= FLAG_CHAR; - } - break; - case 'j': - ++fmt; - if(sizeof(intmax_t) == sizeof(long)) - flags |= FLAG_LONG; - else flags |= FLAG_LLONG; - break; - case 'z': - ++fmt; - if(sizeof(size_t) == sizeof(long)) - flags |= FLAG_LONG; - else flags |= FLAG_LLONG; - break; - case 't': - ++fmt; - if(sizeof(ptrdiff_t) == sizeof(long)) - flags |= FLAG_LONG; - else flags |= FLAG_LLONG; - break; - case 'L': - ++fmt; - break; - default: - break; - } - // Print according to specifier - switch(*fmt) { - case 'd': - case 'i': - case 'u': - case 'x': - case 'X': - case 'o': - case 'b': { - // Figure out the signedness and base - int base = 10; - if(*fmt == 'x' || *fmt == 'X') base = 16; - if(*fmt == 'o') base = 8; - if(*fmt == 'b') base = 2; - int signd = (*fmt == 'i' || *fmt == 'd'); - // Figure out flags - if(*fmt == 'X') flags |= FLAG_UPPER; - if(base == 10) flags &= ~FLAG_HASH; - if(!signd) flags &= ~(FLAG_PLUS|FLAG_SPACE); - if(flags & FLAG_PREC) flags &= ~FLAG_ZERO; - ++fmt; - // Read-in the integer argument from var args - int neg = 0; - unsigned long long value = 0; - if(signd) { - long long num; - if(flags & FLAG_LLONG) - num = (long long)va_arg(va, long long); - else if(flags & FLAG_LONG) - num = (long long)va_arg(va, long); - else - num = (long long)va_arg(va, int); - // Avoiding UB on unary negation like a bitch - if(num == LLONG_MIN) { - neg = 1; - value = (unsigned long long)LLONG_MAX + 1; - } - else { - neg = num >= 0? 0 : 1; - num = num >= 0? num : -num; - value = (unsigned long long)num; - } - } - else { - if(flags & FLAG_LLONG) - value = (unsigned long long)va_arg(va, unsigned long long); - else if(flags & FLAG_LONG) - value = (unsigned long long)va_arg(va, unsigned long); - else - value = (unsigned long long)va_arg(va, unsigned int); - } - // Output integer - w = pfx(_ntoa)(w, ctx, cb, neg, value, base, prec, width, flags); - if(w < 0) return -1; - } break; - case 'a': - case 'A': { - if(*fmt == 'A') flags |= FLAG_UPPER; - ++fmt; - double value = va_arg(va, double); - w = pfx(_dtoh)(w, ctx, cb, value, prec, width, flags); - if(w < 0) return -1; - } break; - case 'e': - case 'E': - case 'f': - case 'F': - case 'g': - case 'G': { - if(*fmt == 'E' || *fmt == 'F' || *fmt == 'G') flags |= FLAG_UPPER; - char conv = tolower(*fmt); - ++fmt; - double value = va_arg(va, double); - int class = fpclassify(value); - if(class == FP_INFINITE || class == FP_NAN) { - return pfx(_infnantoa)(w, ctx, cb, value, prec, width, flags); - } - decfloat_t dec_value = f64_to_decimal(value); - if(conv == 'f') { - w = pfx(_dtoa)(w, ctx, cb, dec_value, prec, width, flags); - } - else if(conv == 'e') { - w = pfx(_etoa)(w, ctx, cb, dec_value, prec, width, flags); - } - else { - int P = prec; - if(!(flags & FLAG_PREC)) P = 6; - if(prec == 0) P = 1; - int64_t E; - { - if(class == FP_ZERO) { - E = 0; - } - else { - E = dec_value.exponent; - } - } - if(class == FP_SUBNORMAL || class == FP_ZERO) { - E = 0; - } - flags |= FLAG_PREC; - if(P > E && E >= -4) { - w = pfx(_dtoa)(w, ctx, cb, dec_value, P-(E+1), width, flags); - } - else { - w = pfx(_etoa)(w, ctx, cb, dec_value, P-1, width, flags); - } - } - if(w < 0) return -1; - }break; - case 'c': { - ++fmt; - int ch = va_arg(va, int); - int pad = width-1; - // Print width left-pad - if(!(flags & FLAG_LEFT) && !(flags & FLAG_ZERO)) while(pad-- > 0) { - out(' '); - } - out(ch); - // Print right-pad - if(flags & FLAG_LEFT) while(pad-- > 0) { - out(' '); - } - } break; - case 's': { - ++fmt; - char *str = NULL; - wchar_t *wstr = NULL; - int len = 0; - if(flags & FLAG_LONG) { - wstr = va_arg(va, wchar_t *); - wchar_t *s = wstr; - while(*s++!=0) ++len; - int pad = width - len; - // Print width left-pad - if(!(flags & FLAG_LEFT) && !(flags & FLAG_ZERO)) while(pad-- > 0) { - out(' '); - } - // Print string - mbstate_t ps = {0}; - for(int i = 0; i < len; ++i) { - if(sizeof(ctype) == 2) { - out(wstr[i]); - } - else { - // char utf8[5]; - // char *s = utf8; - // size_t r = c16rtomb(s, wstr[i], &ps); - // if(r == (size_t)(-1)) return -1; - // if(r != 0) { - // while(*s != 0) { - // out(*s++); - // } - // } - } - } - // Print right-pad - if(flags & FLAG_LEFT) while(pad-- > 0) { - out(' '); - } - } - else { - str = va_arg(va, char *); - char *s = str; - if(flags & FLAG_PREC) { - while(*s++!=0 && len 0) { - out(' '); - } - // Print string - //mbstate_t ps = {0}; - for(int i = 0; i < len; ++i) { - out(str[i]); - } - // Print right-pad - if(flags & FLAG_LEFT) while(pad-- > 0) { - out(' '); - } - } - } break; - case 'p': { - ++fmt; - void *ptr = va_arg(va, void *); - unsigned long long iptr = (unsigned long long)(uintptr_t)ptr; - w = pfx(_ntoa)(w, ctx, cb, 0, iptr, 16, 16, 0, FLAG_HASH); - if(w < 0) return -1; - } break; - case 'n': { - ++fmt; - int *p = va_arg(va, int *); - *p = w; - } break; - case '%': { - ++fmt; - out('%'); - } break; - } - } - return w; -} - -static inline int pfx(_isdigit)(ctype ch) { - return '0' <= ch && ch <= '9'; -} - -static inline int pfx(_atoi)(ctype const **sp, int *err) { - int i = 0; - ctype const *s = *sp; - while(pfx(_isdigit(*s))) { - int d = *s-'0'; - if(i > (INT_MAX - d)/10) { - *err = 1; - return 0; - } - i = 10*i + d; - ++s; - } - *sp = s; - return i; -} - -static inline int pfx(_ntoa)( - int w, - void *ctx, - pfx(cbfn) cb, - int neg, - unsigned long long value, - int base, - int prec, - int width, - int flags -) { - // We'll Write digits into buf in reverse and then call _out_rbuf - int ndigits = 0; - static ctype digits[64]; - // Remove hash flag for 0 values - if(value == 0) flags &= ~FLAG_HASH; - // Write digits to buffer in reverse (starting from least significant) - do { - int d = (int)(value%base); - value /= base; - if(d < 10) - d += '0'; - else if(flags & FLAG_UPPER) - d += 'A' - 10; - else d += 'a' - 10; - digits[ndigits++] = d; - } while(value); - // Figure out the length of the prefix (part of number before digit stirng) - int pref_len = 0; - if(flags & FLAG_HASH) pref_len = base == 8? 1 : 2; - else if(neg) pref_len = 1; - else if(flags & FLAG_PLUS) pref_len = 1; - else if(flags & FLAG_SPACE) pref_len = 1; - if(ndigits > prec) prec = ndigits; - int num_len = pref_len + prec; - int pad_len = width - num_len; - if(!(flags & FLAG_LEFT)) { - ctype pad_ch = ' '; - if(flags & FLAG_ZERO) pad_ch = '0'; - while(pad_len-- > 0) { - out(pad_ch); - } - } - // Print width left-pad if it's made out of space - if(!(flags & FLAG_LEFT) && !(flags & FLAG_ZERO)) while(pad_len-- > 0) { - out(' '); - } - // Print prefix - if(flags & FLAG_HASH) { - out('0'); - if(base == 16) { out('x'); } - else if(base == 2) { out('b'); } - } - else if(neg) { out('-'); } - else if(flags & FLAG_PLUS) { out('+'); } - else if(flags & FLAG_SPACE) { out(' '); } - // Print width left-pad if it's made out of zero - if(!(flags & FLAG_LEFT) && (flags & FLAG_ZERO)) while(pad_len-- > 0) { - out('0'); - } - // Print zero-pad due to precision - for(int i = ndigits; i < prec; ++i) { - out('0'); - } - // Output buffer in reverse - if(ndigits) while(ndigits--) { - out(digits[ndigits]); - } - // Print right-pad - if(flags & FLAG_LEFT) while(pad_len-- > 0) { - out(' '); - } - return w; -} - -static inline int pfx(_infnantoa)( - int w, - void *ctx, - pfx(cbfn) cb, - double value, - int prec, - int width, - int flags -) { - char const *name = NULL; - int nchars = 0; - if(isinf(value)) name = "inf", nchars = 3; - if(isnan(value)) name = "nan", nchars = 3; - // Figure out prefix - int pref_len = 0; - u64 bits = F64_BITS(value); - u64 mant = F64_MANT(bits); - int neg = F64_SIGN(bits) & (mant == 0); - if(neg) pref_len = 1; - else if(flags & FLAG_PLUS) pref_len = 1; - else if(flags & FLAG_SPACE) pref_len = 1; - // Figure out pad - int str_len = pref_len + nchars; - int pad_len = width - str_len; - // Print left-pad - if(!(flags & FLAG_LEFT)) { - while(pad_len-- > 0) { - out(' '); - } - } - // Print the prefix - if(neg) out('-'); - else if(flags & FLAG_PLUS) out('+'); - else if(flags & FLAG_SPACE) out(' '); - // Print the string - while(*name) { - out(*name++); - } - // Print right-pad - if(flags & FLAG_LEFT) { - while(pad_len-- > 0) { - out(' '); - } - } - return w; -} - -static inline int pfx(_dtoh)( - int w, - void *ctx, - pfx(cbfn) cb, - double value, - int prec, - int width, - int flags -) { - // Filter out inifnities and NaN - { - int class = fpclassify(value); - if(class == FP_INFINITE || class == FP_NAN) { - return pfx(_infnantoa)(w, ctx, cb, value, prec, width, flags); - } - } - // Deconstruct the float - u64 bits = F64_BITS(value); - u64 flt_sgn = F64_SIGN(bits); - u64 flt_mnt = F64_MANT(bits); - i64 flt_exp = F64_BEXP(bits); - u64 frc; - u64 mnt; - i64 exp; - { - mnt = flt_mnt; - exp = flt_exp - 0x3ff; - if(flt_exp == 0 && flt_mnt == 0) { - exp = 0; - } - } - // Calculate widths of different number parts and extract some data - static ctype frc_buffer[64] = {0}; - static ctype exp_buffer[64] = {0}; - ctype *frc_buf = frc_buffer + sizeof frc_buffer; - ctype *exp_buf = exp_buffer + sizeof exp_buffer; - ctype sgn_ch; - ctype exp_sgn_ch; - int has_sgn; - int has_point; - int nfrc = 0; - int nexp = 0; - int nfrcp = 0; - { - // Sign - if(flt_sgn) { - has_sgn = 1; - sgn_ch = '-'; - } - else if(flags & FLAG_PLUS) { - has_sgn = 1; - sgn_ch = '+'; - } - else if(flags & FLAG_SPACE) { - has_sgn = 1; - sgn_ch = ' '; - } - // Fractional part - frc = mnt; - if(frc != 0) { - while(!(frc & 0xf)) { - frc >>= 4; - } - } - u64 f = frc; - do { - int d = f % 16; - f /= 16; - *--frc_buf = fromdigit(d, flags & FLAG_UPPER); - } while(f != 0); - // Frac/whole digits - if(flags & FLAG_PREC) { - nfrcp = prec; - } - else { - nfrcp = nfrc; - } - // Decimal point - has_point = 1; - if(nfrc == 0 && !(flags & FLAG_HASH)) { - has_point = 0; - } - // Exponent - i64 e = exp; - if(e < 0) { - exp_sgn_ch = '-'; - e = -e; - } - else { - exp_sgn_ch = '+'; - } - do { - *--exp_buf = (e%10) + '0'; - e /= 10; - nexp ++; - } while(e != 0); - } - // Figure out the width of a float - int nfloat = has_sgn + 2 + 1 + has_point + nfrcp + 1 + 1 + nexp; - int pad = MIN(0, width - nfloat); - print_lwidth_spaces(flags, pad); - if(has_sgn) { - out(sgn_ch); - } - out('0'); - out((flags & FLAG_UPPER)? 'X' : 'x'); - print_lwidth_zeros(flags, pad); - out((flt_exp == 0) ? '0' : '1'); - if(has_point) { - out('.'); - } - int i; - for(i = 0; i != nfrcp; ++i) { - if(i < nfrc) { - out(frc_buf[i]); - } - else { - out('0'); - } - } - out((flags & FLAG_UPPER)? 'P' : 'p'); - out(exp_sgn_ch); - for(int i = 0; i != nexp; ++i) { - out(exp_buf[i]); - } - print_rwidth(flags, pad); - return w; -} - -static inline int pfx(_dtoa)( - int w, - void *ctx, - pfx(cbfn) cb, - decfloat_t value, - int prec, - int width, - int flags -) { - int64_t exp = value.exponent; - int64_t mant = value.mantissa; - // Figure out how many digits does mantissa take up (mant_digits_n) - // and the number of digits after decimal point (prec) - // and the number of digits before decimal point (while_digits_n) - static ctype mant_buf[64] = {0}; - int whole_digits_n; - int mant_digits_n = 0; - { - int64_t m = mant; - do { - mant_buf[mant_digits_n++] = m % 10 + '0'; - m /= 10; - } while(m != 0); - } - if((flags & FLAG_PREC) == 0) { - prec = 6; - } - whole_digits_n = mant_digits_n + exp; - if(whole_digits_n <= 0) whole_digits_n = 1; - // Figure out how many symbols decimal point takes up (0 or 1) - int decimal_point_n = 1; - if(prec == 0) { - decimal_point_n = 0; - if(flags & FLAG_HASH) { - decimal_point_n = 1; - } - } - // Figure out sign symbol and number of chars it takes up (0 or 1) - int sign_n = 0; - ctype sign_ch; - if(value.sign) { - sign_n = 1; - sign_ch = '-'; - } - else if(flags & FLAG_PLUS) { - sign_n = 1; - sign_ch = '+'; - } - else if(flags & FLAG_SPACE) { - sign_n = 1; - sign_ch = ' '; - } - // Figure out the width of the number - int significand_width = whole_digits_n + decimal_point_n + prec; - int n_width = sign_n + significand_width; - // Figure out width-padding required - int pad = 0; - if(width > n_width) pad = width - n_width; - // Print width left-pad if it's made out of space - if(!(flags & FLAG_LEFT) && !(flags & FLAG_ZERO)) while(pad-- > 0) { - out(' '); - } - // Print sign if there - if(sign_n) - out(sign_ch); - // Print width left-pad if it's made out of zero - if(!(flags & FLAG_LEFT) && (flags & FLAG_ZERO)) while(pad-- > 0) { - out('0'); - } - // Print whole part - while(whole_digits_n--) { - if(-exp >= mant_digits_n) { - out('0'); - } - else { - out(mant_buf[--mant_digits_n]); - } - ++exp; - } - // Print decimal point - if(decimal_point_n) out('.'); - // Print fractional part that's made out of digits - int prec_digs = prec < mant_digits_n ? prec : mant_digits_n; - while(mant_digits_n < prec_digs) { - if(-exp >= mant_digits_n) { - out('0'); - } - else { - out(mant_buf[--mant_digits_n]); - } - ++exp; - } - while(prec_digs-- > 0) { - out('0'); - } - // Print right-pad - if(flags & FLAG_LEFT) while(pad-- > 0) { - out(' '); - } - return w; -} - -static inline int pfx(_etoa)( - int w, - void *ctx, - pfx(cbfn) cb, - decfloat_t value, - int prec, - int width, - int flags -) { - int64_t exp = value.exponent; - int64_t mant = value.mantissa; - // Figure out how many digits does mantissa take up (mant_digits_n) - // and the number of digits after decimal point (prec) - static ctype mant_buf[64] = {0}; - int mant_digits_n = 0; - { - int64_t m = mant; - do { - mant_buf[mant_digits_n++] = m % 10 + '0'; - m /= 10; - } while(m != 0); - } - mant_digits_n -= 1; - // Need to adjust exponent based on the amount of digits in the mantissa - exp += mant_digits_n; - if((flags & FLAG_PREC) == 0) { - prec = 6; - } - // Figure out how many symbols decimal point takes up (0 or 1) - int decimal_point_n = 1; - if(prec == 0) { - decimal_point_n = 0; - if(flags & FLAG_HASH) { - decimal_point_n = 1; - } - } - // Figure out how many digits exponent take up and it's sign - // also save exponent digits to a buffer starting from LSD - static ctype exp_buf[64] = {0}; - int exp_digits_n = 0; - ctype exp_sign; - if(exp < 0) { - exp_sign = '-'; - exp = -exp; - } - else { - exp_sign = '+'; - } - { - int64_t e = exp; - do { - exp_buf[exp_digits_n++] = e % 10 + '0'; - e /= 10; - } while(e != 0); - } - // Figure out sign symbol and number of chars it takes up (0 or 1) - int sign_n = 0; - ctype sign_ch; - if(value.sign) { - sign_n = 1; - sign_ch = '-'; - } - else if(flags & FLAG_PLUS) { - sign_n = 1; - sign_ch = '+'; - } - else if(flags & FLAG_SPACE) { - sign_n = 1; - sign_ch = ' '; - } - // Figure out the width of the number - int significand_width = 1 + decimal_point_n + prec; - int exp_part_width = 2 /*e+-*/ + exp_digits_n; - int n_width = sign_n + significand_width + exp_part_width; - // Figure out width-padding required - int pad = 0; - if(width > n_width) pad = width - n_width; - // Print width left-pad if it's made out of space - if(!(flags & FLAG_LEFT) && !(flags & FLAG_ZERO)) while(pad-- > 0) { - out(' '); - } - // Print sign if there - if(sign_n) - out(sign_ch); - // Print width left-pad if it's made out of zero - if(!(flags & FLAG_LEFT) && (flags & FLAG_ZERO)) while(pad-- > 0) { - out('0'); - } - // Print whole part - out(mant_buf[mant_digits_n]); - // Print decimal point - if(decimal_point_n) out('.'); - // Print precision padding - for(int i = mant_digits_n; i < prec; ++i) { - out('0'); - } - if(prec < mant_digits_n) mant_digits_n = prec; - while(mant_digits_n--) - out(mant_buf[mant_digits_n]); - // Print the exponent part - out((flags & FLAG_UPPER)? 'E' : 'e'); - out(exp_sign); - while(exp_digits_n--) - out(exp_buf[exp_digits_n]); - // Print right-pad - if(flags & FLAG_LEFT) while(pad-- > 0) { - out(' '); - } - return w; -} - -#undef out diff --git a/src/fmt/ints.h b/src/fmt/ints.h deleted file mode 100644 index 2a72d73..0000000 --- a/src/fmt/ints.h +++ /dev/null @@ -1,150 +0,0 @@ - -static inline u64 pfx(fmt_int_arg)( - fmt_stream_t *stream, - fmt_t *fmt, - ctype const **strp, - int *signp, - int *basep, - va_list va -) { - ctype const *str = *strp; - // Get integer properties - int base; - int is_signed; - switch(*str) { - case 'o': base = 8; break; - case 'b': base = 2; break; - case 'x': - case 'X': base = 16; break; - default: base = 10; - } - switch(*str) { - case 'd': is_signed = 1; break; - case 'i': is_signed = 1; break; - default: is_signed = 0; - } - if(*str == 'X') { - fmt->flags |= FLAG_UPPER; - } - // Discard some flags - if(base == 10) { - fmt->flags &= ~FLAG_HASH; - } - if(!is_signed) { - fmt->flags &= ~(FLAG_PLUS|FLAG_SPACE); - } - if(fmt->flags & FLAG_PREC) { - fmt->flags &= ~FLAG_ZERO; - } - // Parse sign and abs value of an integer - int sign = 0; - u64 abs_value = 0; - if(is_signed) { - i64 num; - if(fmt->flags & FLAG_LLONG) { - num = (i64)va_arg(va, intll); - } - else if(fmt->flags & FLAG_LONG) { - num = (i64)va_arg(va, intl); - } - else { - num = (i64)va_arg(va, int); - } - // Handle overflow on '-' - if(num == LLONG_MIN) { - sign = 1; - abs_value = (u64)LLONG_MAX + 1; - } - else { - sign = num >= 0? 0 : 1; - num = num >= 0? num : -num; - abs_value = (u64)num; - } - } - else { - if(fmt->flags & FLAG_LLONG) { - abs_value = (u64)va_arg(va, intull); - } - else if(fmt->flags & FLAG_LONG) { - abs_value = (u64)va_arg(va, intul); - } - else { - abs_value = (u64)va_arg(va, intu); - } - } - ++str; - *strp = str; - *basep = base; - *signp = sign; - return abs_value; -} - -static inline int pfx(fmt_int)( - fmt_stream_t *stream, - fmt_t fmt, - int neg, - u64 value, - int base) { - // We'll Write digits into buf in reverse and then call _out_rbuf - int ndigits = 0; - ctype digits[64] = {0}; - // Remove hash flag for 0 values - if(value == 0) fmt.flags &= ~FLAG_HASH; - // Write digits to buffer in reverse (starting from least significant) - do { - int d = (int)(value%base); - value /= base; - if(d < 10) - d += '0'; - else if(fmt.flags & FLAG_UPPER) - d += 'A' - 10; - else d += 'a' - 10; - digits[ndigits++] = d; - } while(value); - // Figure out the length of the prefix (part of number before digit stirng) - int pref_len = 0; - if(fmt.flags & FLAG_HASH) pref_len = base == 8? 1 : 2; - else if(neg) pref_len = 1; - else if(fmt.flags & FLAG_PLUS) pref_len = 1; - else if(fmt.flags & FLAG_SPACE) pref_len = 1; - if(ndigits > fmt.prec) fmt.prec = ndigits; - int num_len = pref_len + fmt.prec; - int pad_len = fmt.width - num_len; - if(!(fmt.flags & FLAG_LEFT)) { - ctype pad_ch = ' '; - if(fmt.flags & FLAG_ZERO) pad_ch = '0'; - while(pad_len-- > 0) { - stream_out(stream, pad_ch); - } - } - // Print width left-pad if it's made out of space - if(!(fmt.flags & FLAG_LEFT) && !(fmt.flags & FLAG_ZERO)) while(pad_len-- > 0) { - stream_out(stream, ' '); - } - // Print prefix - if(fmt.flags & FLAG_HASH) { - stream_out(stream, '0'); - if(base == 16) { stream_out(stream, 'x'); } - else if(base == 2) { stream_out(stream, 'b'); } - } - else if(neg) { stream_out(stream, '-'); } - else if(fmt.flags & FLAG_PLUS) { stream_out(stream, '+'); } - else if(fmt.flags & FLAG_SPACE) { stream_out(stream, ' '); } - // Print width left-pad if it's made out of zero - if(!(fmt.flags & FLAG_LEFT) && (fmt.flags & FLAG_ZERO)) while(pad_len-- > 0) { - stream_out(stream, '0'); - } - // Print zero-pad due to precision - for(int i = ndigits; i < fmt.prec; ++i) { - stream_out(stream, '0'); - } - // Output buffer in reverse - if(ndigits) while(ndigits--) { - stream_out(stream, digits[ndigits]); - } - // Print right-pad - if(fmt.flags & FLAG_LEFT) while(pad_len-- > 0) { - stream_out(stream, ' '); - } - return stream->w; -} diff --git a/src/os_win/assert.c b/src/os_win/assert.c index 6fb7456..a72add5 100644 --- a/src/os_win/assert.c +++ b/src/os_win/assert.c @@ -18,12 +18,12 @@ static void _print_stack_trace() { 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", - " %d: %s\n", - (int)(frames-i-1), - //symbol->Address, - symbol->Name - ); + // printf(//" %u: 0x%"PRIx64" (%s)\n", + // " %d: %s\n", + // (int)(frames-i-1), + // //symbol->Address, + // symbol->Name + // ); } free(symbol); } @@ -39,10 +39,10 @@ void _assert( // For GUI application we display the info into a messagebox char buf[1024]; int i = 0; - i += snprintf(buf+i, sizeof buf-i, "Assertion failed: %s\n", cond); - i += snprintf(buf+i, sizeof buf-i, " Function: %s\n", func); - i += snprintf(buf+i, sizeof buf-i, " File: %s\n", file); - i += snprintf(buf+i, sizeof buf-i, " Line: %d\n", line); + // i += snprintf(buf+i, sizeof buf-i, "Assertion failed: %s\n", cond); + // i += snprintf(buf+i, sizeof buf-i, " Function: %s\n", func); + // i += snprintf(buf+i, sizeof buf-i, " File: %s\n", file); + // i += snprintf(buf+i, sizeof buf-i, " Line: %d\n", line); display_msg: int reaction = MessageBoxA(NULL, buf, "Assertion Failed", 0x00000032L); switch(reaction) { @@ -53,11 +53,11 @@ display_msg: } else { // For console application we print the info to console - printf("Assertion failed: %s\n", cond); - printf(" Function: %s\n", func); - printf(" File: %s\n", file); - printf(" Line: %d\n", line); - printf("Trace:\n"); + // printf("Assertion failed: %s\n", cond); + // printf(" Function: %s\n", func); + // printf(" File: %s\n", file); + // printf(" Line: %d\n", line); + // printf("Trace:\n"); _print_stack_trace(); abort(); } diff --git a/src/os_win/cookie.c b/src/os_win/cookie.c index 3efa641..4eb7941 100644 --- a/src/os_win/cookie.c +++ b/src/os_win/cookie.c @@ -9,7 +9,7 @@ void __security_init_cookie() { void __security_check_cookie(u64 retrieved) { if(__security_cookie != retrieved) { - printf("Bro you've got a buffer overrun\n"); + // printf("Bro you've got a buffer overrun\n"); abort(); } } diff --git a/src/os_win/entry.c b/src/os_win/entry.c index dc8cfac..a71f554 100644 --- a/src/os_win/entry.c +++ b/src/os_win/entry.c @@ -11,7 +11,7 @@ _Noreturn void mainCRTStartup() { _setup_eh(); _setup_heap(); _setup_timer(); - _setup_io(); + _io_init(); __security_init_cookie(); srand(0); @@ -28,7 +28,7 @@ _Noreturn void mainCRTStartup() { _setup_eh(); _setup_heap(); _setup_timer(); - _setup_io(); + _io_init(); __security_init_cookie(); srand(0); diff --git a/src/os_win/environment.c b/src/os_win/environment.c index 08a828a..8cdcd46 100644 --- a/src/os_win/environment.c +++ b/src/os_win/environment.c @@ -34,7 +34,7 @@ _Noreturn void exit(int status) { while(atexit_func_count--) { atexit_funcs[atqexit_func_count](); } - _close_io(); + _io_close(); _Exit(status); } diff --git a/src/os_win/stdio.c b/src/os_win/file.c similarity index 63% rename from src/os_win/stdio.c rename to src/os_win/file.c index c2d2be7..345cc66 100644 --- a/src/os_win/stdio.c +++ b/src/os_win/file.c @@ -1,42 +1,37 @@ -enum stream_width_t { - STREAM_CHAR_UNSET, - STREAM_CHAR_NARROW, - STREAM_CHAR_WIDE, -} typedef stream_width_t; +enum FileMode { + MODE_INPUT, + MODE_OUTPUT, + MODE_UPDATE, +} typedef FileMode; -enum stream_io_mode_t { - STREAM_INPUT, - STREAM_OUTPUT, - STREAM_UPDATE, -} typedef stream_io_mode_t; +enum FileType { + FILE_BINARY, + FILE_TEXT, +} typedef FileType; -enum stream_bt_mode_t { - STREAM_BINARY, - STREAM_TEXT, -} typedef stream_bt_mode_t; - -struct stream_buffer_t typedef stream_buffer_t; -struct stream_buffer_t { - int is_internal; - int mode; +struct FileBuffer typedef FileBuffer; +struct FileBuffer { + int is_internal; + int mode; size_t size; void *data; size_t written; }; struct FILE { - HANDLE handle; - stream_width_t char_width; // This technically needs not be stored - mbstate_t mbstate; - stream_buffer_t buffer; - stream_io_mode_t io_mode; - stream_bt_mode_t bt_mode; - int eof; - int err; - mtx_t lock; - FILE *prev; - FILE *next; + HANDLE handle; + mbstate_t mbstate; + FileBuffer buffer; + FileMode io_mode; + FileType bt_mode; + int eof; + int err; + mtx_t lock; + bool temp; + char *temp_name; + FILE *prev; + FILE *next; }; FILE *stdout; @@ -46,108 +41,121 @@ FILE *stderr; // We hold a linked list of all file streams in order to flush all the buffers // after the program terminates. It might be not a good idea to store all the // files into this linked list, but for now performance is not a concern. -static FILE *streams_to_close = NULL; -static void close_list_add(FILE *stream) { - if(streams_to_close != NULL) { - streams_to_close->next = stream; - stream->prev = streams_to_close; +static FILE *_file_tracker = NULL; + +static void _file_track(FILE *stream) { + if(_file_tracker != NULL) { + _file_tracker->next = stream; + stream->prev = _file_tracker; stream->next = NULL; - streams_to_close = stream; + _file_tracker = stream; } else { - streams_to_close = stream; + _file_tracker = stream; stream->prev = NULL; stream->next = NULL; } } -static void close_list_remove(FILE *stream) { +static void _file_untrack(FILE *stream) { FILE *prev = stream->prev; FILE *next = stream->next; if(prev != NULL) prev->next = next; if(next != NULL) next->prev = prev; - if(next == NULL) streams_to_close = prev; + if(next == NULL) _file_tracker = prev; } -static inline void init_stream( - FILE *stream, - HANDLE handle, - stream_io_mode_t io_mode, - stream_bt_mode_t bt_mode -) { +// Multithreaded access + +static inline void _file_lock_init(FILE *stream) { + mtx_init(&stream->lock, mtx_recursive); +} + +static inline void _file_lock_destroy(FILE *stream) { + mtx_destroy(&stream->lock); +} + +static inline void _file_lock(FILE *stream) { + mtx_lock(&stream->lock); +} + +static inline void _file_unlock(FILE *stream) { + mtx_unlock(&stream->lock); +} + +// Managing file handles + +static inline FILE *_file_create(HANDLE handle, FileMode io_mode, FileType bt_mode) { + FILE *stream = calloc(1, sizeof(FILE)); + if(stream == NULL) { + return NULL; + } stream->handle = handle; - stream->char_width = STREAM_CHAR_UNSET; - stream->mbstate = (mbstate_t){0}; - stream->buffer.mode = _IONBF; stream->io_mode = io_mode; stream->bt_mode = bt_mode; - stream->eof = 0; - stream->err = 0; -} - -static inline FILE *create_stream( - HANDLE handle, - stream_io_mode_t io_mode, - stream_bt_mode_t bt_mode -) { - FILE *stream = malloc(sizeof(FILE)); - if(stream == NULL) return NULL; - init_stream(stream, handle, io_mode, bt_mode); - mtx_init(&stream->lock, mtx_recursive); - close_list_add(stream); + _file_lock_init(stream); + _file_track(stream); return stream; } -static inline void delete_stream(FILE *stream) { - mtx_t lock = stream->lock; - mtx_lock(&lock); +static inline void _file_close(FILE *stream) { + _file_lock(stream); CloseHandle(stream->handle); - close_list_remove(stream); + _file_untrack(stream); + _file_unlock(stream); + _file_lock_destroy(stream); free(stream); - mtx_unlock(&lock); - mtx_destroy(&lock); } -static void _setup_io() { +static void _io_init() { HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hstderr = GetStdHandle(STD_ERROR_HANDLE); HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE); - stdout = create_stream(hstdout, STREAM_UPDATE, STREAM_TEXT); - stderr = create_stream(hstderr, STREAM_UPDATE, STREAM_TEXT); - stdin = create_stream(hstdin, STREAM_INPUT, STREAM_BINARY); + stdout = _file_create(hstdout, MODE_UPDATE, FILE_TEXT); + stderr = _file_create(hstderr, MODE_UPDATE, FILE_TEXT); + stdin = _file_create(hstdin, MODE_INPUT, FILE_BINARY); char *in_buf = calloc(BUFSIZ, sizeof(char)); char *out_buf = calloc(BUFSIZ, sizeof(char)); - stdin->buffer = (stream_buffer_t){1, _IOLBF, BUFSIZ, in_buf}; - stdout->buffer = (stream_buffer_t){1, _IOLBF, BUFSIZ, out_buf}; - stderr->buffer = (stream_buffer_t){1, _IONBF, 0, NULL}; + stdin->buffer = (FileBuffer){1, _IOLBF, BUFSIZ, in_buf}; + stdout->buffer = (FileBuffer){1, _IOLBF, BUFSIZ, out_buf}; + stderr->buffer = (FileBuffer){1, _IONBF, 0, NULL}; - SetConsoleCP(CP_UTF8); // maybe will work someday + SetConsoleCP(CP_UTF8); // Maybe it will work someday SetConsoleOutputCP(CP_UTF8); } -int win_parse_mode( - char const *mode, - stream_io_mode_t *pio_mode, - stream_bt_mode_t *pbt_mode, - DWORD *paccess, - DWORD *pshare, - DWORD *pdisp -) { +static void _io_close() { + while(_file_tracker != NULL) { + FILE *stream = _file_tracker; + fclose(stream); + } +} + +// File mode parsing + +struct WindowsMode typedef WindowsMode; +struct WindowsMode { + DWORD access; + DWORD share; + DWORD disp; +}; + +static int _mode_parse(char const *mode, FileMode *pio_mode, FileType *pbt_mode, WindowsMode *win_mode) { DWORD access = 0; DWORD share = 0; DWORD disp = 0; - stream_io_mode_t io_mode = 0; - stream_bt_mode_t bt_mode = 0; + FileMode io_mode = 0; + FileType bt_mode = 0; int flag_p = 0; int flag_b = 0; int flag_x = 0; switch(*mode++) { - case 'r': io_mode = STREAM_INPUT; break; - case 'w': io_mode = STREAM_OUTPUT; break; - case 'a': io_mode = STREAM_UPDATE; break; + case 'r': io_mode = MODE_INPUT; break; + case 'w': io_mode = MODE_OUTPUT; break; + case 'a': io_mode = MODE_UPDATE; break; default: return 0; } while(*mode) switch(*mode++) { @@ -156,15 +164,14 @@ int win_parse_mode( case 'x': flag_x = 1; break; default: return 0; } - bt_mode = flag_b? STREAM_BINARY : STREAM_TEXT; - // Not sure about the sharing modes + bt_mode = flag_b? FILE_BINARY : FILE_TEXT; switch(io_mode) { - case STREAM_INPUT: { + case MODE_INPUT: { access = GENERIC_READ | (flag_p? GENERIC_WRITE : 0); share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; disp = OPEN_EXISTING; } break; - case STREAM_OUTPUT: { + case MODE_OUTPUT: { access = GENERIC_WRITE | (flag_p? GENERIC_READ : 0); share = 0; disp = CREATE_ALWAYS; @@ -172,37 +179,82 @@ int win_parse_mode( disp = CREATE_NEW; } } break; - case STREAM_UPDATE: { + case MODE_UPDATE: { access = GENERIC_READ | GENERIC_WRITE; share = 0; disp = OPEN_ALWAYS; } break; } - *paccess = access; - *pshare = share; - *pdisp = disp; + win_mode->access = access; + win_mode->share = share; + win_mode->disp = disp; *pio_mode = io_mode; *pbt_mode = bt_mode; return 1; } -FILE *fopen(const char *restrict name, const char *restrict mode) { - DWORD access; - DWORD share; - DWORD disp; - DWORD flags = FILE_FLAG_WRITE_THROUGH; - stream_io_mode_t io_mode; - stream_bt_mode_t bt_mode; - if(!win_parse_mode(mode, &io_mode, &bt_mode, &access, &share, &disp)) { +// Operations on files + +int remove(const char *filename) { + BOOL ok = DeleteFileA(filename); + return !ok; +} + +int rename(const char *old, const char *new) { + BOOL ok = MoveFileA(old, new); + return !ok; +} + +// Opening/closing files + +char *tmpnam(char *s) { + static char internal_buffer[L_tmpnam]; + char *buffer; + if(s != NULL) { + buffer = s; + } + else { + buffer = &internal_buffer[0]; + } + UINT num = GetTempFileNameA(".", ".t_", 0, buffer); + if(num == 0) { return NULL; } + else { + return buffer; + } +} + +FILE *tmpfile(void) { + char *file_name = malloc(L_tmpnam); + UINT num = GetTempFileNameA(".", ".t_", 0, &file_name[0]); + if(!num) { + return NULL; + } + FILE *tmp_file = fopen(&file_name[0], "wb+"); + tmp_file->temp = true; + tmp_file->temp_name = file_name; + return tmp_file; +} + +FILE *fopen(const char *restrict name, const char *restrict mode) { + WindowsMode win_mode; + DWORD flags = FILE_FLAG_WRITE_THROUGH; + FileMode io_mode; + FileType bt_mode; + if(!_mode_parse(mode, &io_mode, &bt_mode, &win_mode)) { + return NULL; + } + DWORD access = win_mode.access; + DWORD share = win_mode.share; + DWORD disp = win_mode.disp; HANDLE handle = CreateFileA(name, access, share, NULL, disp, flags, NULL); if(handle == INVALID_HANDLE_VALUE) { return NULL; } - FILE *stream = create_stream(handle, io_mode, bt_mode); + FILE *stream = _file_create(handle, io_mode, bt_mode); void *buffer_data = malloc(BUFSIZ); - stream->buffer = (stream_buffer_t) {1, _IOFBF, BUFSIZ, buffer_data}; + stream->buffer = (FileBuffer) {1, _IOFBF, BUFSIZ, buffer_data}; return stream; } @@ -211,15 +263,16 @@ FILE *freopen(const char *restrict name, const char *restrict mode, FILE *restri return NULL; } fflush(stream); - DWORD access; - DWORD share; - DWORD disp; + WindowsMode win_mode; DWORD flags = FILE_FLAG_WRITE_THROUGH; - stream_io_mode_t io_mode; - stream_bt_mode_t bt_mode; - if(!win_parse_mode(mode, &io_mode, &bt_mode, &access, &share, &disp)) { + FileMode io_mode; + FileType bt_mode; + if(!_mode_parse(mode, &io_mode, &bt_mode, &win_mode)) { return NULL; } + DWORD access = win_mode.access; + DWORD share = win_mode.share; + DWORD disp = win_mode.disp; if(name == NULL) { HANDLE handle = ReOpenFile(stream->handle, access, share, flags); if(handle == INVALID_HANDLE_VALUE) { @@ -232,15 +285,14 @@ FILE *freopen(const char *restrict name, const char *restrict mode, FILE *restri if(handle == INVALID_HANDLE_VALUE) { return NULL; } - init_stream(stream, handle, io_mode, bt_mode); + *stream = (FILE) {0}; + stream->handle = handle; + stream->io_mode = io_mode; + stream->bt_mode = bt_mode; } return stream; } -FILE *tmpfile(void) { - return NULL; -} - int fclose(FILE *stream) { if(fflush(stream) == EOF) { return EOF; @@ -251,17 +303,63 @@ int fclose(FILE *stream) { if(!CloseHandle(stream->handle)) { return EOF; } + if(stream->temp) { + BOOL err = DeleteFileA(stream->temp_name); + free(stream->temp_name); + return err; + } return 0; } -static void _close_io() { - while(streams_to_close != NULL) { - FILE *stream = streams_to_close; - fflush(stream); - delete_stream(stream); +// Buffering + +int setvbuf(FILE *restrict stream, char *restrict ptr, int mode, size_t size) { + if(mode != _IOFBF && mode != _IOLBF && mode != _IONBF) { + return 1; + } + _file_lock(stream); + FileBuffer *buffer = &stream->buffer; + buffer->mode = mode; + if(ptr == NULL) { + buffer->data = realloc(buffer->data, size); + buffer->size = size; + } + else { + buffer->data = ptr; + buffer->size = size; + } + _file_unlock(stream); + return 0; +} + +void setbuf(FILE *restrict stream, char *restrict buf) { + if(buf == NULL) { + setvbuf(stream, NULL, _IONBF, 0); + } + else { + setvbuf(stream, buf, _IOFBF, BUFSIZ); } } +int fflush(FILE *stream) { + _file_lock(stream); + int res = 0; + FileBuffer *buffer = &stream->buffer; + void *data = buffer->data; + size_t size = buffer->written; + DWORD bytes_written; + BOOL ok = WriteFile(stream->handle, data, size, &bytes_written, NULL); + if(!ok) { + res = EOF; + stream->eof = 1; + } + buffer->written = 0; + _file_unlock(stream); + return res; +} + +// Errors + int feof(FILE *stream) { return stream->eof; } @@ -276,57 +374,14 @@ void clearerr(FILE *stream) { } void perror(char const *s) { - printf("%s: %s\n", s, strerror(errno)); + // printf("%s: %s\n", s, strerror(errno)); } -int setvbuf(FILE *restrict stream, char *restrict ptr, int mode, size_t size) { - if(mode != _IOFBF && mode != _IOLBF && mode != _IONBF) { - return 1; - } - mtx_lock(&stream->lock); - stream_buffer_t *buffer = &stream->buffer; - buffer->mode = mode; - if(ptr == NULL) { - buffer->data = realloc(buffer->data, size); - buffer->size = size; - } - else { - buffer->data = ptr; - buffer->size = size; - } - mtx_unlock(&stream->lock); - return 0; -} - -void setbuf(FILE *restrict stream, char *restrict buf) { - if(buf == NULL) { - setvbuf(stream, NULL, _IONBF, 0); - } - else { - setvbuf(stream, buf, _IOFBF, BUFSIZ); - } -} - -int fflush(FILE *stream) { - mtx_lock(&stream->lock); - int res = 0; - stream_buffer_t *buffer = &stream->buffer; - void *data = buffer->data; - size_t size = buffer->written; - DWORD bytes_written; - BOOL ok = WriteFile(stream->handle, data, size, &bytes_written, NULL); - if(!ok) { - res = EOF; - stream->eof = 1; - } - buffer->written = 0; - mtx_unlock(&stream->lock); - return res; -} +// File reads/writes int fputc(int c, FILE *stream) { - mtx_lock(&stream->lock); - stream_buffer_t *buffer = &stream->buffer; + _file_lock(stream); + FileBuffer *buffer = &stream->buffer; int res = c; if(buffer->mode == _IONBF) { unsigned char str[1] = {c}; @@ -335,7 +390,7 @@ int fputc(int c, FILE *stream) { if(!ok) { res = EOF; stream->err = 1; - goto cum; + goto end; } } @@ -349,19 +404,19 @@ int fputc(int c, FILE *stream) { } if(needs_flush) { if(fflush(stream) == EOF) { - goto cum; + goto end; } } } -cum: - mtx_unlock(&stream->lock); +end: + _file_unlock(stream); return res; } int fgetc(FILE *stream) { - mtx_lock(&stream->lock); + _file_lock(stream); int res = 0; - stream_buffer_t *buffer = &stream->buffer; + FileBuffer *buffer = &stream->buffer; int read_from_disk = 1; if(buffer->mode != _IONBF) { unsigned char *data = buffer->data; @@ -377,95 +432,47 @@ int fgetc(FILE *stream) { if(bytes_read != 1) { res = EOF; stream->eof = 1; - goto cum; + goto end; } if(!ok) { res = EOF; - goto cum; + goto end; } res = buf[0]; } -cum: - mtx_unlock(&stream->lock); +end: + _file_unlock(stream); return res; } int ungetc(int c, FILE *stream) { - mtx_lock(&stream->lock); + _file_lock(stream); int res; - stream_buffer_t *buffer = &stream->buffer; + FileBuffer *buffer = &stream->buffer; if(buffer->mode == _IONBF) { res = EOF; - goto cum; + goto end; } else { if(c == EOF) { res = EOF; - goto cum; + goto end; } if(buffer->written == buffer->size) { res = EOF; - goto cum; + goto end; } unsigned char *data = buffer->data; data[buffer->written++] = (unsigned char)c; res = c; } -cum: - mtx_unlock(&stream->lock); +end: + _file_unlock(stream); return res; } -int fgetpos(FILE *restrict stream, fpos_t *restrict pos) { - LONG pos_hi = 0; - DWORD pos_lo = SetFilePointer(stream->handle, 0, &pos_hi, FILE_CURRENT); - if(pos_lo == INVALID_SET_FILE_POINTER) { - return 1; - } - int64_t offset = ((int64_t)pos_hi << 32) | (int64_t)pos_lo; - pos->offset = offset; - pos->mbstate = stream->mbstate; - return 0; -} - -int fseek(FILE *stream, long int offset, int whence) { - // Note(bumbread): the SEEK_SET, SEEK_CUR and SEEK_END are defined to match - // Windows' constants, so no conversion is requierd between them. - LONG pos_hi = 0; - DWORD pos_lo = SetFilePointer(stream->handle, offset, &pos_hi, whence); - if(pos_lo == INVALID_SET_FILE_POINTER) { - return -1L; - } - return 0; -} - -int fsetpos(FILE *stream, const fpos_t *pos) { - LONG pos_hi = pos->offset >> 32; - LONG pos_lo = (LONG)(pos->offset & 0xffffffff); - DWORD status = SetFilePointer(stream->handle, pos_lo, &pos_hi, FILE_BEGIN); - if(status == INVALID_SET_FILE_POINTER) { - return 1; - } - stream->mbstate = pos->mbstate; - return 0; -} - -long int ftell(FILE *stream) { - LONG pos_hi = 0; - DWORD pos_lo = SetFilePointer(stream->handle, 0, &pos_hi, FILE_CURRENT); - if(pos_lo == INVALID_SET_FILE_POINTER) { - return -1L; - } - int64_t offset = ((int64_t)pos_hi << 32) | (int64_t)pos_lo; - return offset; -} - -void rewind(FILE *stream) { - fseek(stream, 0, SEEK_SET); -} - size_t fwrite(void const *restrict buffer, size_t size, size_t count, FILE *restrict stream) { - mtx_lock(&stream->lock); + _file_lock(stream); unsigned char const *bytes = (unsigned char const*)buffer; size_t num_written; for(num_written = 0; num_written < count; ++num_written) { @@ -478,12 +485,12 @@ size_t fwrite(void const *restrict buffer, size_t size, size_t count, FILE *rest bytes += size; } end: - mtx_unlock(&stream->lock); + _file_unlock(stream); return num_written; } size_t fread(void *restrict buffer, size_t size, size_t count, FILE *restrict stream) { - mtx_lock(&stream->lock); + _file_lock(stream); unsigned char *bytes = (unsigned char *)buffer; size_t num_read; for(num_read = 0; num_read < count; ++num_read) { @@ -497,7 +504,7 @@ size_t fread(void *restrict buffer, size_t size, size_t count, FILE *restrict st bytes += size; } end: - mtx_unlock(&stream->lock); + _file_unlock(stream); return num_read; } @@ -517,7 +524,7 @@ char *fgets(char *restrict str, int count, FILE *restrict stream) { str[0] = 0; return str; } - mtx_lock(&stream->lock); + _file_lock(stream); int i; for(i = 0; i < count-1; ++i) { int c = fgetc(stream); @@ -535,12 +542,12 @@ char *fgets(char *restrict str, int count, FILE *restrict stream) { } } str[i] = 0; - mtx_unlock(&stream->lock); + _file_unlock(stream); return str; } int fputs(char const *str, FILE *stream) { - mtx_lock(&stream->lock); + _file_lock(stream); int res = 0; while(*str) { int c = fputc(*str++, stream); @@ -549,7 +556,7 @@ int fputs(char const *str, FILE *stream) { break; } } - mtx_unlock(&stream->lock); + _file_unlock(stream); return res; } @@ -562,3 +569,55 @@ int puts(char const *str) { char *gets(char *str) { return fgets(str, 0x7fffffff, stdin); } + +// File positioning: + +int fgetpos(FILE *restrict stream, fpos_t *restrict pos) { + LONG pos_hi = 0; + DWORD pos_lo = SetFilePointer(stream->handle, 0, &pos_hi, FILE_CURRENT); + if(pos_lo == INVALID_SET_FILE_POINTER) { + return 1; + } + int64_t offset = ((int64_t)pos_hi << 32) | (int64_t)pos_lo; + pos->offset = offset; + pos->mbstate.leftover = stream->mbstate.leftover; + pos->mbstate.high_surrogate = stream->mbstate.high_surrogate; + return 0; +} + +int fseek(FILE *stream, long int offset, int whence) { + // Note(bumbread): the SEEK_SET, SEEK_CUR and SEEK_END are defined to match + // the Windows constants, so no conversion is requierd between them. + LONG pos_hi = 0; + DWORD pos_lo = SetFilePointer(stream->handle, offset, &pos_hi, whence); + if(pos_lo == INVALID_SET_FILE_POINTER) { + return -1L; + } + return 0; +} + +int fsetpos(FILE *stream, const fpos_t *pos) { + LONG pos_hi = pos->offset >> 32; + LONG pos_lo = (LONG)(pos->offset & 0xffffffff); + DWORD status = SetFilePointer(stream->handle, pos_lo, &pos_hi, FILE_BEGIN); + if(status == INVALID_SET_FILE_POINTER) { + return 1; + } + stream->mbstate.leftover = pos->mbstate.leftover; + stream->mbstate.high_surrogate = pos->mbstate.high_surrogate; + return 0; +} + +long int ftell(FILE *stream) { + LONG pos_hi = 0; + DWORD pos_lo = SetFilePointer(stream->handle, 0, &pos_hi, FILE_CURRENT); + if(pos_lo == INVALID_SET_FILE_POINTER) { + return -1L; + } + int64_t offset = ((int64_t)pos_hi << 32) | (int64_t)pos_lo; + return offset; +} + +void rewind(FILE *stream) { + fseek(stream, 0, SEEK_SET); +} diff --git a/src/os_win/threads.c b/src/os_win/thread.c similarity index 100% rename from src/os_win/threads.c rename to src/os_win/thread.c diff --git a/src/os_win/win.h b/src/os_win/win.h index adc591c..ea936d4 100644 --- a/src/os_win/win.h +++ b/src/os_win/win.h @@ -10,5 +10,4 @@ static void _setup_timer(void); static void _setup_eh(); static void _setup_heap(); -static void _setup_io(); -static void _close_io(); \ No newline at end of file +static void _io_close(); \ No newline at end of file diff --git a/test/test_io.c b/test/test_io.c index cf4d0a1..04a6f6c 100644 --- a/test/test_io.c +++ b/test/test_io.c @@ -2,29 +2,10 @@ #include #include #include -int main(void) -{ - // prepare a file holding 4 values of type char - enum {SIZE = 4}; - FILE* fp = fopen("test.bin", "wb"); - assert(fp); - fputc('a', fp); - fputc('b', fp); - fputc('d', fp); - fputc('c', fp); - fclose(fp); - - // demo using fsetpos to return to the beginning of a file - fp = fopen("test.bin", "rb"); - fpos_t pos; - int c = fgetc(fp); - printf("First value in the file: %c\n", c); - fgetpos(fp, &pos); - c = fgetc(fp); - printf("Second value in the file: %c\n", c); - fsetpos(fp,&pos); - c = fgetc(fp); - printf("Second value in the file again: %c\n", c); - fclose(fp); + +int main(void) { + FILE *tmp = tmpfile(); + fputc('a', tmp); + fclose(tmp); return 0; }