From 31dbc0abd14929001745f93c5b2d31ffe575ec26 Mon Sep 17 00:00:00 2001 From: flysand7 Date: Sun, 23 Jul 2023 01:30:04 +1100 Subject: [PATCH] ANEW --- .gitignore | 2 + build.ps1 | 2 +- build.sh | 18 + docs/assert.md | 78 --- docs/complex.md | 4 - docs/readme.md | 42 -- include/_stdatomic.h | 13 - include/assert.h | 35 -- include/cia_definitions.h | 69 +++ include/complex.h | 4 - include/ctype.h | 17 - include/errno.h | 13 - include/fenv.h | 62 --- include/float.h | 43 -- include/inttypes.h | 275 ---------- include/iso646.h | 14 - include/limits.h | 87 ---- include/locale.h | 45 -- include/math.h | 301 ----------- include/os_win/threads_types.h | 38 -- include/signal.h | 26 - include/std.h | 31 -- include/stdalign.h | 8 - include/stdbool.h | 8 - include/stddef.h | 24 - include/stdint.h | 153 ------ include/stdio.h | 137 ----- include/stdlib.h | 132 ----- include/stdnoreturn.h | 6 - include/string.h | 91 ---- include/tgmath.h | 101 ---- include/threads.h | 89 ---- include/time.h | 78 --- include/uchar.h | 48 -- include/wchar.h | 187 ------- include/wctype.h | 29 -- license | 13 + readme.md | 58 ++- src/ciabatta.c | 79 +-- src/conv/decfloat/decfloat.c | 319 ------------ src/conv/decfloat/decfloat_table.h | 367 ------------- src/conv/digits.c | 48 -- src/conv/float.c | 130 ----- src/conv/int.c | 169 ------ src/conv/strpfx.c | 10 - src/ctype.c | 67 --- src/errno.c | 2 - src/fenv.c | 121 ----- src/linux/crt_ctors.c | 32 ++ src/linux/crt_entry.asm | 39 ++ src/linux/entry.c | 11 + src/linux/syscall.c | 137 +++++ src/locale.c | 61 --- src/math/basic.c | 140 ----- src/math/bits.c | 100 ---- src/math/cordic/cordic_data.h | 202 -------- src/math/cordic/cordic_dataf.h | 106 ---- src/math/cordic/cordic_datal.h | 202 -------- src/math/cordic/maketab.py | 58 --- src/math/division.c | 248 --------- src/math/gen_math.c | 28 - src/math/gen_math.h | 228 --------- src/math/round.c | 522 ------------------- src/os_linux/linux_environment.c | 85 --- src/os_linux/syscalls.asm | 9 - src/os_win/assert.c | 64 --- src/os_win/chkstk.asm | 28 - src/os_win/cmdline.c | 116 ----- src/os_win/cookie.c | 15 - src/os_win/entry.c | 42 -- src/os_win/env.c | 138 ----- src/os_win/file.c | 628 ----------------------- src/os_win/mem.c | 129 ----- src/os_win/signal.c | 85 --- src/os_win/thread.c | 362 ------------- src/os_win/time.c | 439 ---------------- src/os_win/win.h | 13 - src/stdlib/algorithm.c | 82 --- src/stdlib/multibyte.c | 21 - src/stdlib/random.c | 15 - src/string.c | 243 --------- src/uchar.c | 126 ----- src/util.c | 76 --- src/wchar.c | 99 ---- src/wctype.c | 121 ----- test.sh | 8 + tests/crt.c | 795 +---------------------------- tests/empty.c | 4 + tests/testing.h | 471 +++++++++++++++++ tests/windows_utf8.c | 20 - tests/winmain.c | 57 --- utf8.rc => utf8/utf8.rc | 0 utf8.xml => utf8/utf8.xml | 0 93 files changed, 858 insertions(+), 9240 deletions(-) create mode 100755 build.sh delete mode 100644 docs/assert.md delete mode 100644 docs/complex.md delete mode 100644 docs/readme.md delete mode 100644 include/_stdatomic.h delete mode 100644 include/assert.h create mode 100644 include/cia_definitions.h delete mode 100644 include/complex.h delete mode 100644 include/ctype.h delete mode 100644 include/errno.h delete mode 100644 include/fenv.h delete mode 100644 include/float.h delete mode 100644 include/inttypes.h delete mode 100644 include/iso646.h delete mode 100644 include/limits.h delete mode 100644 include/locale.h delete mode 100644 include/math.h delete mode 100644 include/os_win/threads_types.h delete mode 100644 include/signal.h delete mode 100644 include/std.h delete mode 100644 include/stdalign.h delete mode 100644 include/stdbool.h delete mode 100644 include/stddef.h delete mode 100644 include/stdint.h delete mode 100644 include/stdio.h delete mode 100644 include/stdlib.h delete mode 100644 include/stdnoreturn.h delete mode 100644 include/string.h delete mode 100644 include/tgmath.h delete mode 100644 include/threads.h delete mode 100644 include/time.h delete mode 100644 include/uchar.h delete mode 100644 include/wchar.h delete mode 100644 include/wctype.h create mode 100644 license delete mode 100644 src/conv/decfloat/decfloat.c delete mode 100644 src/conv/decfloat/decfloat_table.h delete mode 100644 src/conv/digits.c delete mode 100644 src/conv/float.c delete mode 100644 src/conv/int.c delete mode 100644 src/conv/strpfx.c delete mode 100644 src/ctype.c delete mode 100644 src/errno.c delete mode 100644 src/fenv.c create mode 100644 src/linux/crt_ctors.c create mode 100644 src/linux/crt_entry.asm create mode 100644 src/linux/entry.c create mode 100644 src/linux/syscall.c delete mode 100644 src/locale.c delete mode 100644 src/math/basic.c delete mode 100644 src/math/bits.c delete mode 100644 src/math/cordic/cordic_data.h delete mode 100644 src/math/cordic/cordic_dataf.h delete mode 100644 src/math/cordic/cordic_datal.h delete mode 100644 src/math/cordic/maketab.py delete mode 100644 src/math/division.c delete mode 100644 src/math/gen_math.c delete mode 100644 src/math/gen_math.h delete mode 100644 src/math/round.c delete mode 100644 src/os_linux/linux_environment.c delete mode 100644 src/os_linux/syscalls.asm delete mode 100644 src/os_win/assert.c delete mode 100644 src/os_win/chkstk.asm delete mode 100644 src/os_win/cmdline.c delete mode 100644 src/os_win/cookie.c delete mode 100644 src/os_win/entry.c delete mode 100644 src/os_win/env.c delete mode 100644 src/os_win/file.c delete mode 100644 src/os_win/mem.c delete mode 100644 src/os_win/signal.c delete mode 100644 src/os_win/thread.c delete mode 100644 src/os_win/time.c delete mode 100644 src/os_win/win.h delete mode 100644 src/stdlib/algorithm.c delete mode 100644 src/stdlib/multibyte.c delete mode 100644 src/stdlib/random.c delete mode 100644 src/string.c delete mode 100644 src/uchar.c delete mode 100644 src/util.c delete mode 100644 src/wchar.c delete mode 100644 src/wctype.c create mode 100755 test.sh create mode 100644 tests/empty.c create mode 100644 tests/testing.h delete mode 100644 tests/windows_utf8.c delete mode 100644 tests/winmain.c rename utf8.rc => utf8/utf8.rc (100%) rename utf8.xml => utf8/utf8.xml (100%) diff --git a/.gitignore b/.gitignore index b1a0cf4..e7386fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ bin a.out +*.a +*.so *.exe *.lib *.obj diff --git a/build.ps1 b/build.ps1 index e6dc962..b6c1da1 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,6 +1,6 @@ # Generate the resources for UTF8 -windres -o utf8.obj utf8.rc +windres -o utf8/utf8.obj utf8/utf8.rc # Compile chkstk nasm src\os_win\chkstk.asm -o chkstk.o -fwin64 diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..1c5a562 --- /dev/null +++ b/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +[ ! -d "lib" ] && mkdir "lib" +[ ! -d "bin" ] && mkdir "bin" + +nasm -f elf64 "src/linux/crt_entry.asm" -o "bin/crt_entry.o" +clang -fPIC -nostdlib -I "include" -g "src/linux/crt_ctors.c" -c -o "bin/crt_ctors.o" +clang -fPIC -nostdlib -I "include" -g "src/ciabatta.c" -c -o "bin/ciabatta.o" + +rm "$LIB_FILE" 2> /dev/null + +if [ "$1" != "-shared" ]; then + llvm-ar -q "lib/ciabatta.a" "bin/crt_ctors.o" "bin/crt_entry.o" "bin/ciabatta.o" +else + clang -fPIC -nostdlib -shared -o "lib/ciabatta.so" "bin/ciabatta.o" + cp "bin/crt_ctors.o" "lib/ctors.o" + cp "bin/crt_entry.o" "lib/entry.o" +fi diff --git a/docs/assert.md b/docs/assert.md deleted file mode 100644 index 1dee247..0000000 --- a/docs/assert.md +++ /dev/null @@ -1,78 +0,0 @@ - -# assert.h - debug assertions - -Macro definitions: - -- [`assert(expr)`](#assert) -- [`static_assert`](#static-assert) - -## [assert](#assert) - -Assert a given condition is true, otherwise abort execution of a program. - -The macro checks whether `expr` is true, and if not, prints the -diagnostic information and then aborts execution in a way equivalent to calling -abort() function (See SIGABRT). - -If `_DEBUG` macro is defined, assert does not print a diagnostic message, and -instead simply causes a debug break. - -If NDEBUG macro is defined assert expands to an empty statement. If both NDEBUG -and `_DEBUG` are defined, then `_DEBUG` macro is ignored. - -```c -#if defined(NDEBUG) - #define assert(expr) ((void)0) -#elif defined(`_DEBUG`) - #define assert(expr) /* debug break */ -#else - #define assert(expr) /* print diagnostic, then abort */ -#endif -``` - -
-Example - -```c -// Uncomment to disable assert -//#define NDEBUG -#include - -int factorial(int n) { - assert(n >= 0); - if(n == 0) return 1; - return n*factorial(n-1); -} - -int main() { - printf("Factorial of %d is %d\n", 10, factorial(10)); - printf("Factorial of %d is %d\n", -1, factorial(-1)); - return 0; -} -``` - -The first function would print 3628800, the second would trigger an assert. -Output: - -``` -Factorial of 10 is 3628800 -Assertion failed: n >= 0 - Function: factorial - File: test\test_assert.c - Line: 4 -Trace: - 4: factorial - 3: main - 2: mainCRTStartup - 1: BaseThreadInitThunk - 0: RtlUserThreadStart -``` -
- -## [static_assert](#static-assert) - -Keyword macro that expands to C11 keyword `_Static_assert`. - -```c -#define static_assert _Static_assert -``` diff --git a/docs/complex.md b/docs/complex.md deleted file mode 100644 index 1ce3ab1..0000000 --- a/docs/complex.md +++ /dev/null @@ -1,4 +0,0 @@ - -# complex.h - complex number support - -Not supported/implemented diff --git a/docs/readme.md b/docs/readme.md deleted file mode 100644 index 7e54ef5..0000000 --- a/docs/readme.md +++ /dev/null @@ -1,42 +0,0 @@ - -# Ciabatta - -Ciabatta is a C standard library implementation. The goal is to provide a -cross-platform implementation that provides it's own documentation, clarifying -implementation-defined details, as well as provides additional functionality, -like sockets, or unicode processing, the kind of functionality that is used -in different kinds of programs. - -## Headers - -The implementation doesn't provide all headers. The headers that aren't -provided are supposed to be provided by compiler. The list of such headers: - -- stdarg.h -- setjmp.h - -The headers that are provided have documentation included: - -- [assert.h](assert.md) -- [complex.h](complex.md) -- [ctype.h](ctype.md) -- [errno.h](errno.md) -- [fenv.h](fenv.md) -- [inttypes.h](inttypes.md) -- [locale.h](locale.md) -- [math.h](math.md) -- [signal.h](signal.md) -- [stdio.h](stdio.md) -- [stdlib.h](stdlib.md) -- [string.h](string.md) -- [tgmath.h](tgmath.md) -- [threads.h](threads.md) -- [time.h](time.md) -- [uchar.h](uchar.md) -- [wchar.h](wchar.md) -- [wctype.h](wctype.md) - -## Locales - -Not supported. The `char *` strings are assumed to be encoded using ASCII/UTF-8 -encoding. diff --git a/include/_stdatomic.h b/include/_stdatomic.h deleted file mode 100644 index 84f60d3..0000000 --- a/include/_stdatomic.h +++ /dev/null @@ -1,13 +0,0 @@ - -#pragma once - -enum memory_order { - memory_order_relaxed, - memory_order_consume, - memory_order_acquire, - memory_order_release, - memory_order_acq_rel, - memory_order_seq_cst -}; - -typedef int atomic_int; diff --git a/include/assert.h b/include/assert.h deleted file mode 100644 index 7b038be..0000000 --- a/include/assert.h +++ /dev/null @@ -1,35 +0,0 @@ - -#pragma once - -#if defined(_MSC_VER) && !defined(__clang__) - #define _Noreturn -#endif - -void _assert( - char const *cond, - char const *func, - char const *file, - int line -); - -#if defined(NDEBUG) - #define assert(ignore) ((void)0) -#elif defined(_DEBUG) - #if defined(__GNUC__) || defined(__CUIKC__) - #define assert(c) if (!(c)) __builtin_trap() - #elif defined(_MSC_VER) - #define assert(c) if (!(c)) __debugbreak() - #else - // In debug mode there shouldn't be any optimizations so this should - // work as a simple way to cause a trap. - #define assert(c) do { if (!(c)) *(volatile int *)0 = 0; } while(0) - #endif -#else - #define _static_assert _Static_assert - #define assert(condition) \ - do { \ - if(!(condition)) { \ - _assert(#condition, __func__, __FILE__, __LINE__); \ - } \ - } while(0) -#endif diff --git a/include/cia_definitions.h b/include/cia_definitions.h new file mode 100644 index 0000000..48fc08c --- /dev/null +++ b/include/cia_definitions.h @@ -0,0 +1,69 @@ + +#pragma once + +// Pre-C23 keyword macros +#define static_assert _Static_assert + +// Platform macros +#define CIA_LINUX 1 +#define CIA_WINDOWS 2 +#define CIA_ANDROID 3 + +// Platform detection +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) + #define CIA_OS CIA_WINDOWS + #if !defined(_WIN64) + #error "32-bit windows is not supported" + #endif +#elif __APPLE__ + #error "Apple OS's not supported and will never be unless you want to write the support for it" +#elif __ANDROID__ + #define CIA_OS CIA_ANDROID +#elif __linux__ + #define CIA_OS CIA_LINUX +#else + #error "Unable to detect the OS" +#endif + +// Convenience platform checking macros +#define os_is_linux() (CIA_OS == CIA_LINUX) +#define os_is_windows() (CIA_OS == CIA_WINDOWS) +#define os_is_android() (CIA_OS == CIA_ANDROID) + +// Assert commonly-accepted platform-invariant sizes +static_assert(sizeof(char) == 1, "Char isn't 1 bytes long"); +static_assert(sizeof(short) == 2, "Short isn't 2 bytes long"); +static_assert(sizeof(int) == 4, "Int isn't 4 bytes long"); +static_assert(sizeof(long long int) == 8, "Long long isn't 8 bytes long"); +#if os_is_linux() + static_assert(sizeof(long) == 8, "Long on linux isn't 8 bytes"); +#elif os_is_windows() + static_assert(sizeof(long) == 4, "Long on windows isn't 4 bytes"); +#endif + +// stdint.h type definitions +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +#if os_is_linux() + typedef signed long int64_t; + typedef unsigned long uint64_t; +#elif os_is_windows() + typedef signed long long int64_t; + typedef unsigned long long uint64_t; +#else + #error "Platform not implemented" +#endif + +// Short type definitions +typedef int8_t i8; +typedef uint8_t u8; +typedef int16_t i16; +typedef uint16_t u16; +typedef int32_t i32; +typedef uint32_t u32; +typedef int64_t i64; +typedef uint64_t u64; diff --git a/include/complex.h b/include/complex.h deleted file mode 100644 index 70a21d5..0000000 --- a/include/complex.h +++ /dev/null @@ -1,4 +0,0 @@ - -#pragma once - -#error "Complex Numbers aren't implemented" diff --git a/include/ctype.h b/include/ctype.h deleted file mode 100644 index e24a3d9..0000000 --- a/include/ctype.h +++ /dev/null @@ -1,17 +0,0 @@ - -#pragma once - -int isalnum(int c); -int isalpha(int c); -int isblank(int c); -int iscntrl(int c); -int isdigit(int c); -int isgraph(int c); -int islower(int c); -int isprint(int c); -int ispunct(int c); -int isspace(int c); -int isupper(int c); -int isxdigit(int c); -int tolower(int c); -int toupper(int c); diff --git a/include/errno.h b/include/errno.h deleted file mode 100644 index e9fae4b..0000000 --- a/include/errno.h +++ /dev/null @@ -1,13 +0,0 @@ - -#pragma once - -#define EDOM 1 -#define EILSEQ 2 -#define ERANGE 3 - -// TODO: figure out why _Thread_local doesn't work -extern _Thread_local int errno; - -#if __STDC_WANT_LIB_EXT1__ == 1 - typedef int errno_t; -#endif diff --git a/include/fenv.h b/include/fenv.h deleted file mode 100644 index 234803a..0000000 --- a/include/fenv.h +++ /dev/null @@ -1,62 +0,0 @@ - -#pragma once - -typedef unsigned fexcept_t; -typedef unsigned fenv_t; - -// These constants correspond to bits in MXCSR register -#define FE_INVALID (1 << 0) -#define FE_DIVBYZERO (1 << 2) -#define FE_OVERFLOW (1 << 3) -#define FE_UNDERFLOW (1 << 4) -#define FE_INEXACT (1 << 5) -#define FE_DENORM (1 << 1) -#define FE_DAZ (1 << 6) - -#define FE_ALL_EXCEPT \ - ( FE_INVALID \ - | FE_DIVBYZERO \ - | FE_OVERFLOW \ - | FE_UNDERFLOW \ - | FE_INEXACT \ - | FE_DENORM \ - | FE_DAZ ) - -// These constants correspond to the rounding field in MXCSR register -#define FE_TONEAREST 0x00 -#define FE_DOWNWARD 0x01 -#define FE_UPWARD 0x02 -#define FE_TOWARDZERO 0x03 - -extern fenv_t _fe_dfl_env; -#define FE_DFL_ENV (&_fe_dfl_env) - -// Exceptions - -int feclearexcept(int excepts); -int fegetexceptflag(fexcept_t *flagp, int excepts); -int feraiseexcept(int excepts); -int fesetexceptflag(const fexcept_t *flagp, int excepts); -int fetestexcept(int excepts); - -// Rounding behaviour - -int fegetround(void); -int fesetround(int round); - -// Environment - -int fegetenv(fenv_t *env); -int fesetenv(fenv_t *env); -int feholdexcept(fenv_t *envp); -int feupdateenv(fenv_t const *envp); - -// Non-standard functions - -int _feenabletraps(int excepts); -int _fedisabletraps(int excepts); - -#if defined(_CIABATTA_EXT) - #define feenabletraps _feenabletraps - #define fedisabletraps _fedisabletraps -#endif diff --git a/include/float.h b/include/float.h deleted file mode 100644 index 78c5322..0000000 --- a/include/float.h +++ /dev/null @@ -1,43 +0,0 @@ - -#pragma once - -#define DECIMAL_DIG 10 -#define FLT_ROUNDS 1 -#define FLT_EVAL_METHOD 0 - -#define FLT_RADIX 2 -#define FLT_DECIMAL_DIG 6 -#define FLT_MIN 0x1.000000p-126 -#define FLT_MAX 0x1.7ffffep+127 -#define FLT_TRUE_MIN 0x1.000000p-149 -#define FLT_EPSILON 0x1.000002p+0 -#define FLT_MANT_DIG 23 -#define FLT_MIN_EXP -125 -#define FLT_MAX_EXP +128 -#define FLT_MIN_10_EXP -37 -#define FLT_MAX_10_EXP +38 -#define FLT_HAS_SUBNORM 1 - -#define DBL_DECIMAL_DIG 10 -#define DBL_MIN 0x1.0000000000000p-1022 -#define DBL_MAX 0x1.fffffffffffffp+1023 -#define DBL_TRUE_MIN 0x1.0000000000000p-1074 -#define DBL_EPSILON 0x1.0000000000001p+0 -#define DBL_MANT_DIG 11 -#define DBL_MIN_EXP -1022 -#define DBL_MAX_EXP +1024 -#define DBL_MIN_10_EXP -307 -#define DBL_MAX_10_EXP +308 -#define DBL_HAS_SUBNORM 1 - -#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG -#define LDBL_MIN DBL_MIN -#define LDBL_MAX DBL_MAX -#define LDBL_TRUE_MIN DBL_TRUE_MIN -#define LDBL_EPSILON DBL_EPSILON -#define LDBL_MANT_DIG DBL_MANT_DIG -#define LDBL_MIN_EXP DBL_MIN_EXP -#define LDBL_MIN_10_EXP DBL_MIN_10_EXP -#define LDBL_MAX_EXP DBL_MAX_EXP -#define LDBL_MAX_10_EXP DBL_MAX_10_EXP -#define LDBL_HAS_SUBNORM DBL_HAS_SUBNORM diff --git a/include/inttypes.h b/include/inttypes.h deleted file mode 100644 index 63fbd0f..0000000 --- a/include/inttypes.h +++ /dev/null @@ -1,275 +0,0 @@ - -#pragma once - -#include - -#define PRIi8 "hhi" -#define PRIu8 "hhu" -#define PRIo8 "hho" -#define PRId8 "hhd" -#define PRIx8 "hhx" -#define PRIX8 "hhX" - -#define PRIi16 "hi" -#define PRIu16 "hu" -#define PRIo16 "ho" -#define PRId16 "hd" -#define PRIx16 "hx" -#define PRIX16 "hX" - -#define PRIi32 "i" -#define PRIu32 "u" -#define PRIo32 "o" -#define PRId32 "d" -#define PRIx32 "x" -#define PRIX32 "X" - -#if defined(_WIN64) - #define PRIi64 "lli" - #define PRIu64 "llu" - #define PRIo64 "llo" - #define PRId64 "lld" - #define PRIx64 "llx" - #define PRIX64 "llX" -#else - #define PRIi64 "li" - #define PRIu64 "lu" - #define PRIo64 "lo" - #define PRId64 "ld" - #define PRIx64 "lx" - #define PRIX64 "lX" -#endif - -#define PRIdLEAST8 "hhi" -#define PRIuLEAST8 "hhu" -#define PRIoLEAST8 "hho" -#define PRIiLEAST8 "hhd" -#define PRIxLEAST8 "hhx" -#define PRIXLEAST8 "hhX" - -#define PRIiLEAST16 "hi" -#define PRIuLEAST16 "hu" -#define PRIoLEAST16 "ho" -#define PRIdLEAST16 "hd" -#define PRIxLEAST16 "hx" -#define PRIXLEAST16 "hX" - -#define PRIiLEAST32 "i" -#define PRIuLEAST32 "u" -#define PRIoLEAST32 "o" -#define PRIdLEAST32 "d" -#define PRIxLEAST32 "x" -#define PRIXLEAST32 "X" - -#if defined(_WIN32) - #define PRIiLEAST64 "lli" - #define PRIuLEAST64 "llu" - #define PRIoLEAST64 "llo" - #define PRIdLEAST64 "lld" - #define PRIxLEAST64 "llx" - #define PRIXLEAST64 "llX" -#else - #define PRIiLEAST64 "li" - #define PRIuLEAST64 "lu" - #define PRIoLEAST64 "lo" - #define PRIdLEAST64 "ld" - #define PRIxLEAST64 "lx" - #define PRIXLEAST64 "lX" -#endif - -#define PRIiFAST8 "i" -#define PRIuFAST8 "u" -#define PRIoFAST8 "o" -#define PRIdFAST8 "d" -#define PRIxFAST8 "x" -#define PRIXFAST8 "X" - -#define PRIiFAST16 "i" -#define PRIuFAST16 "u" -#define PRIoFAST16 "o" -#define PRIdFAST16 "d" -#define PRIxFAST16 "x" -#define PRIXFAST16 "X" - -#define PRIiFAST32 "i" -#define PRIuFAST32 "u" -#define PRIoFAST32 "o" -#define PRIdFAST32 "d" -#define PRIxFAST32 "x" -#define PRIXFAST32 "X" - -#if defined(_WIN32) - #define PRIiFAST64 "lli" - #define PRIuFAST64 "llu" - #define PRIoFAST64 "llo" - #define PRIdFAST64 "lld" - #define PRIxFAST64 "llx" - #define PRIXFAST64 "llX" - #define PRIiPTR "lli" - #define PRIuPTR "llu" - #define PRIoPTR "llo" - #define PRIdPTR "lld" - #define PRIxPTR "llx" - #define PRIXPTR "llX" - #define PRIiMAX "lli" - #define PRIuMAX "llu" - #define PRIoMAX "llo" - #define PRIdMAX "lld" - #define PRIxMAX "llx" - #define PRIXMAX "llX" -#else - #define PRIiFAST64 "li" - #define PRIuFAST64 "lu" - #define PRIoFAST64 "lo" - #define PRIdFAST64 "ld" - #define PRIxFAST64 "lx" - #define PRIXFAST64 "lX" - #define PRIiPTR "li" - #define PRIuPTR "lu" - #define PRIoPTR "lo" - #define PRIdPTR "ld" - #define PRIxPTR "lx" - #define PRIXPTR "lX" - #define PRIiMAX "li" - #define PRIuMAX "lu" - #define PRIoMAX "lo" - #define PRIdMAX "ld" - #define PRIxMAX "lx" - #define PRIXMAX "lX" -#endif - -#define SCNi8 "hhi" -#define SCNu8 "hhu" -#define SCNo8 "hho" -#define SCNd8 "hhd" -#define SCNx8 "hhx" - -#define SCNiLEAST8 "hhi" -#define SCNuLEAST8 "hhu" -#define SCNoLEAST8 "hho" -#define SCNdLEAST8 "hhd" -#define SCNxLEAST8 "hhx" - -#define SCNdFAST8 "hhd" -#define SCNiFAST8 "hhi" -#define SCNoFAST8 "hho" -#define SCNuFAST8 "hhu" -#define SCNxFAST8 "hhx" - -#define SCNi16 "hi" -#define SCNu16 "hu" -#define SCNo16 "ho" -#define SCNd16 "hd" -#define SCNx16 "hx" - -#define SCNiLEAST16 "hi" -#define SCNuLEAST16 "hu" -#define SCNoLEAST16 "ho" -#define SCNdLEAST16 "hd" -#define SCNxLEAST16 "hx" - -#define SCNiFAST16 "i" -#define SCNuFAST16 "u" -#define SCNoFAST16 "o" -#define SCNdFAST16 "d" -#define SCNxFAST16 "x" - -#define SCNi32 "i" -#define SCNu32 "u" -#define SCNo32 "o" -#define SCNd32 "d" -#define SCNx32 "x" - -#define SCNiFAST32 "i" -#define SCNuFAST32 "u" -#define SCNoFAST32 "o" -#define SCNdFAST32 "d" -#define SCNxFAST32 "x" - -#define SCNiLEAST32 "i" -#define SCNuLEAST32 "u" -#define SCNoLEAST32 "o" -#define SCNdLEAST32 "d" -#define SCNxLEAST32 "x" - -#if defined(_WIN32) - #define SCNi64 "lli" - #define SCNu64 "llu" - #define SCNo64 "llo" - #define SCNd64 "lld" - #define SCNx64 "llx" - - #define SCNiLEAST64 "lli" - #define SCNuLEAST64 "llu" - #define SCNoLEAST64 "llo" - #define SCNdLEAST64 "lld" - #define SCNxLEAST64 "llx" - - #define SCNiFAST64 "lli" - #define SCNuFAST64 "llu" - #define SCNoFAST64 "llo" - #define SCNdFAST64 "lld" - #define SCNxFAST64 "llx" - - #define SCNiMAX "lli" - #define SCNuMAX "llu" - #define SCNoMAX "llo" - #define SCNdMAX "lld" - #define SCNxMAX "llx" - - #define SCNiPTR "lli" - #define SCNuPTR "llu" - #define SCNoPTR "llo" - #define SCNdPTR "lld" - #define SCNxPTR "llx" -#else - #define SCNi64 "li" - #define SCNu64 "lu" - #define SCNo64 "lo" - #define SCNd64 "ld" - #define SCNx64 "lx" - - #define SCNiLEAST64 "li" - #define SCNuLEAST64 "lu" - #define SCNoLEAST64 "lo" - #define SCNdLEAST64 "ld" - #define SCNxLEAST64 "lx" - - #define SCNiFAST64 "li" - #define SCNuFAST64 "lu" - #define SCNoFAST64 "lo" - #define SCNdFAST64 "ld" - #define SCNxFAST64 "lx" - - #define SCNiMAX "li" - #define SCNuMAX "lu" - #define SCNoMAX "lo" - #define SCNdMAX "ld" - #define SCNxMAX "lx" - - #define SCNiPTR "li" - #define SCNuPTR "lu" - #define SCNoPTR "lo" - #define SCNdPTR "ld" - #define SCNxPTR "lx" -#endif - -#if defined(_WIN32) - typedef unsigned short wchar_t; -#else - typedef int wchar_t; -#endif - -typedef struct imaxdiv_t imaxdiv_t; -struct imaxdiv_t { - intmax_t quot; - intmax_t rem; -}; - -intmax_t imaxabs(intmax_t j); -imaxdiv_t imaxdiv(intmax_t numer, intmax_t denom); -intmax_t strtoimax(const char *restrict s, char **restrict end, int base); -uintmax_t strtoumax(const char *restrict s, char ** restrict end, int base); -intmax_t wcstoimax(const wchar_t *restrict s, wchar_t **restrict end, int base); -uintmax_t wcstoumax(const wchar_t *restrict s, wchar_t **restrict end, int base); - diff --git a/include/iso646.h b/include/iso646.h deleted file mode 100644 index db811b9..0000000 --- a/include/iso646.h +++ /dev/null @@ -1,14 +0,0 @@ - -#pragma once - -#define and && -#define and_eq &= -#define bitand & -#define bitor | -#define compl ~ -#define not ! -#define not_eq != -#define or || -#define or_eq |= -#define xor ^ -#define xor_eq ^= \ No newline at end of file diff --git a/include/limits.h b/include/limits.h deleted file mode 100644 index fbf9271..0000000 --- a/include/limits.h +++ /dev/null @@ -1,87 +0,0 @@ - -#pragma once - -#define MB_LEN_MAX 5 - -#define CHAR_BIT 8 -#define BOOL_WIDTH 8 - -#define UCHAR_WIDTH 8 -#define SCHAR_WIDTH 8 -#define UCHAR_MAX 0xff -#define SCHAR_MIN -0x80 -#define SCHAR_MAX +0x7f - -#if defined(__CHAR_UNSIGNED__) || defined(_CHAR_UNSIGNED) - #define CHAR_MIN UCHAR_MIN - #define CHAR_MAX UCHAR_MAX -#else - #define CHAR_MIN SCHAR_MIN - #define CHAR_MAX SCHAR_MAX -#endif - -#define USHRT_WIDTH 16 -#define SHRT_WIDTH 16 -#define USHRT_MAX 0xffff -#define SHRT_MIN -0x8000 -#define SHRT_MAX +0x7fff - -#define UINT_WIDTH 32 -#define INT_WIDTH 32 -#define UINT_MAX 0xffffffffu -#define INT_MIN -0x80000000 -#define INT_MAX +0x7fffffff - -#if defined(_WIN64) - #define ULONG_WIDTH 32 - #define LONG_WIDTH 32 - #define ULONG_MAX +0xffffffff - #define LONG_MIN -0x80000000 - #define LONG_MAX +0x7fffffff -#else - #define ULONG_WIDTH 64 - #define LONG_WIDTH 64 - #define ULONG_MAX 0xffffffffffffffffull - #define LONG_MIN -0x8000000000000000ll - #define LONG_MAX +0x7fffffffffffffffll -#endif - -#define ULLONG_WIDTH 64 -#define LLONG_WIDTH 64 -#define ULLONG_MAX 0xffffffffffffffffull -#define LLONG_MIN -0x8000000000000000ll -#define LLONG_MAX +0x7fffffffffffffffll - -#define PTRDIFF_WIDTH LLONG_WIDTH -#define PTRDIFF_MIN LLONG_MIN -#define PTRDIFF_MAX LLONG_MAX - -#define SIZE_WIDTH ULLONG_WIDTH -#define SIZE_MAX ULLONG_MAX - -#define SIG_ATOMIC_WIDTH LLONG_WIDTH -#define SIG_ATOMIC_MIN LLONG_MIN -#define SIG_ATOMIC_MAX LLONG_MAX - -#define WINT_WIDTH INT_WIDTH -#define WINT_MIN INT_MIN -#define WINT_MAX INT_MAX - -#define CHAR_WIDTH 8 -#define WCHAR_WIDTH USHORT_WIDTH - -#if !defined(WCHAR_MIN) - #if defined(_WIN32) - #define WCHAR_MIN 0 - #else - #define WCHAR_MIN INT_MIN - #endif -#endif - -#if !defined(WCHAR_MAX) - #if defined(_WIN32) - #define WCHAR_MAX USHORT_MAX - #else - #define WCHAR_MAX INT_MAX - #endif -#endif diff --git a/include/locale.h b/include/locale.h deleted file mode 100644 index 8241c0e..0000000 --- a/include/locale.h +++ /dev/null @@ -1,45 +0,0 @@ - -#pragma once - -#define _COL_IGNORE_SPACE 0x1 -#define _COL_IGNORE_SYMBOL 0x2 - -// Locale categories -#define LC_ALL 0 -#define LC_COLLATE 1 -#define LC_CTYPE 2 -#define LC_MONETARY 3 -#define LC_NUMERIC 4 -#define LC_TIME 5 - -struct lconv { - // LC_NUMERIC - char *decimal_point; // "." - char *thousands_sep; // "" - char *grouping; // "" - // LC_MONETARY - char *mon_decimal_point; // "" - char *mon_thousands_sep; // "" - char *mon_grouping; // "" - char *positive_sign; // "" - char *negative_sign; // "" - char *currency_symbol; // "" - char frac_digits; // CHAR_MAX - char p_cs_precedes; // CHAR_MAX - char n_cs_precedes; // CHAR_MAX - char p_sep_by_space; // CHAR_MAX - char n_sep_by_space; // CHAR_MAX - char p_sign_posn; // CHAR_MAX - char n_sign_posn; // CHAR_MAX - char *int_curr_symbol; // "" - char int_frac_digits; // CHAR_MAX - char int_p_cs_precedes; // CHAR_MAX - char int_n_cs_precedes; // CHAR_MAX - char int_p_sep_by_space; // CHAR_MAX - char int_n_sep_by_space; // CHAR_MAX - char int_p_sign_posn; // CHAR_MAX - char int_n_sign_posn; // CHAR_MAX -}; - -char *setlocale(int category, const char *locale); -struct lconv *localeconv(void); diff --git a/include/math.h b/include/math.h deleted file mode 100644 index a8dbb86..0000000 --- a/include/math.h +++ /dev/null @@ -1,301 +0,0 @@ - -#pragma once - -typedef float float_t; -typedef double double_t; - -#ifndef _HUGE_ENUF -#define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow -#endif - -#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) -#define HUGE_VAL ((double)INFINITY) -#define HUGE_VALF ((float)INFINITY) - -#define NAN (-(float)(INFINITY * 0.0F)) - -#define FP_ILOGBNAN (-1-0x7fffffff) -#define FP_ILOGB0 FP_ILOGBNAN - -#define MATH_ERRNO 1 -#define MATH_ERREXCEPT 2 - -#define math_errhandling (MATH_ERRNO | MATH_ERREXCEPT) - -// Classification -#define FP_ZERO 0 -#define FP_SUBNORMAL 1 -#define FP_NORMAL 2 -#define FP_INFINITE 4 -#define FP_NAN 5 -int _fpclassify(double); -int _fpclassifyf(float); -int _fpclassifyl(long double); -#define fpclassify(x) (sizeof(x)==4?_fpclassifyf(x) \ - :sizeof(x)==8?_fpclassify(x) \ - : _fpclassifyl(x) ) -#define isfinite(x) (fpclassify(x) != FP_INFINITE && fpclassify(x) != FP_NAN) -#define isinf(x) (fpclassify(x) == FP_INFINITE) -#define isnan(x) (fpclassify(x) == FP_NAN) -#define isnormal(x) (fpclassify(x) == FP_NORMAL) - -// signbit shit -int _signbit(double); -int _signbitf(float); -int _signbitl(long double); -#define signbit(x) (sizeof(x) == sizeof(float) ? _signbitf(x) \ - :sizeof(x) == sizeof(double) ? _signbit(x) \ - : _signbitl(x) ) - -// Ordering -#define isunordered(x,y) (isnan((x)) ? ((void)(y),1) : isnan((y))) -#define isgreater(x,y) (!isunordered(x,y) && ((x) > (y))) -#define isgreaterequal(x,y) (!isunordered(x,y) && ((x) >= (y))) -#define isless(x,y) (!isunordered(x,y) && ((x) < (y))) -#define islessequal(x,y) (!isunordered(x,y) && ((x) <= (y))) -#define islessgreater(x,y) (!isunordered(x,y) && ((x) != (y))) - -#if defined(_USE_MATH_DEFINES) - #define M_E 2.7182818284590452354 - #define M_LOG2E 1.4426950408889634074 - #define M_LOG10E 0.43429448190325182765 - #define M_LN2 0.69314718055994530942 - #define M_LN10 2.30258509299404568402 - #define M_PI 3.14159265358979323846 - #define M_PI_2 1.57079632679489661923 - #define M_PI_4 0.78539816339744830962 - #define M_1_PI 0.31830988618379067154 - #define M_2_PI 0.63661977236758134308 - #define M_2_SQRTPI 1.12837916709551257390 - #define M_SQRT2 1.41421356237309504880 - #define M_SQRT1_2 0.70710678118654752440 -#endif - -// Floating-point function prototypes -double acos (double); -float acosf (float); -long double acosl (long double); - -double acosh (double); -float acoshf (float); -long double acoshl (long double); - -double asin (double); -float asinf (float); -long double asinl (long double); - -double asinh (double); -float asinhf (float); -long double asinhl (long double); - -double atan (double); -float atanf (float); -long double atanl (long double); - -double atan2 (double, double); -float atan2f (float, float); -long double atan2l (long double, long double); - -double atanh (double); -float atanhf (float); -long double atanhl (long double); - -double cbrt (double); -float cbrtf (float); -long double cbrtl (long double); - -double ceil (double); -float ceilf (float); -long double ceill (long double); - -double copysign (double, double); -float copysignf (float, float); -long double copysignl (long double, long double); - -double cos (double); -float cosf (float); -long double cosl (long double); - -double cosh (double); -float coshf (float); -long double coshl (long double); - -double erf (double); -float erff (float); -long double erfl (long double); - -double erfc (double); -float erfcf (float); -long double erfcl (long double); - -double exp (double); -float expf (float); -long double expl (long double); - -double exp2 (double); -float exp2f (float); -long double exp2l (long double); - -double expm1 (double); -float expm1f (float); -long double expm1l (long double); - -double fabs (double); -float fabsf (float); -long double fabsl (long double); - -double fdim (double, double); -float fdimf (float, float); -long double fdiml (long double, long double); - -double floor (double); -float floorf (float); -long double floorl (long double); - -double fma (double, double, double); -float fmaf (float, float, float); -long double fmal (long double, long double, long double); - -double fmax (double, double); -float fmaxf (float, float); -long double fmaxl (long double, long double); - -double fmin (double, double); -float fminf (float, float); -long double fminl (long double, long double); - -double fmod (double, double); -float fmodf (float, float); -long double fmodl (long double, long double); - -double frexp (double, int *); -float frexpf (float, int *); -long double frexpl (long double, int *); - -double hypot (double, double); -float hypotf (float, float); -long double hypotl (long double, long double); - -int ilogb (double); -int ilogbf (float); -int ilogbl (long double); - -double ldexp (double, int); -float ldexpf (float, int); -long double ldexpl (long double, int); - -double lgamma (double); -float lgammaf (float); -long double lgammal (long double); - -long long llrint (double); -long long llrintf (float); -long long llrintl (long double); - -long long llround (double); -long long llroundf (float); -long long llroundl (long double); - -double log (double); -float logf (float); -long double logl (long double); - -double log10 (double); -float log10f (float); -long double log10l (long double); - -double log1p (double); -float log1pf (float); -long double log1pl (long double); - -double log2 (double); -float log2f (float); -long double log2l (long double); - -double logb (double); -float logbf (float); -long double logbl (long double); - -long lrint (double); -long lrintf (float); -long lrintl (long double); - -long lround (double); -long lroundf (float); -long lroundl (long double); - -double modf (double, double *); -float modff (float, float *); -long double modfl (long double, long double *); - -double nan (const char *); -float nanf (const char *); -long double nanl (const char *); - -double nearbyint (double); -float nearbyintf (float); -long double nearbyintl (long double); - -double nextafter (double, double); -float nextafterf (float, float); -long double nextafterl (long double, long double); - -double nexttoward (double, long double); -float nexttowardf(float, long double); -long double nexttowardl(long double, long double); - -double pow (double, double); -float powf (float, float); -long double powl (long double, long double); - -double remainder (double, double); -float remainderf (float, float); -long double remainderl (long double, long double); - -double remquo (double, double, int *); -float remquof (float, float, int *); -long double remquol (long double, long double, int *); - -double rint (double); -float rintf (float); -long double rintl (long double); - -double round (double); -float roundf (float); -long double roundl (long double); - -double scalbln (double, long); -float scalblnf (float, long); -long double scalblnl (long double, long); - -double scalbn (double, int); -float scalbnf (float, int); -long double scalbnl (long double, int); - -double sin (double); -float sinf (float); -long double sinl (long double); - -double sinh (double); -float sinhf (float); -long double sinhl (long double); - -double sqrt (double); -float sqrtf (float); -long double sqrtl (long double); - -double tan (double); -float tanf (float); -long double tanl (long double); - -double tanh (double); -float tanhf (float); -long double tanhl (long double); - -double tgamma (double); -float tgammaf (float); -long double tgammal (long double); - -double trunc (double); -float truncf (float); -long double truncl (long double); diff --git a/include/os_win/threads_types.h b/include/os_win/threads_types.h deleted file mode 100644 index 4ef470f..0000000 --- a/include/os_win/threads_types.h +++ /dev/null @@ -1,38 +0,0 @@ - -// Note(bumbread): this file is included into threads.h when compiled under -// windows. Here we avoid including windows.h directly because it may be -// undesireable to include a bunch of non-standard names and types into user's -// files just to get a few of them. - -#pragma once - -#define ONCE_FLAG_INIT ((once_flag){0}) - -typedef struct thrd_t { - void *handle; -} thrd_t; - -typedef struct tss_t { - unsigned tls_index; -} tss_t; - -// We pretend that once_flag defined the same way as INIT_ONCE -// from winapi headers (aka _RTL_RUN_ONCE), which itself is defined -// as a union -typedef union once_flag { - void *ptr; -} once_flag; - -// This mirrors CONDITION_VARIABLE type (aka _RTL_CONDITION_VARIABLE) -typedef struct cnd_t { - void *ptr; -} cnd_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; diff --git a/include/signal.h b/include/signal.h deleted file mode 100644 index ed4f5fb..0000000 --- a/include/signal.h +++ /dev/null @@ -1,26 +0,0 @@ - -#pragma once - -typedef int sig_atomic_t; - -// TODO: idk about SIG_ERR, for now this -#define SIG_ERR ((void(*)(int))0) -#define SIG_DFL _signal_default_handler -#define SIG_IGN _signal_ignore_handler - -// Note(bumbread): from the impl standpoint the numbers are arbitrary -#define _SIG_MIN 0 -#define SIGINT 1 -#define SIGILL 2 -#define SIGFPE 3 -#define SIGSEGV 4 -#define SIGTERM 5 -#define SIGABRT 6 -// These guys are impl defined -#define SIGBREAK 7 -#define SIGALIGN 8 -#define SIGSTEP 9 -#define _SIG_MAX 9 - -void (*signal(int sig, void (*func)(int)))(int); -int raise(int sig); diff --git a/include/std.h b/include/std.h deleted file mode 100644 index 79a8dcc..0000000 --- a/include/std.h +++ /dev/null @@ -1,31 +0,0 @@ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -// #include -#include -#include -#include -#include -#include diff --git a/include/stdalign.h b/include/stdalign.h deleted file mode 100644 index 5c4013d..0000000 --- a/include/stdalign.h +++ /dev/null @@ -1,8 +0,0 @@ - -#pragma once - -#define __alignas_is_defined 1 -#define __alignof_is_defined 1 - -#define alignas _Alignas -#define alignof _Alignof diff --git a/include/stdbool.h b/include/stdbool.h deleted file mode 100644 index 1cbb9a1..0000000 --- a/include/stdbool.h +++ /dev/null @@ -1,8 +0,0 @@ - -#pragma once - -#define __bool_true_false_are_defined 1 - -#define bool _Bool -#define true 1 -#define false 0 diff --git a/include/stddef.h b/include/stddef.h deleted file mode 100644 index f562749..0000000 --- a/include/stddef.h +++ /dev/null @@ -1,24 +0,0 @@ - -#pragma once - -#if !defined(NULL) - #define NULL ((void *)0) -#endif - -#define offsetof(st, m) ((size_t)((char *)&((st *)0)->m - (char *)0)) - -#if defined(_WIN32) - typedef long long ptrdiff_t; - typedef unsigned long long size_t; - typedef unsigned long long max_align_t; - typedef unsigned short wchar_t; -#else - typedef long ptrdiff_t; - typedef unsigned long size_t; - typedef unsigned long max_align_t; - typedef int wchar_t; -#endif - -#if __STDC_WANT_LIB_EXT1__ == 1 - typedef size_t rsize_t; -#endif diff --git a/include/stdint.h b/include/stdint.h deleted file mode 100644 index a1af872..0000000 --- a/include/stdint.h +++ /dev/null @@ -1,153 +0,0 @@ - -#pragma once - -typedef signed char int8_t; -typedef short int16_t; -typedef int int32_t; -typedef long long int64_t; -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; - -#if defined(_WIN64) - typedef unsigned long long uint64_t; -#else - typedef unsigned long uint64_t; -#endif - -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -typedef int32_t int_fast8_t; -typedef int32_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint32_t uint_fast8_t; -typedef uint32_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -typedef int64_t intptr_t; -typedef uint64_t uintptr_t; - -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - -#define INT8_WIDTH 8 -#define INT16_WIDTH 16 -#define INT32_WIDTH 32 -#define INT64_WIDTH 64 - -#define UINT8_WIDTH 8 -#define UINT16_WIDTH 16 -#define UINT32_WIDTH 32 -#define UINT64_WIDTH 64 - -#define INT8_MIN -0x80 -#define INT16_MIN -0x8000 -#define INT32_MIN -0x80000000 -#define INT64_MIN -0x8000000000000000ll - -#define INT8_MAX +0x7f -#define INT16_MAX +0x7fff -#define INT32_MAX +0x7fffffff -#define INT64_MAX +0x7fffffffffffffff - -#define UINT8_MAX +0xff -#define UINT16_MAX +0xffff -#define UINT32_MAX +0xffffffffu -#define UINT64_MAX +0xffffffffffffffffull - -#define INT_LEAST8_WIDTH INT8_WIDTH -#define INT_LEAST16_WIDTH INT16_WIDTH -#define INT_LEAST32_WIDTH INT32_WIDTH -#define INT_LEAST64_WIDTH INT64_WIDTH - -#define UINT_LEAST8_WIDTH INT8_WIDTH -#define UINT_LEAST16_WIDTH INT16_WIDTH -#define UINT_LEAST32_WIDTH INT32_WIDTH -#define UINT_LEAST64_WIDTH INT64_WIDTH - -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST64_MIN INT64_MIN - -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MAX INT64_MAX - -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -#define INT_FAST8_WIDTH INT32_WIDTH -#define INT_FAST16_WIDTH INT32_WIDTH -#define INT_FAST32_WIDTH INT32_WIDTH -#define INT_FAST64_WIDTH INT64_WIDTH - -#define UINT_FAST8_WIDTH INT32_WIDTH -#define UINT_FAST16_WIDTH INT32_WIDTH -#define UINT_FAST32_WIDTH INT32_WIDTH -#define UINT_FAST64_WIDTH INT64_WIDTH - -#define INT_FAST8_MIN INT32_MIN -#define INT_FAST16_MIN INT32_MIN -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST64_MIN INT64_MIN - -#define INT_FAST8_MAX INT32_MAX -#define INT_FAST16_MAX INT32_MAX -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MAX INT64_MAX - -#define UINT_FAST8_MAX UINT32_MAX -#define UINT_FAST16_MAX UINT32_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -#define INTPTR_WIDTH INT64_WIDTH -#define UINTPTR_WIDTH UINT64_WIDTH -#define INTPTR_MIN INT64_MIN -#define INTPTR_MAX INT64_MAX -#define UINTPTR_MAX UINT64_MAX - -#define INTMAX_WIDTH INT64_WIDTH -#define UINTMAX_WIDTH UINT64_WIDTH -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -#define INT8_C(lit) lit -#define INT16_C(lit) lit -#define INT32_C(lit) lit - -#if defined(_WIN32) - #define INT64_C(lit) lit ## ll -#else - #define INT64_C(lit) lit # l -#endif - -#define UINT8_C(lit) lit -#define UINT16_C(lit) lit -#define UINT32_C(lit) lit - -#if defined(_WIN32) - #define UINT64_C(lit) lit ## ull -#endif - -#if __STDC_WANT_LIB_EXT1__ == 1 - #if defined(_WIN32) - #define RSIZE_MAX 0xffffffffffffull; - #else - #define RSIZE_MAX 0xfffffffffffful; - #endif -#endif diff --git a/include/stdio.h b/include/stdio.h deleted file mode 100644 index 2ba8d3e..0000000 --- a/include/stdio.h +++ /dev/null @@ -1,137 +0,0 @@ - -#pragma once - -#include - -// 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 - -typedef struct FILE FILE; - -typedef struct { - unsigned long long offset; - 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 - -#define _IONBF 0 -#define _IOFBF 1 -#define _IOLBF 2 -#define BUFSIZ 512 -#define EOF (-1) -#define FOPEN_MAX 32 - -#ifdef _os_win - #define FILENAME_MAX 260 -#else - #define FILENAME_MAX 4096 -#endif - -#define _PRINTF_NAN_LEN_MAX 20 - -#define L_tmpnam FILENAME_MAX - -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 - -#ifdef _os_win - #define TMP_MAX SHORT_MAX -#else - #define TMP_MAX INT_MAX -#endif - -#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); - -// 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); - -// I/O buffering control -void setbuf (FILE *restrict stream, char *restrict buf); -int setvbuf (FILE *restrict stream, char *restrict buf, int mode, size_t size); -int fflush (FILE *stream); - -// String formatted print -int vsnprintf(char *restrict s, size_t n, const char *restrict format, va_list arg); -int vsprintf (char *restrict s, const char *restrict format, va_list arg); -int snprintf (char *restrict s, size_t n, const char *restrict format, ...); -int sprintf (char *restrict s, const char *restrict format, ...); - -// File formatted print -int vfprintf (FILE *restrict stream, const char *restrict format, va_list arg); -int fprintf (FILE *restrict stream, const char *restrict format, ...); -int vprintf (const char *restrict format, va_list arg); -int printf (const char *restrict format, ...); - -// String formatted scan -int vsscanf(const char *restrict s, const char *restrict format, va_list arg); -int vscanf (const char *restrict format, va_list arg); -int sscanf (const char *restrict s, const char *restrict format, ...); - -// String formatted scan -int vfscanf(FILE *restrict stream, const char *restrict format, va_list arg); -int fscanf (FILE *restrict stream, const char *restrict format, ...); -int scanf (const char *restrict format, ...); - -// File reading -#define getc fgetc -int fgetc (FILE *stream); -int getchar(void); -int ungetc (int c, FILE *stream); -char *fgets (char *restrict s, int n, FILE *restrict stream); -size_t fread (void *restrict ptr, size_t size, size_t nmemb, FILE *restrict stream); - -// File writing -#define putc fputc -int fputc (int c, FILE *stream); -int putchar(int c); -int fputs (const char *restrict s, FILE *restrict stream); -int puts (const char *s); -size_t fwrite (const void *restrict ptr, size_t size, size_t nmemb, FILE *restrict stream); - -int fgetpos (FILE *restrict stream, fpos_t *restrict pos); -int fseek (FILE *stream, long int offset, int whence); -int fsetpos (FILE *stream, const fpos_t *pos); -long int ftell (FILE *stream); -void rewind (FILE *stream); - -void clearerr(FILE *stream); -int feof (FILE *stream); -int ferror (FILE *stream); -void perror (const char *s); - -#if __STDC_WANT_LIB_EXT1__ == 1 - #define L_tmpnam_s L_tmpnam - #define TMP_MAX_S TMP_MAX - - errno_t tmpfile_s(FILE *restrict *restrict streamptr); - errno_t tmpnam_s (char *s, rsize_t maxsize); -#endif diff --git a/include/stdlib.h b/include/stdlib.h deleted file mode 100644 index 94456ce..0000000 --- a/include/stdlib.h +++ /dev/null @@ -1,132 +0,0 @@ -#pragma once - -#if defined(_MSC_VER) && !defined(__clang__) - #define _Noreturn __declspec(noreturn) -#endif - -#if !defined(__STDC_LIB_EXT1__) - #define __STDC_LIB_EXT1__ -#endif - -#ifdef __STDC_WANT_SECURE_LIB__ - #if !defined(__STDC_WANT_LIB_EXT1__) - #define __STDC_WANT_LIB_EXT1__ 1 - #endif -#endif - -#if !defined(NULL) - #define NULL ((void *)0) -#endif - -#define EXIT_SUCCESS 0 -#define EXIT_FAILURE 1 - -#if defined(_WIN32) - typedef unsigned long long size_t; - typedef unsigned short wchar_t; -#else - typedef unsigned long size_t; - typedef int wchar_t; -#endif - -typedef struct div_t { - int quot; - int rem; -} div_t; - -typedef struct ldiv_t { - long quot; - long rem; -} ldiv_t; - -typedef struct lldiv_t { - long long quot; - long long rem; -} lldiv_t; - -#define EXIT_FAILURE 1 -#define EXIT_SUCCESS 0 - -#define RAND_MAX 65536 - -#define MB_CUR_MAX 5 - -// Microsoft extension, COUNTOF(x) counts array elements -#ifndef COUNTOF -#define COUNTOF(...) (sizeof(__VA_ARGS__) / sizeof((__VA_ARGS__)[0])) -#endif - -// Some number stuff -int abs (int i); -long labs (long i); -long long llabs(long long i); -div_t div (int numer, int denom); -ldiv_t ldiv (long numer, long denom); -lldiv_t lldiv(long long numer, long long denom); - -// String conversion routines -double atof (const char *nptr); -int atoi (const char *nptr); -long atol (const char *nptr); -long long atoll (const char *nptr); -double strtod (const char *restrict nptr, char **restrict endptr); -float strtof (const char *restrict nptr, char **restrict endptr); -long double strtold (const char *restrict nptr, char **restrict endptr); -long strtol (const char *restrict nptr, char **restrict endptr, int base); -long long strtoll (const char *restrict nptr, char **restrict endptr, int base); -unsigned long strtoul (const char *restrict nptr, char **restrict endptr, int base); -unsigned long long strtoull(const char *restrict nptr, char **restrict endptr, int base); - -char *itoa(int value, char *str, int base); - -// PRNG -int rand (void); -void srand(unsigned int seed); - -// Memory management functions -void *malloc (size_t size); -void *calloc (size_t nmemb, size_t size); -void *aligned_alloc(size_t align, size_t size); -void *realloc (void *ptr, size_t size); -void free (void *ptr); - -// Communication with environment -_Noreturn void abort (void); -_Noreturn void quick_exit (int status); -_Noreturn void _Exit (int status); -_Noreturn void exit (int status); -int atexit (void (*func)(void)); -int at_quick_exit(void (*func)(void)); -char *getenv (const char *name); -int system (const char *string); - -const void *bsearch( - const void *key, - const void *base, - size_t nmemb, - size_t size, - int (*compar)(const void *, const void *) -); - -void qsort( - void *base, - size_t nmemb, - size_t size, - int (*compar)(const void *, const void *) -); - -// Multibyte strings -int mblen (const char *s, size_t n); -int mbtowc (wchar_t *restrict pwc, const char *restrict s, size_t n); -size_t mbstowcs(wchar_t *restrict pwcs, const char *restrict s, size_t n); -int wctomb (char *s, wchar_t wchar); -size_t wcstombs(char *restrict s, const wchar_t *restrict pwcs, size_t n); - -// #ifdef __STDC_WANT_LIB_EXT1__ -// typedef void (*constraint_handler_t)(const char * restrict msg, void * restrict ptr, errno_t error); - -// constraint_handler_t set_constraint_handler_s(constraint_handler_t handler); -// void abort_handler_s(const char * restrict msg, void * restrict ptr, errno_t error); -// void ignore_handler_s(const char * restrict msg, void * restrict ptr, errno_t error); -// errno_t getenv_s(size_t * restrict len, char * restrict value, rsize_t maxsize, const char * restrict name); -// #endif diff --git a/include/stdnoreturn.h b/include/stdnoreturn.h deleted file mode 100644 index 2dba6c1..0000000 --- a/include/stdnoreturn.h +++ /dev/null @@ -1,6 +0,0 @@ - -#pragma once - -#if !defined(noreturn) - #define noreturn _Noreturn -#endif diff --git a/include/string.h b/include/string.h deleted file mode 100644 index 92d1393..0000000 --- a/include/string.h +++ /dev/null @@ -1,91 +0,0 @@ - -#pragma once - -#if !defined(NULL) - #define NULL ((void *)0) -#endif - -#if defined(_WIN32) - typedef unsigned long long size_t; -#else - typedef unsigned long size_t; -#endif - -#if !defined(__STDC_LIB_EXT1__) - #define __STDC_LIB_EXT1__ - typedef int errno_t; - typedef size_t rsize_t; -#endif - -#if __STDC_WANT_SECURE_LIB__ == 1 - #if !defined(__STDC_WANT_LIB_EXT1__) - #define __STDC_WANT_LIB_EXT1__ 1 - #endif -#endif - -#if !defined(__STDC_ALLOC_LIB__) - #define __STDC_ALLOC_LIB__ -#endif - -size_t strlen(const char *s); -char *strerror(int errnum); - -// Copying -void *memset (void *s, int c, size_t n); -void *memmove (void *s1, const void *s2, size_t n); -void *memcpy (void *restrict s1, const void *restrict s2, size_t n); -char *strncpy (char *restrict s1, const char *restrict s2, size_t n); -char *strcpy (char *restrict s1, const char *restrict s2); - -// Concat -char *strncat (char *restrict s1, const char *restrict s2, size_t n); -char *strcat (char *restrict s1, const char *restrict s2); - -// Comparison -int memcmp (const void *s1, const void *s2, size_t n); -int strncmp (const char *s1, const char *s2, size_t n); -int strcmp (const char *s1, const char *s2); - -// Collation/Localisation thingy -int strcoll (const char *s1, const char *s2); -size_t strxfrm (char *restrict s1, const char *restrict s2, size_t n); - -// Tokenization and related stuff -void *memchr (const void *str, int c, size_t n); -char *strchr (const char *str, int c); -size_t strcspn(const char *str, const char *s); -char *strpbrk(const char *str, const char *s); -char *strrchr(const char *str, int c); -size_t strspn (const char *str, const char *s); -char *strstr (const char *str, const char *s); -char *strtok (char *restrict str, const char *restrict s); - -// Linux extension: reentrant strtok -char *strtok_r(char *restrict s1, const char *restrict s2, char **restrict ctx); - -// Extension 1 -#if __STDC_WANT_LIB_EXT1__ == 1 - - size_t strnlen_s(const char *str, size_t strsz); - - // Safe memory copies - errno_t memset_s (void *s, rsize_t smax, int c, rsize_t n); - errno_t memmove_s(void *s1, rsize_t s1max, const void *s2, rsize_t n); - errno_t memcpy_s (void *restrict s1, rsize_t s1max, const void *restrict s2, rsize_t n); - errno_t strncpy_s(char *restrict s1, rsize_t s1max, const char *restrict s2, rsize_t n); - errno_t strcpy_s (char *restrict s1, rsize_t s1max, const char *restrict s2); - - // Safe concat et strtok - errno_t strcat_s (char *restrict s1, rsize_t s1max, const char *restrict s2); - errno_t strncat_s(char *restrict s1, rsize_t s1max, const char *restrict s2, rsize_t n); - char *strtok_s(char *restrict s1, rsize_t *restrict s1max, const char *restrict s2, char **restrict ptr); - - // Safe error strings - errno_t strerror_s(char *s, rsize_t maxsize, errno_t errnum); - size_t strerrorlen_s(errno_t errnum); -#endif - -// Extension 2 -#if __STDC_WANT_LIB_EXT2__ == 1 - char *strdup(const char *str1); -#endif diff --git a/include/tgmath.h b/include/tgmath.h deleted file mode 100644 index 37dd122..0000000 --- a/include/tgmath.h +++ /dev/null @@ -1,101 +0,0 @@ - -#pragma once - -#include - -#define _tg_is_ld(x) (sizeof(x) == sizeof(long double)) -#define _tg_is_d(x) (sizeof(x) == sizeof(double)) - -#define _tg_is_ld2(x,y) (_tg_is_ld(x) || _tg_is_ld(y)) -#define _tg_is_d2(x,y) (_tg_is_d (x) || _tg_is_d (y)) - -#define _tg_is_ld3(x,y,z) (_tg_is_ld(x) || _tg_is_ld(y) || _tg_is_ld(z)) -#define _tg_is_d3(x,y,z) (_tg_is_d (x) || _tg_is_d (y) || _tg_is_d (z)) - - -#define _tg_func1(func,x) ( _tg_is_ld(x) ? (func ## l)(x) \ - : _tg_is_d(x) ? (func)(x) \ - : (func ## f)(x) ) - - -#define _tg_func1p(func,x,p) ( _tg_is_ld(x) ? (func ## l)(x,p) \ - : _tg_is_d(x) ? (func)(x,p) \ - : (func ## f)(x,p) ) - -#define _tg_func2(func,x,y) ( _tg_is_ld2(x,y) ? (func ## l)(x,y) \ - : _tg_is_d2(x,y) ? (func)(x,y) \ - : (func ## f)(x,y) ) - -#define _tg_func2p(func,x,y,p) ( _tg_is_ld2(x,y) ? (func ## l)(x,y,p) \ - : _tg_is_d2(x,y) ? (func)(x,y,p) \ - : (func ## f)(x,y,p) ) - - -#define _tg_func3(func,x,y,z) ( _tg_is_ld3(x,y,z) ? (func ## l)(x,y,z) \ - : _tg_is_d3(x,y,z) ? (func)(x,y,z) \ - : (func ## f)(x,y,z) ) - -#define cos(x) _tg_func1(cos, x) -#define sin(x) _tg_func1(sin, x) -#define tan(x) _tg_func1(tan, x) -#define acos(x) _tg_func1(acos, x) -#define asin(x) _tg_func1(asin, x) -#define atan(x) _tg_func1(atan, x) -#define atan2(x,y) _tg_func2(atan2, x, y) - -#define cosh(x) _tg_func1(cosh, x) -#define sinh(x) _tg_func1(sinh, x) -#define tanh(x) _tg_func1(tanh, x) -#define acosh(x) _tg_func1(acosh, x) -#define asinh(x) _tg_func1(asinh, x) -#define atanh(x) _tg_func1(atanh, x) - -#define exp(x) _tg_func1(exp, x) -#define exp2(x) _tg_func1(exp2, x) -#define expm1(x) _tg_func1(expm1, x) -#define pow(x,y) _tg_func2(pow, x, y) -#define log(x,y) _tg_func2(log, x, y) -#define sqrt(x) _tg_func1(sqrt, x) -#define cbrt(x) _tg_func1(cbrt, x) -#define hypot(x,y) _tg_func2(hypot, x, y) - -#define log10(x) _tg_func1(log10, x) -#define log1p(x) _tg_func1(log1p, x) -#define log2(x) _tg_func1(log2, x) -#define logb(x) _tg_func1(logb, x) -#define ilogb(x) _tg_func1(ilogb, x) - -#define ceil(x) _tg_func1(ceil, x) -#define floor(x) _tg_func1(floor, x) -#define trunc(x) _tg_func1(trunc, x) -#define llrint(x) _tg_func1(llrint, x) -#define lrint(x) _tg_func1(lrint, x) -#define rint(x) _tg_func1(rint, x) -#define llround(x) _tg_func1(llround, x) -#define lround(x) _tg_func1(lround, x) -#define round(x) _tg_func1(round, x) -#define nearbyint(x) _tg_func1(nearbyint, x) - -#define erf(x) _tg_func1(erf, x) -#define erfc(x) _tg_func1(erfc, x) -#define tgamma(x) _tg_func1(tgamma, x) -#define lgamma(x) _tg_func1(lgamma, x) - -#define fabs(x) _tg_func1(fabs, x) -#define fdim(x,y) _tg_func2(fdim, x, y) -#define fmax(x,y) _tg_func2(fmax, x, y) -#define fmin(x,y) _tg_func2(fmin, x, y) -#define fmod(x,y) _tg_func2(fmod, x, y) -#define remainder(x,y) _tg_func2(remainder, x, y) -#define remquo(x,y,p) _tg_func2p(remquo, x, y, p) -#define fma(x,y,z) _tg_func3(fma, x, y, z) - -#define copysign(x,y) _tg_func2(copysign, x, y) -#define frexp(x,p) _tg_func1p(frexp, x, p) -#define ldexp(x,p) _tg_func1p(ldexp, x, p) -#define modf(x,p) _tg_func1p(modf, x, p) -#define scalbn(x,p) _tg_func1p(scalbn, x, p) -#define scalbln(x,p) _tg_func1p(scalbln, x, p) - -#define nextafter(x,y) _tg_func2(nextafter, x, y) -#define nexttoward(x,y) _tg_func2(nexttoward, x, y) diff --git a/include/threads.h b/include/threads.h deleted file mode 100644 index 800d810..0000000 --- a/include/threads.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -// Note(bumbread): some of the macros and types are platform-dependent -// and can be found in os_win/ subfolder. - -#if defined(_WIN32) - #include "os_win/threads_types.h" -#else - #error "Not implemented" -#endif - -// 7.28.1 p.3: Macros - -#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; - }; -#endif - -typedef void(*tss_dtor_t) (void*); -typedef int (*thrd_start_t)(void*); - -// 7.28.1 p.5: Enumeration constants - -enum { - mtx_plain = 0, - mtx_recursive = 1, - mtx_timed = 2, -}; - -enum { - thrd_success, - thrd_timedout, - thrd_busy, - thrd_error, - thrd_nomem -}; - -// 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); -int thrd_equal (thrd_t thr0, thrd_t thr1); -int thrd_join (thrd_t thr, int *res); -void thrd_yield (void); -int thrd_sleep( - const struct timespec *duration, - struct timespec *remaining -); -_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/include/time.h b/include/time.h deleted file mode 100644 index 308a681..0000000 --- a/include/time.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -// 7.29.1 p.2: Macros - -#define __STDC_VERSION_TIME_H__ 202311L - -#if !defined(NULL) - #define NULL ((void *)0) -#endif - -#define CLOCKS_PER_SEC ((clock_t)1000000) - -#define TIME_UTC 1 -#define TIME_MONOTONIC 2 -#define TIME_ACTIVE 3 -#define TIME_THREAD_ACTIVE 4 - -// 7.29.1 p.4: Types - -#if defined(_WIN32) - typedef unsigned long long size_t; -#else - typedef unsigned long size_t; -#endif - -typedef unsigned long long clock_t; -typedef unsigned long long time_t; - -#if !defined(_timespec_defined) - #define _timespec_defined - struct timespec { - time_t tv_sec; - long tv_nsec; - }; -#endif - -#if !defined(_tm_defined) - #define _tm_defined - struct tm { - int tm_sec; - int tm_min; - int tm_hour; - int tm_mon; - int tm_mday; - int tm_year; - int tm_wday; - int tm_yday; - int tm_isdst; - }; -#endif - -// Basic timer functions -clock_t clock(void); -time_t time(time_t *timer); -double difftime(time_t time1, time_t time0); - -// Human-readable time functions -time_t mktime(struct tm *timeptr); -struct tm *gmtime(const time_t *timer); -struct tm *localtime(const time_t *timer); - -// Timespec functions -int timespec_get(struct timespec *ts, int base); -int timespec_getres(struct timespec *ts, int base); - -// Time formatting functions -char *asctime(const struct tm *timeptr); -char *ctime(const time_t *timer); -size_t strftime(char *restrict str, size_t sz, const char *restrict fmt, const struct tm *restrict time); - -#ifdef __STDC_WANT_LIB_EXT1__ - -errno_t asctime_s(char *s, rsize_t maxsize, const struct tm *timeptr); -errno_t ctime_s(char *s, rsize_t maxsize, const time_t *timer); -struct tm *gmtime_s(const time_t * restrict timer, struct tm * restrict result); -struct tm *localtime_s(const time_t * restrict timer, struct tm * restrict result); - -#endif diff --git a/include/uchar.h b/include/uchar.h deleted file mode 100644 index e4d591f..0000000 --- a/include/uchar.h +++ /dev/null @@ -1,48 +0,0 @@ - -#pragma once - -#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 unsigned short char16_t; -typedef unsigned int char32_t; - -size_t mbrtoc16( - char16_t *restrict pc16, - char const *restrict s, - size_t n, - mbstate_t *restrict ps -); - -size_t c16rtomb( - char *restrict s, - char16_t c16, - mbstate_t *restrict ps -); - -size_t mbrtoc32( - char32_t *restrict pc32, - char const *restrict s, - size_t n, - mbstate_t *restrict ps -); - -size_t c32rtomb( - char *restrict s, - char32_t c32, - mbstate_t *restrict ps -); diff --git a/include/wchar.h b/include/wchar.h deleted file mode 100644 index 580e306..0000000 --- a/include/wchar.h +++ /dev/null @@ -1,187 +0,0 @@ - -#pragma once - -#include -#include - -#if !defined(WEOF) - #define WEOF -1 -#endif - -#if !defined(NULL) - #define NULL ((void *)0) -#endif - -#if defined(_WIN32) - #if !defined(WCHAR_MIN) - #define WCHAR_MIN 0x0000 - #endif - #if !defined(WCHAR_MAX) - #define WCHAR_MAX 0xffff - #endif - typedef unsigned short wchar_t; -#else - #if !defined(WCHAR_MIN) - #define WCHAR_MIN -0x80000000 - #endif - #if !defined(WCHAR_MAX) - #define WCHAR_MAX +0x7fffffff - #endif - typedef int wchar_t; -#endif - -typedef int wint_t; -typedef int wint_t; -typedef int (*wctrans_t)(wint_t wc); -typedef int (*wctype_t)(wint_t wc); - -#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 - -#if !defined(_tm_defined) - #define _tm_defined - struct tm { - int tm_sec; - int tm_min; - int tm_hour; - int tm_mon; - int tm_mday; - int tm_year; - int tm_wday; - int tm_yday; - int tm_isdst; - }; -#endif - -typedef struct FILE FILE; - -// String length -size_t wcslen(const wchar_t *s); - -// Copying -wchar_t *wmemset (wchar_t *s, wchar_t c, size_t n); -wchar_t *wmemmove(wchar_t *s1, wchar_t const *s2, size_t n); -wchar_t *wmemcpy (wchar_t *restrict s1, wchar_t const *restrict s2, size_t n); -wchar_t *wcsncpy (wchar_t *restrict s1, wchar_t const *restrict s2, size_t n); -wchar_t *wcscpy (wchar_t *restrict s1, wchar_t const *restrict s2); - -// Concat -wchar_t *wcscat (wchar_t *restrict s1, wchar_t const *restrict s2); -wchar_t *wcsncat(wchar_t *restrict s1, wchar_t const *restrict s2, size_t n); - -// Comparison -int wcscmp (wchar_t const *s1, wchar_t const *s2); -int wcsncmp(wchar_t const *s1, wchar_t const *s2, size_t n); -int wmemcmp(wchar_t const *s1, wchar_t const *s2, size_t n); - -// Localization -int wcscoll (wchar_t const *s1, wchar_t const *s2); -size_t wcsxfrm (wchar_t *restrict s1, wchar_t const *restrict s2, size_t n); - -// Tokenization and stuff -wchar_t *wmemchr(wchar_t const *s, wchar_t c, size_t n); -wchar_t *wcschr (wchar_t const *s, wchar_t c); -wchar_t *wcsrchr(wchar_t const *s, wchar_t c); -wchar_t *wcspbrk(wchar_t const *s1, wchar_t const *s2); -size_t wcscspn(wchar_t const *s1, wchar_t const *s2); -size_t wcsspn (wchar_t const *s1, wchar_t const *s2); -wchar_t *wcsstr (wchar_t const *s1, wchar_t const *s2); -wchar_t *wcstok (wchar_t *restrict s1, wchar_t const *restrict s2, wchar_t **restrict ptr); - -// Formatted print -int vfwprintf(FILE *restrict stream, const wchar_t *restrict format, va_list arg); -int fwprintf (FILE *restrict stream, const wchar_t *restrict format, ...); -int vswprintf(wchar_t *restrict s, size_t n, const wchar_t *restrict format, va_list arg); -int swprintf (wchar_t *restrict s, size_t n, const wchar_t *restrict format, ...); -int vwprintf (wchar_t const *restrict format, va_list arg); -int wprintf (wchar_t const *restrict format, ...); - -// Formatted scan -int vfwscanf(FILE *restrict stream, const wchar_t *restrict format, va_list arg); -int fwscanf (FILE *restrict stream, const wchar_t *restrict format, ...); -int vswscanf(const wchar_t *restrict s, const wchar_t *restrict format, va_list arg); -int swscanf (const wchar_t *restrict s, const wchar_t *restrict format, ...); -int vwscanf (const wchar_t *restrict format, va_list arg); -int wscanf (const wchar_t *restrict format, ...); - -// File reading -wint_t fgetwc(FILE *stream); -wchar_t *fgetws(wchar_t *restrict s, int n, FILE *restrict stream); -wint_t getwc(FILE *stream); -wint_t getwchar(void); -wint_t ungetwc(wint_t c, FILE *stream); -wint_t fputwc(wchar_t c, FILE *stream); - -// File writing -int fputws(const wchar_t *restrict s, FILE *restrict stream); -wint_t putwc(wchar_t c, FILE *stream); -wint_t putwchar(wchar_t c); - -// Switch stream mode to wide -int fwide(FILE *stream, int mode); - -// Float conversions -double wcstod (wchar_t const *restrict nptr, wchar_t **restrict endptr); -float wcstof (wchar_t const *restrict nptr, wchar_t **restrict endptr); - -// Integer conversions -long double wcstold (wchar_t const *restrict nptr, wchar_t **restrict endptr); -long int wcstol (wchar_t const *restrict nptr, wchar_t **restrict endptr, int base); -long long int wcstoll (wchar_t const *restrict nptr, wchar_t **restrict endptr, int base); -unsigned long int wcstoul (wchar_t const *restrict nptr, wchar_t **restrict endptr, int base); -unsigned long long int wcstoull(wchar_t const *restrict nptr, wchar_t **restrict endptr, int base); - -// Character conversions -wint_t btowc(int c); -int wctob(wint_t c); - -// Ftime conversion -size_t wcsftime(wchar_t *restrict s, size_t maxsize, const wchar_t *restrict format, const struct tm *restrict timeptr); - -// Multibyte conversions -int mbsinit (mbstate_t const *ps); -size_t mbrlen (char const *restrict s, size_t n, mbstate_t *restrict ps); -size_t mbrtowc (wchar_t *restrict pwc, char const *restrict s, size_t n, mbstate_t *restrict ps); -size_t mbsrtowcs(wchar_t *restrict dst, char const **restrict src, size_t len, mbstate_t *restrict ps); -size_t wcrtomb (char *restrict s, wchar_t wc, mbstate_t *restrict ps); -size_t wcsrtombs(char *restrict dst, wchar_t const **restrict src, size_t len, mbstate_t *restrict ps); - -#ifdef __STDC_WANT_LIB_EXT1__ - -int vfwprintf_s (FILE *restrict stream, const wchar_t *restrict format, va_list arg); -int fwprintf_s (FILE *restrict stream, const wchar_t *restrict format, ...); -int vsnwprintf_s(wchar_t *restrict s, rsize_t n, const wchar_t *restrict format, va_list arg); -int vswprintf_s (wchar_t *restrict s, rsize_t n, const wchar_t *restrict format, va_list arg); -int snwprintf_s (wchar_t *restrict s, rsize_t n, const wchar_t *restrict format, ...); -int swprintf_s (wchar_t *restrict s, rsize_t n, const wchar_t *restrict format, ...); -int vwprintf_s (wchar_t const *restrict format, va_list arg); -int wprintf_s (wchar_t const *restrict format, ...); - -int vfwscanf_s(FILE *restrict stream, const wchar_t *restrict format, va_list arg); -int fwscanf_s (FILE *restrict stream, const wchar_t *restrict format, ...); -int vswscanf_s(const wchar_t *restrict s, const wchar_t *restrict format, va_list arg); -int swscanf_s (const wchar_t *restrict s, const wchar_t *restrict format, ...); -int vwscanf_s (const wchar_t *restrict format, va_list arg); -int wscanf_s (const wchar_t *restrict format, ...); - -errno_t wcscpy_s (wchar_t *restrict s1, rsize_t s1max, const wchar_t *restrict s2); -errno_t wcsncpy_s (wchar_t *restrict s1, rsize_t s1max, const wchar_t *restrict s2, rsize_t n); -errno_t wmemcpy_s (wchar_t *restrict s1, rsize_t s1max, const wchar_t *restrict s2, rsize_t n); -errno_t wmemmove_s(wchar_t *s1, rsize_t s1max, const wchar_t *s2, rsize_t n); -errno_t wcscat_s (wchar_t *restrict s1, rsize_t s1max, const wchar_t *restrict s2); -errno_t wcsncat_s (wchar_t *restrict s1, rsize_t s1max, const wchar_t *restrict s2, rsize_t n); -wchar_t *wcstok_s (wchar_t *restrict s1, rsize_t *restrict s1max, const wchar_t *restrict s2, wchar_t **restrict ptr); -size_t wcsnlen_s (const wchar_t *s, size_t maxsize); -errno_t wcrtomb_s (size_t *restrict retval, char *restrict s, rsize_t smax, wchar_t wc, mbstate_t *restrict ps); -errno_t mbsrtowcs_s(size_t *restrict retval, wchar_t *restrict dst, rsize_t dstmax, const char **restrict src, rsize_t len, mbstate_t *restrict ps); -errno_t wcsrtombs_s(size_t *restrict retval, char *restrict dst, rsize_t dstmax, const wchar_t **restrict src, rsize_t len, mbstate_t *restrict ps); - -#endif diff --git a/include/wctype.h b/include/wctype.h deleted file mode 100644 index 01cd6ca..0000000 --- a/include/wctype.h +++ /dev/null @@ -1,29 +0,0 @@ - -#pragma once - -typedef int wint_t; -typedef int (*wctrans_t)(wint_t wc); -typedef int (*wctype_t)(wint_t wc); - -#if !defined(WEOF) - #define WEOF 0 -#endif - -int iswalnum(wint_t wc); -int iswalpha(wint_t wc); -int iswblank(wint_t wc); -int iswcntrl(wint_t wc); -int iswdigit(wint_t wc); -int iswgraph(wint_t wc); -int iswlower(wint_t wc); -int iswprint(wint_t wc); -int iswpunct(wint_t wc); -int iswspace(wint_t wc); -int iswupper(wint_t wc); -int iswxdigit(wint_t wc); -int iswctype(wint_t wc, wctype_t desc); -wctype_t wctype(const char *property); -wint_t towlower(wint_t wc); -wint_t towupper(wint_t wc); -wint_t towctrans(wint_t wc, wctrans_t desc); -wctrans_t wctrans(const char *property); diff --git a/license b/license new file mode 100644 index 0000000..f8e0f77 --- /dev/null +++ b/license @@ -0,0 +1,13 @@ +Zero-Clause BSD +============= + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE +FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE \ No newline at end of file diff --git a/readme.md b/readme.md index 9114ddd..27843e4 100644 --- a/readme.md +++ b/readme.md @@ -38,23 +38,57 @@ This library is supposed to be extensible to other platforms, meaning that you can write an OS layer for another OS and use the rest of the CRT functionality. -## Building & Usage +## Building ciabatta Building ciabatta with MSVC is not supported. The only compiler that the library have been compiled and tested with is clang. Note that the library can only be used with clang -1. Run ./build.cmd to compile ciabatta - - (Optionally) Run `./test crt` to make sure there are no errors -2. Grab the following files into your project's directory: - - The `./include` folder - - The `./ciabatta.lib` archive file - - The `./utf8.obj` object file -3. Add the following flags to your compilation command: - `-I ./include utf8.obj -nostdlib -mfma` -4. Don't forget to link to the following libraries: - `-lciabatta.lib` +### Building on windows + +Run ./build.ps1 to compile ciabatta +- (Optionally) Run `./test crt` to make sure there are no errors + +### Building and using on linux + +There are two options: Use ciabatta as a shared library or as a static +library. + +Run ./build.sh to compile ciabatta +- If you wish to use shared library instead add -shared option to the build script + +## Usage + +Grab the following files into your project's (or any other) directory: + +- The `./include` folder +- The `.lib` folder +- (Windows only) The `utf8` folder + +In order to compile your project with ciabatta see the following sections + +### Compiling with ciabatta on windows + +1. Add the following flags to your compilation command: + `-nostdlib -I ./include utf8.obj -mfma` +2. Link to the following libraries: + `-l ./lib/ciabatta.lib` + +**Note:** The `include` folder refers to the folder you copied from ciabatta. Set the path to it accordingly. + +### Compiling with ciabatta on linux + +1. In case of static linking: + 1. Add the following flags to your compilation command: + `-nostdlib -static -I ./include` + 2. Link to the following libraries + `./lib/ciabatta.a` +2. In case of dynamic linking: + 1. Add the following flags to your compilation command: + `-nostdlib -no-pie -I ./include` + 2. Link to the following libraries: + `./lib/ciabatta.so ./lib.ctors.o ./lib.entry.o` ## Contributing @@ -62,4 +96,4 @@ Pull requests welcome and accepted in any form. ## License -TBD +See [the license file](license) diff --git a/src/ciabatta.c b/src/ciabatta.c index d9d6a32..6396d56 100644 --- a/src/ciabatta.c +++ b/src/ciabatta.c @@ -1,78 +1,7 @@ -// Standard Headers -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include -// Intrinsics -#if !defined(__FMA__) -#if !defined(_MSC_VER) -#error "Get a better CPU (the kind that supports FMA) or enable -mfma" -#endif -#endif -// xmmintrin.h depends on mm_malloc.h, which itself includes other CRT headers -// Which introduces compiler errors. Actually does it really matter? I would -// need to check again -#undef __STDC_HOSTED__ -// #include -#include - -#include "intrin.h" - -// Platform-independent functionality -#include "util.c" -#include "math/basic.c" -#include "math/division.c" -#include "math/gen_math.c" -#include "math/bits.c" -#include "math/round.c" -#include "conv/decfloat/decfloat.c" -#include "conv/digits.c" -#include "conv/strpfx.c" -#include "conv/int.c" -#include "conv/float.c" -#include "stdlib/algorithm.c" -#include "stdlib/multibyte.c" -#include "stdlib/random.c" -#include "ctype.c" -#include "errno.c" -#include "fenv.c" -#include "locale.c" -#include "string.c" -#include "uchar.c" -#include "wchar.c" -#include "wctype.c" - -// Windows platform functionality -#if defined(CIABATTA_WIN) -#include "os_win/win.h" -#include "os_win/cookie.c" -#include "os_win/assert.c" -#include "os_win/cmdline.c" -#include "os_win/env.c" -#include "os_win/mem.c" -#include "os_win/signal.c" -#include "os_win/file.c" -#include "os_win/thread.c" -#include "os_win/time.c" -#include "os_win/entry.c" +#if os_is_linux() + #include "linux/syscall.c" + #include "linux/entry.c" #endif diff --git a/src/conv/decfloat/decfloat.c b/src/conv/decfloat/decfloat.c deleted file mode 100644 index a8857c4..0000000 --- a/src/conv/decfloat/decfloat.c +++ /dev/null @@ -1,319 +0,0 @@ - -#include "decfloat_table.h" - -typedef struct decfloat_t decfloat_t; -struct decfloat_t { - u64 sign; - u64 exponent; - i64 mantissa; -}; - -#define DOUBLE_MANTISSA_BITS 52 -#define DOUBLE_EXPONENT_BITS 11 -#define DOUBLE_BIAS 1023 - -static const char DIGIT_TABLE[200] = { - "00010203040506070809101112131415161718192021222324" - "25262728293031323334353637383940414243444546474849" - "50515253545556575859606162636465666768697071727374" - "75767778798081828384858687888990919293949596979899" -}; - -static inline u32 pow5Factor(u64 value) { - const u64 m_inv_5 = 14757395258967641293u; // 5 * m_inv_5 = 1 (mod 2^64) - const u64 n_div_5 = 3689348814741910323u; // #{ n | n = 0 (mod 2^64) } = 2^64 / 5 - u32 count = 0; - for (;;) { - value *= m_inv_5; - if (value > n_div_5) - break; - ++count; - } - return count; -} - -// Returns true if value is divisible by 5^p. -static inline bool multipleOfPowerOf5(const u64 value, const u32 p) { - // I tried a case distinction on p, but there was no performance difference. - return pow5Factor(value) >= p; -} - -// Returns true if value is divisible by 2^p. -static inline bool multipleOfPowerOf2(const u64 value, const u32 p) { - // __builtin_ctzll doesn't appear to be faster here. - return (value & ((1ull << p) - 1)) == 0; -} - -static inline u64 umul128(const u64 a, const u64 b, u64* const productHi) { - return _umul128(a, b, productHi); -} - -static inline u64 umulh(const u64 a, const u64 b) { - u64 hi; - umul128(a, b, &hi); - return hi; -} - -static inline u64 shiftright128(const u64 lo, const u64 hi, const u32 dist) { - return __shiftright128(lo, hi, (unsigned char) dist); -} - -static inline u64 mulShift64(const u64 m, const u64* const mul, const int32_t j) { - // m is maximum 55 bits - u64 high1; // 128 - const u64 low1 = umul128(m, mul[1], &high1); // 64 - u64 high0; // 64 - umul128(m, mul[0], &high0); // 0 - const u64 sum = high0 + low1; - if (sum < high0) { - ++high1; // overflow into high1 - } - return shiftright128(sum, high1, j - 64); -} - - -static inline u64 mulShiftAll64(const u64 m, const u64* const mul, const int32_t j, - u64* const vp, u64* const vm, const u32 mmShift) { - *vp = mulShift64(4 * m + 2, mul, j); - *vm = mulShift64(4 * m - 1 - mmShift, mul, j); - return mulShift64(4 * m, mul, j); -} - -// Returns floor(log_10(2^e)); requires 0 <= e <= 1650. -static inline u32 log10Pow2(const int32_t e) { - // The first value this approximation fails for is 2^1651 which is just greater than 10^297. - return (((u32) e) * 78913) >> 18; -} - -// Returns floor(log_10(5^e)); requires 0 <= e <= 2620. -static inline u32 log10Pow5(const int32_t e) { - // The first value this approximation fails for is 5^2621 which is just greater than 10^1832. - return (((u32) e) * 732923) >> 20; -} - -// Returns e == 0 ? 1 : ceil(log_2(5^e)); requires 0 <= e <= 3528. -static inline int32_t pow5bits(const int32_t e) { - // This approximation works up to the point that the multiplication overflows at e = 3529. - // If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater - // than 2^9297. - return (int32_t) (((((u32) e) * 1217359) >> 19) + 1); -} - -static inline u32 decimalLength17(const u64 v) { - // This is slightly faster than a loop. - // The average output length is 16.38 digits, so we check high-to-low. - // Function precondition: v is not an 18, 19, or 20-digit number. - // (17 digits are sufficient for round-tripping.) - if (v >= 10000000000000000L) { return 17; } - if (v >= 1000000000000000L) { return 16; } - if (v >= 100000000000000L) { return 15; } - if (v >= 10000000000000L) { return 14; } - if (v >= 1000000000000L) { return 13; } - if (v >= 100000000000L) { return 12; } - if (v >= 10000000000L) { return 11; } - if (v >= 1000000000L) { return 10; } - if (v >= 100000000L) { return 9; } - if (v >= 10000000L) { return 8; } - if (v >= 1000000L) { return 7; } - if (v >= 100000L) { return 6; } - if (v >= 10000L) { return 5; } - if (v >= 1000L) { return 4; } - if (v >= 100L) { return 3; } - if (v >= 10L) { return 2; } - return 1; -} - -static inline u64 div5(const u64 x) { - return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 2; -} - -static inline u64 div10(const u64 x) { - return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 3; -} - -static inline u64 div100(const u64 x) { - return umulh(x >> 2, 0x28F5C28F5C28F5C3u) >> 2; -} - -static inline u64 div1e8(const u64 x) { - return umulh(x, 0xABCC77118461CEFDu) >> 26; -} - -static decfloat_t ieee_to_decimal(u64 sign, u64 ieeeMantissa, u32 ieeeExponent) { - int32_t e2; - u64 m2; - if (ieeeExponent == 0) { - // We subtract 2 so that the bounds computation has 2 additional bits. - e2 = 1 - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2; - m2 = ieeeMantissa; - } else { - e2 = (int32_t) ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2; - m2 = (1ull << DOUBLE_MANTISSA_BITS) | ieeeMantissa; - } - const bool even = (m2 & 1) == 0; - const bool acceptBounds = even; - - // Step 2: Determine the interval of valid decimal representations. - const u64 mv = 4 * m2; - // Implicit bool -> int conversion. True is 1, false is 0. - const u32 mmShift = ieeeMantissa != 0 || ieeeExponent <= 1; - // We would compute mp and mm like this: - // u64 mp = 4 * m2 + 2; - // u64 mm = mv - 1 - mmShift; - - // Step 3: Convert to a decimal power base using 128-bit arithmetic. - u64 vr, vp, vm; - int32_t e10; - bool vmIsTrailingZeros = false; - bool vrIsTrailingZeros = false; - if (e2 >= 0) { - // I tried special-casing q == 0, but there was no effect on performance. - // This expression is slightly faster than max(0, log10Pow2(e2) - 1). - const u32 q = log10Pow2(e2) - (e2 > 3); - e10 = (int32_t) q; - const int32_t k = DOUBLE_POW5_INV_BITCOUNT + pow5bits((int32_t) q) - 1; - const int32_t i = -e2 + (int32_t) q + k; - vr = mulShiftAll64(m2, DOUBLE_POW5_INV_SPLIT[q], i, &vp, &vm, mmShift); - if (q <= 21) { - // This should use q <= 22, but I think 21 is also safe. Smaller values - // may still be safe, but it's more difficult to reason about them. - // Only one of mp, mv, and mm can be a multiple of 5, if any. - const u32 mvMod5 = ((u32) mv) - 5 * ((u32) div5(mv)); - if (mvMod5 == 0) { - vrIsTrailingZeros = multipleOfPowerOf5(mv, q); - } else if (acceptBounds) { - // Same as min(e2 + (~mm & 1), pow5Factor(mm)) >= q - // <=> e2 + (~mm & 1) >= q && pow5Factor(mm) >= q - // <=> true && pow5Factor(mm) >= q, since e2 >= q. - vmIsTrailingZeros = multipleOfPowerOf5(mv - 1 - mmShift, q); - } else { - // Same as min(e2 + 1, pow5Factor(mp)) >= q. - vp -= multipleOfPowerOf5(mv + 2, q); - } - } - } else { - // This expression is slightly faster than max(0, log10Pow5(-e2) - 1). - const u32 q = log10Pow5(-e2) - (-e2 > 1); - e10 = (int32_t) q + e2; - const int32_t i = -e2 - (int32_t) q; - const int32_t k = pow5bits(i) - DOUBLE_POW5_BITCOUNT; - const int32_t j = (int32_t) q - k; - vr = mulShiftAll64(m2, DOUBLE_POW5_SPLIT[i], j, &vp, &vm, mmShift); - if (q <= 1) { - // {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits. - // mv = 4 * m2, so it always has at least two trailing 0 bits. - vrIsTrailingZeros = true; - if (acceptBounds) { - // mm = mv - 1 - mmShift, so it has 1 trailing 0 bit iff mmShift == 1. - vmIsTrailingZeros = mmShift == 1; - } else { - // mp = mv + 2, so it always has at least one trailing 0 bit. - --vp; - } - } else if (q < 63) { // TODO(ulfjack): Use a tighter bound here. - // We want to know if the full product has at least q trailing zeros. - // We need to compute min(p2(mv), p5(mv) - e2) >= q - // <=> p2(mv) >= q && p5(mv) - e2 >= q - // <=> p2(mv) >= q (because -e2 >= q) - vrIsTrailingZeros = multipleOfPowerOf2(mv, q); - } - } - // Step 4: Find the shortest decimal representation in the interval of valid representations. - int32_t removed = 0; - uint8_t lastRemovedDigit = 0; - u64 output; - // On average, we remove ~2 digits. - if (vmIsTrailingZeros || vrIsTrailingZeros) { - // General case, which happens rarely (~0.7%). - for (;;) { - const u64 vpDiv10 = div10(vp); - const u64 vmDiv10 = div10(vm); - if (vpDiv10 <= vmDiv10) { - break; - } - const u32 vmMod10 = ((u32) vm) - 10 * ((u32) vmDiv10); - const u64 vrDiv10 = div10(vr); - const u32 vrMod10 = ((u32) vr) - 10 * ((u32) vrDiv10); - vmIsTrailingZeros &= vmMod10 == 0; - vrIsTrailingZeros &= lastRemovedDigit == 0; - lastRemovedDigit = (uint8_t) vrMod10; - vr = vrDiv10; - vp = vpDiv10; - vm = vmDiv10; - ++removed; - } - if (vmIsTrailingZeros) { - for (;;) { - const u64 vmDiv10 = div10(vm); - const u32 vmMod10 = ((u32) vm) - 10 * ((u32) vmDiv10); - if (vmMod10 != 0) { - break; - } - const u64 vpDiv10 = div10(vp); - const u64 vrDiv10 = div10(vr); - const u32 vrMod10 = ((u32) vr) - 10 * ((u32) vrDiv10); - vrIsTrailingZeros &= lastRemovedDigit == 0; - lastRemovedDigit = (uint8_t) vrMod10; - vr = vrDiv10; - vp = vpDiv10; - vm = vmDiv10; - ++removed; - } - } - if (vrIsTrailingZeros && lastRemovedDigit == 5 && vr % 2 == 0) { - // Round even if the exact number is .....50..0. - lastRemovedDigit = 4; - } - // We need to take vr + 1 if vr is outside bounds or we need to round up. - output = vr + ((vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || lastRemovedDigit >= 5); - } else { - // Specialized for the common case (~99.3%). Percentages below are relative to this. - bool roundUp = false; - const u64 vpDiv100 = div100(vp); - const u64 vmDiv100 = div100(vm); - if (vpDiv100 > vmDiv100) { // Optimization: remove two digits at a time (~86.2%). - const u64 vrDiv100 = div100(vr); - const u32 vrMod100 = ((u32) vr) - 100 * ((u32) vrDiv100); - roundUp = vrMod100 >= 50; - vr = vrDiv100; - vp = vpDiv100; - vm = vmDiv100; - removed += 2; - } - // Loop iterations below (approximately), without optimization above: - // 0: 0.03%, 1: 13.8%, 2: 70.6%, 3: 14.0%, 4: 1.40%, 5: 0.14%, 6+: 0.02% - // Loop iterations below (approximately), with optimization above: - // 0: 70.6%, 1: 27.8%, 2: 1.40%, 3: 0.14%, 4+: 0.02% - for (;;) { - const u64 vpDiv10 = div10(vp); - const u64 vmDiv10 = div10(vm); - if (vpDiv10 <= vmDiv10) { - break; - } - const u64 vrDiv10 = div10(vr); - const u32 vrMod10 = ((u32) vr) - 10 * ((u32) vrDiv10); - roundUp = vrMod10 >= 5; - vr = vrDiv10; - vp = vpDiv10; - vm = vmDiv10; - ++removed; - } - // We need to take vr + 1 if vr is outside bounds or we need to round up. - output = vr + (vr == vm || roundUp); - } - const int32_t exp = e10 + removed; - - decfloat_t fd; - fd.sign = sign; - fd.exponent = output? exp : 0; - fd.mantissa = output; - return fd; -} - -static decfloat_t f64_to_decimal(double d) { - u64 bits = F64_BITS(d); - u64 ieee_exp = F64_BEXP(bits); - u64 ieee_mant = F64_MANT(bits); - u64 sign = bits >> 63; - return ieee_to_decimal(sign, ieee_mant, ieee_exp); -} diff --git a/src/conv/decfloat/decfloat_table.h b/src/conv/decfloat/decfloat_table.h deleted file mode 100644 index c8629ee..0000000 --- a/src/conv/decfloat/decfloat_table.h +++ /dev/null @@ -1,367 +0,0 @@ -// Copyright 2018 Ulf Adams -// -// The contents of this file may be used under the terms of the Apache License, -// Version 2.0. -// -// (See accompanying file LICENSE-Apache or copy at -// http://www.apache.org/licenses/LICENSE-2.0) -// -// Alternatively, the contents of this file may be used under the terms of -// the Boost Software License, Version 1.0. -// (See accompanying file LICENSE-Boost or copy at -// https://www.boost.org/LICENSE_1_0.txt) -// -// Unless required by applicable law or agreed to in writing, this software -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. -#ifndef RYU_D2S_FULL_TABLE_H -#define RYU_D2S_FULL_TABLE_H - -// These tables are generated by PrintDoubleLookupTable. -#define DOUBLE_POW5_INV_BITCOUNT 125 -#define DOUBLE_POW5_BITCOUNT 125 - -#define DOUBLE_POW5_INV_TABLE_SIZE 342 -#define DOUBLE_POW5_TABLE_SIZE 326 - -static const uint64_t DOUBLE_POW5_INV_SPLIT[DOUBLE_POW5_INV_TABLE_SIZE][2] = { - { 1u, 2305843009213693952u }, { 11068046444225730970u, 1844674407370955161u }, - { 5165088340638674453u, 1475739525896764129u }, { 7821419487252849886u, 1180591620717411303u }, - { 8824922364862649494u, 1888946593147858085u }, { 7059937891890119595u, 1511157274518286468u }, - { 13026647942995916322u, 1208925819614629174u }, { 9774590264567735146u, 1934281311383406679u }, - { 11509021026396098440u, 1547425049106725343u }, { 16585914450600699399u, 1237940039285380274u }, - { 15469416676735388068u, 1980704062856608439u }, { 16064882156130220778u, 1584563250285286751u }, - { 9162556910162266299u, 1267650600228229401u }, { 7281393426775805432u, 2028240960365167042u }, - { 16893161185646375315u, 1622592768292133633u }, { 2446482504291369283u, 1298074214633706907u }, - { 7603720821608101175u, 2076918743413931051u }, { 2393627842544570617u, 1661534994731144841u }, - { 16672297533003297786u, 1329227995784915872u }, { 11918280793837635165u, 2126764793255865396u }, - { 5845275820328197809u, 1701411834604692317u }, { 15744267100488289217u, 1361129467683753853u }, - { 3054734472329800808u, 2177807148294006166u }, { 17201182836831481939u, 1742245718635204932u }, - { 6382248639981364905u, 1393796574908163946u }, { 2832900194486363201u, 2230074519853062314u }, - { 5955668970331000884u, 1784059615882449851u }, { 1075186361522890384u, 1427247692705959881u }, - { 12788344622662355584u, 2283596308329535809u }, { 13920024512871794791u, 1826877046663628647u }, - { 3757321980813615186u, 1461501637330902918u }, { 10384555214134712795u, 1169201309864722334u }, - { 5547241898389809503u, 1870722095783555735u }, { 4437793518711847602u, 1496577676626844588u }, - { 10928932444453298728u, 1197262141301475670u }, { 17486291911125277965u, 1915619426082361072u }, - { 6610335899416401726u, 1532495540865888858u }, { 12666966349016942027u, 1225996432692711086u }, - { 12888448528943286597u, 1961594292308337738u }, { 17689456452638449924u, 1569275433846670190u }, - { 14151565162110759939u, 1255420347077336152u }, { 7885109000409574610u, 2008672555323737844u }, - { 9997436015069570011u, 1606938044258990275u }, { 7997948812055656009u, 1285550435407192220u }, - { 12796718099289049614u, 2056880696651507552u }, { 2858676849947419045u, 1645504557321206042u }, - { 13354987924183666206u, 1316403645856964833u }, { 17678631863951955605u, 2106245833371143733u }, - { 3074859046935833515u, 1684996666696914987u }, { 13527933681774397782u, 1347997333357531989u }, - { 10576647446613305481u, 2156795733372051183u }, { 15840015586774465031u, 1725436586697640946u }, - { 8982663654677661702u, 1380349269358112757u }, { 18061610662226169046u, 2208558830972980411u }, - { 10759939715039024913u, 1766847064778384329u }, { 12297300586773130254u, 1413477651822707463u }, - { 15986332124095098083u, 2261564242916331941u }, { 9099716884534168143u, 1809251394333065553u }, - { 14658471137111155161u, 1447401115466452442u }, { 4348079280205103483u, 1157920892373161954u }, - { 14335624477811986218u, 1852673427797059126u }, { 7779150767507678651u, 1482138742237647301u }, - { 2533971799264232598u, 1185710993790117841u }, { 15122401323048503126u, 1897137590064188545u }, - { 12097921058438802501u, 1517710072051350836u }, { 5988988032009131678u, 1214168057641080669u }, - { 16961078480698431330u, 1942668892225729070u }, { 13568862784558745064u, 1554135113780583256u }, - { 7165741412905085728u, 1243308091024466605u }, { 11465186260648137165u, 1989292945639146568u }, - { 16550846638002330379u, 1591434356511317254u }, { 16930026125143774626u, 1273147485209053803u }, - { 4951948911778577463u, 2037035976334486086u }, { 272210314680951647u, 1629628781067588869u }, - { 3907117066486671641u, 1303703024854071095u }, { 6251387306378674625u, 2085924839766513752u }, - { 16069156289328670670u, 1668739871813211001u }, { 9165976216721026213u, 1334991897450568801u }, - { 7286864317269821294u, 2135987035920910082u }, { 16897537898041588005u, 1708789628736728065u }, - { 13518030318433270404u, 1367031702989382452u }, { 6871453250525591353u, 2187250724783011924u }, - { 9186511415162383406u, 1749800579826409539u }, { 11038557946871817048u, 1399840463861127631u }, - { 10282995085511086630u, 2239744742177804210u }, { 8226396068408869304u, 1791795793742243368u }, - { 13959814484210916090u, 1433436634993794694u }, { 11267656730511734774u, 2293498615990071511u }, - { 5324776569667477496u, 1834798892792057209u }, { 7949170070475892320u, 1467839114233645767u }, - { 17427382500606444826u, 1174271291386916613u }, { 5747719112518849781u, 1878834066219066582u }, - { 15666221734240810795u, 1503067252975253265u }, { 12532977387392648636u, 1202453802380202612u }, - { 5295368560860596524u, 1923926083808324180u }, { 4236294848688477220u, 1539140867046659344u }, - { 7078384693692692099u, 1231312693637327475u }, { 11325415509908307358u, 1970100309819723960u }, - { 9060332407926645887u, 1576080247855779168u }, { 14626963555825137356u, 1260864198284623334u }, - { 12335095245094488799u, 2017382717255397335u }, { 9868076196075591040u, 1613906173804317868u }, - { 15273158586344293478u, 1291124939043454294u }, { 13369007293925138595u, 2065799902469526871u }, - { 7005857020398200553u, 1652639921975621497u }, { 16672732060544291412u, 1322111937580497197u }, - { 11918976037903224966u, 2115379100128795516u }, { 5845832015580669650u, 1692303280103036413u }, - { 12055363241948356366u, 1353842624082429130u }, { 841837113407818570u, 2166148198531886609u }, - { 4362818505468165179u, 1732918558825509287u }, { 14558301248600263113u, 1386334847060407429u }, - { 12225235553534690011u, 2218135755296651887u }, { 2401490813343931363u, 1774508604237321510u }, - { 1921192650675145090u, 1419606883389857208u }, { 17831303500047873437u, 2271371013423771532u }, - { 6886345170554478103u, 1817096810739017226u }, { 1819727321701672159u, 1453677448591213781u }, - { 16213177116328979020u, 1162941958872971024u }, { 14873036941900635463u, 1860707134196753639u }, - { 15587778368262418694u, 1488565707357402911u }, { 8780873879868024632u, 1190852565885922329u }, - { 2981351763563108441u, 1905364105417475727u }, { 13453127855076217722u, 1524291284333980581u }, - { 7073153469319063855u, 1219433027467184465u }, { 11317045550910502167u, 1951092843947495144u }, - { 12742985255470312057u, 1560874275157996115u }, { 10194388204376249646u, 1248699420126396892u }, - { 1553625868034358140u, 1997919072202235028u }, { 8621598323911307159u, 1598335257761788022u }, - { 17965325103354776697u, 1278668206209430417u }, { 13987124906400001422u, 2045869129935088668u }, - { 121653480894270168u, 1636695303948070935u }, { 97322784715416134u, 1309356243158456748u }, - { 14913111714512307107u, 2094969989053530796u }, { 8241140556867935363u, 1675975991242824637u }, - { 17660958889720079260u, 1340780792994259709u }, { 17189487779326395846u, 2145249268790815535u }, - { 13751590223461116677u, 1716199415032652428u }, { 18379969808252713988u, 1372959532026121942u }, - { 14650556434236701088u, 2196735251241795108u }, { 652398703163629901u, 1757388200993436087u }, - { 11589965406756634890u, 1405910560794748869u }, { 7475898206584884855u, 2249456897271598191u }, - { 2291369750525997561u, 1799565517817278553u }, { 9211793429904618695u, 1439652414253822842u }, - { 18428218302589300235u, 2303443862806116547u }, { 7363877012587619542u, 1842755090244893238u }, - { 13269799239553916280u, 1474204072195914590u }, { 10615839391643133024u, 1179363257756731672u }, - { 2227947767661371545u, 1886981212410770676u }, { 16539753473096738529u, 1509584969928616540u }, - { 13231802778477390823u, 1207667975942893232u }, { 6413489186596184024u, 1932268761508629172u }, - { 16198837793502678189u, 1545815009206903337u }, { 5580372605318321905u, 1236652007365522670u }, - { 8928596168509315048u, 1978643211784836272u }, { 18210923379033183008u, 1582914569427869017u }, - { 7190041073742725760u, 1266331655542295214u }, { 436019273762630246u, 2026130648867672343u }, - { 7727513048493924843u, 1620904519094137874u }, { 9871359253537050198u, 1296723615275310299u }, - { 4726128361433549347u, 2074757784440496479u }, { 7470251503888749801u, 1659806227552397183u }, - { 13354898832594820487u, 1327844982041917746u }, { 13989140502667892133u, 2124551971267068394u }, - { 14880661216876224029u, 1699641577013654715u }, { 11904528973500979224u, 1359713261610923772u }, - { 4289851098633925465u, 2175541218577478036u }, { 18189276137874781665u, 1740432974861982428u }, - { 3483374466074094362u, 1392346379889585943u }, { 1884050330976640656u, 2227754207823337509u }, - { 5196589079523222848u, 1782203366258670007u }, { 15225317707844309248u, 1425762693006936005u }, - { 5913764258841343181u, 2281220308811097609u }, { 8420360221814984868u, 1824976247048878087u }, - { 17804334621677718864u, 1459980997639102469u }, { 17932816512084085415u, 1167984798111281975u }, - { 10245762345624985047u, 1868775676978051161u }, { 4507261061758077715u, 1495020541582440929u }, - { 7295157664148372495u, 1196016433265952743u }, { 7982903447895485668u, 1913626293225524389u }, - { 10075671573058298858u, 1530901034580419511u }, { 4371188443704728763u, 1224720827664335609u }, - { 14372599139411386667u, 1959553324262936974u }, { 15187428126271019657u, 1567642659410349579u }, - { 15839291315758726049u, 1254114127528279663u }, { 3206773216762499739u, 2006582604045247462u }, - { 13633465017635730761u, 1605266083236197969u }, { 14596120828850494932u, 1284212866588958375u }, - { 4907049252451240275u, 2054740586542333401u }, { 236290587219081897u, 1643792469233866721u }, - { 14946427728742906810u, 1315033975387093376u }, { 16535586736504830250u, 2104054360619349402u }, - { 5849771759720043554u, 1683243488495479522u }, { 15747863852001765813u, 1346594790796383617u }, - { 10439186904235184007u, 2154551665274213788u }, { 15730047152871967852u, 1723641332219371030u }, - { 12584037722297574282u, 1378913065775496824u }, { 9066413911450387881u, 2206260905240794919u }, - { 10942479943902220628u, 1765008724192635935u }, { 8753983955121776503u, 1412006979354108748u }, - { 10317025513452932081u, 2259211166966573997u }, { 874922781278525018u, 1807368933573259198u }, - { 8078635854506640661u, 1445895146858607358u }, { 13841606313089133175u, 1156716117486885886u }, - { 14767872471458792434u, 1850745787979017418u }, { 746251532941302978u, 1480596630383213935u }, - { 597001226353042382u, 1184477304306571148u }, { 15712597221132509104u, 1895163686890513836u }, - { 8880728962164096960u, 1516130949512411069u }, { 10793931984473187891u, 1212904759609928855u }, - { 17270291175157100626u, 1940647615375886168u }, { 2748186495899949531u, 1552518092300708935u }, - { 2198549196719959625u, 1242014473840567148u }, { 18275073973719576693u, 1987223158144907436u }, - { 10930710364233751031u, 1589778526515925949u }, { 12433917106128911148u, 1271822821212740759u }, - { 8826220925580526867u, 2034916513940385215u }, { 7060976740464421494u, 1627933211152308172u }, - { 16716827836597268165u, 1302346568921846537u }, { 11989529279587987770u, 2083754510274954460u }, - { 9591623423670390216u, 1667003608219963568u }, { 15051996368420132820u, 1333602886575970854u }, - { 13015147745246481542u, 2133764618521553367u }, { 3033420566713364587u, 1707011694817242694u }, - { 6116085268112601993u, 1365609355853794155u }, { 9785736428980163188u, 2184974969366070648u }, - { 15207286772667951197u, 1747979975492856518u }, { 1097782973908629988u, 1398383980394285215u }, - { 1756452758253807981u, 2237414368630856344u }, { 5094511021344956708u, 1789931494904685075u }, - { 4075608817075965366u, 1431945195923748060u }, { 6520974107321544586u, 2291112313477996896u }, - { 1527430471115325346u, 1832889850782397517u }, { 12289990821117991246u, 1466311880625918013u }, - { 17210690286378213644u, 1173049504500734410u }, { 9090360384495590213u, 1876879207201175057u }, - { 18340334751822203140u, 1501503365760940045u }, { 14672267801457762512u, 1201202692608752036u }, - { 16096930852848599373u, 1921924308174003258u }, { 1809498238053148529u, 1537539446539202607u }, - { 12515645034668249793u, 1230031557231362085u }, { 1578287981759648052u, 1968050491570179337u }, - { 12330676829633449412u, 1574440393256143469u }, { 13553890278448669853u, 1259552314604914775u }, - { 3239480371808320148u, 2015283703367863641u }, { 17348979556414297411u, 1612226962694290912u }, - { 6500486015647617283u, 1289781570155432730u }, { 10400777625036187652u, 2063650512248692368u }, - { 15699319729512770768u, 1650920409798953894u }, { 16248804598352126938u, 1320736327839163115u }, - { 7551343283653851484u, 2113178124542660985u }, { 6041074626923081187u, 1690542499634128788u }, - { 12211557331022285596u, 1352433999707303030u }, { 1091747655926105338u, 2163894399531684849u }, - { 4562746939482794594u, 1731115519625347879u }, { 7339546366328145998u, 1384892415700278303u }, - { 8053925371383123274u, 2215827865120445285u }, { 6443140297106498619u, 1772662292096356228u }, - { 12533209867169019542u, 1418129833677084982u }, { 5295740528502789974u, 2269007733883335972u }, - { 15304638867027962949u, 1815206187106668777u }, { 4865013464138549713u, 1452164949685335022u }, - { 14960057215536570740u, 1161731959748268017u }, { 9178696285890871890u, 1858771135597228828u }, - { 14721654658196518159u, 1487016908477783062u }, { 4398626097073393881u, 1189613526782226450u }, - { 7037801755317430209u, 1903381642851562320u }, { 5630241404253944167u, 1522705314281249856u }, - { 814844308661245011u, 1218164251424999885u }, { 1303750893857992017u, 1949062802279999816u }, - { 15800395974054034906u, 1559250241823999852u }, { 5261619149759407279u, 1247400193459199882u }, - { 12107939454356961969u, 1995840309534719811u }, { 5997002748743659252u, 1596672247627775849u }, - { 8486951013736837725u, 1277337798102220679u }, { 2511075177753209390u, 2043740476963553087u }, - { 13076906586428298482u, 1634992381570842469u }, { 14150874083884549109u, 1307993905256673975u }, - { 4194654460505726958u, 2092790248410678361u }, { 18113118827372222859u, 1674232198728542688u }, - { 3422448617672047318u, 1339385758982834151u }, { 16543964232501006678u, 2143017214372534641u }, - { 9545822571258895019u, 1714413771498027713u }, { 15015355686490936662u, 1371531017198422170u }, - { 5577825024675947042u, 2194449627517475473u }, { 11840957649224578280u, 1755559702013980378u }, - { 16851463748863483271u, 1404447761611184302u }, { 12204946739213931940u, 2247116418577894884u }, - { 13453306206113055875u, 1797693134862315907u }, { 3383947335406624054u, 1438154507889852726u }, - { 16482362180876329456u, 2301047212623764361u }, { 9496540929959153242u, 1840837770099011489u }, - { 11286581558709232917u, 1472670216079209191u }, { 5339916432225476010u, 1178136172863367353u }, - { 4854517476818851293u, 1885017876581387765u }, { 3883613981455081034u, 1508014301265110212u }, - { 14174937629389795797u, 1206411441012088169u }, { 11611853762797942306u, 1930258305619341071u }, - { 5600134195496443521u, 1544206644495472857u }, { 15548153800622885787u, 1235365315596378285u }, - { 6430302007287065643u, 1976584504954205257u }, { 16212288050055383484u, 1581267603963364205u }, - { 12969830440044306787u, 1265014083170691364u }, { 9683682259845159889u, 2024022533073106183u }, - { 15125643437359948558u, 1619218026458484946u }, { 8411165935146048523u, 1295374421166787957u }, - { 17147214310975587960u, 2072599073866860731u }, { 10028422634038560045u, 1658079259093488585u }, - { 8022738107230848036u, 1326463407274790868u }, { 9147032156827446534u, 2122341451639665389u }, - { 11006974540203867551u, 1697873161311732311u }, { 5116230817421183718u, 1358298529049385849u }, - { 15564666937357714594u, 2173277646479017358u }, { 1383687105660440706u, 1738622117183213887u }, - { 12174996128754083534u, 1390897693746571109u }, { 8411947361780802685u, 2225436309994513775u }, - { 6729557889424642148u, 1780349047995611020u }, { 5383646311539713719u, 1424279238396488816u }, - { 1235136468979721303u, 2278846781434382106u }, { 15745504434151418335u, 1823077425147505684u }, - { 16285752362063044992u, 1458461940118004547u }, { 5649904260166615347u, 1166769552094403638u }, - { 5350498001524674232u, 1866831283351045821u }, { 591049586477829062u, 1493465026680836657u }, - { 11540886113407994219u, 1194772021344669325u }, { 18673707743239135u, 1911635234151470921u }, - { 14772334225162232601u, 1529308187321176736u }, { 8128518565387875758u, 1223446549856941389u }, - { 1937583260394870242u, 1957514479771106223u }, { 8928764237799716840u, 1566011583816884978u }, - { 14521709019723594119u, 1252809267053507982u }, { 8477339172590109297u, 2004494827285612772u }, - { 17849917782297818407u, 1603595861828490217u }, { 6901236596354434079u, 1282876689462792174u }, - { 18420676183650915173u, 2052602703140467478u }, { 3668494502695001169u, 1642082162512373983u }, - { 10313493231639821582u, 1313665730009899186u }, { 9122891541139893884u, 2101865168015838698u }, - { 14677010862395735754u, 1681492134412670958u }, { 673562245690857633u, 1345193707530136767u } -}; - -static const uint64_t DOUBLE_POW5_SPLIT[DOUBLE_POW5_TABLE_SIZE][2] = { - { 0u, 1152921504606846976u }, { 0u, 1441151880758558720u }, - { 0u, 1801439850948198400u }, { 0u, 2251799813685248000u }, - { 0u, 1407374883553280000u }, { 0u, 1759218604441600000u }, - { 0u, 2199023255552000000u }, { 0u, 1374389534720000000u }, - { 0u, 1717986918400000000u }, { 0u, 2147483648000000000u }, - { 0u, 1342177280000000000u }, { 0u, 1677721600000000000u }, - { 0u, 2097152000000000000u }, { 0u, 1310720000000000000u }, - { 0u, 1638400000000000000u }, { 0u, 2048000000000000000u }, - { 0u, 1280000000000000000u }, { 0u, 1600000000000000000u }, - { 0u, 2000000000000000000u }, { 0u, 1250000000000000000u }, - { 0u, 1562500000000000000u }, { 0u, 1953125000000000000u }, - { 0u, 1220703125000000000u }, { 0u, 1525878906250000000u }, - { 0u, 1907348632812500000u }, { 0u, 1192092895507812500u }, - { 0u, 1490116119384765625u }, { 4611686018427387904u, 1862645149230957031u }, - { 9799832789158199296u, 1164153218269348144u }, { 12249790986447749120u, 1455191522836685180u }, - { 15312238733059686400u, 1818989403545856475u }, { 14528612397897220096u, 2273736754432320594u }, - { 13692068767113150464u, 1421085471520200371u }, { 12503399940464050176u, 1776356839400250464u }, - { 15629249925580062720u, 2220446049250313080u }, { 9768281203487539200u, 1387778780781445675u }, - { 7598665485932036096u, 1734723475976807094u }, { 274959820560269312u, 2168404344971008868u }, - { 9395221924704944128u, 1355252715606880542u }, { 2520655369026404352u, 1694065894508600678u }, - { 12374191248137781248u, 2117582368135750847u }, { 14651398557727195136u, 1323488980084844279u }, - { 13702562178731606016u, 1654361225106055349u }, { 3293144668132343808u, 2067951531382569187u }, - { 18199116482078572544u, 1292469707114105741u }, { 8913837547316051968u, 1615587133892632177u }, - { 15753982952572452864u, 2019483917365790221u }, { 12152082354571476992u, 1262177448353618888u }, - { 15190102943214346240u, 1577721810442023610u }, { 9764256642163156992u, 1972152263052529513u }, - { 17631875447420442880u, 1232595164407830945u }, { 8204786253993389888u, 1540743955509788682u }, - { 1032610780636961552u, 1925929944387235853u }, { 2951224747111794922u, 1203706215242022408u }, - { 3689030933889743652u, 1504632769052528010u }, { 13834660704216955373u, 1880790961315660012u }, - { 17870034976990372916u, 1175494350822287507u }, { 17725857702810578241u, 1469367938527859384u }, - { 3710578054803671186u, 1836709923159824231u }, { 26536550077201078u, 2295887403949780289u }, - { 11545800389866720434u, 1434929627468612680u }, { 14432250487333400542u, 1793662034335765850u }, - { 8816941072311974870u, 2242077542919707313u }, { 17039803216263454053u, 1401298464324817070u }, - { 12076381983474541759u, 1751623080406021338u }, { 5872105442488401391u, 2189528850507526673u }, - { 15199280947623720629u, 1368455531567204170u }, { 9775729147674874978u, 1710569414459005213u }, - { 16831347453020981627u, 2138211768073756516u }, { 1296220121283337709u, 1336382355046097823u }, - { 15455333206886335848u, 1670477943807622278u }, { 10095794471753144002u, 2088097429759527848u }, - { 6309871544845715001u, 1305060893599704905u }, { 12499025449484531656u, 1631326116999631131u }, - { 11012095793428276666u, 2039157646249538914u }, { 11494245889320060820u, 1274473528905961821u }, - { 532749306367912313u, 1593091911132452277u }, { 5277622651387278295u, 1991364888915565346u }, - { 7910200175544436838u, 1244603055572228341u }, { 14499436237857933952u, 1555753819465285426u }, - { 8900923260467641632u, 1944692274331606783u }, { 12480606065433357876u, 1215432671457254239u }, - { 10989071563364309441u, 1519290839321567799u }, { 9124653435777998898u, 1899113549151959749u }, - { 8008751406574943263u, 1186945968219974843u }, { 5399253239791291175u, 1483682460274968554u }, - { 15972438586593889776u, 1854603075343710692u }, { 759402079766405302u, 1159126922089819183u }, - { 14784310654990170340u, 1448908652612273978u }, { 9257016281882937117u, 1811135815765342473u }, - { 16182956370781059300u, 2263919769706678091u }, { 7808504722524468110u, 1414949856066673807u }, - { 5148944884728197234u, 1768687320083342259u }, { 1824495087482858639u, 2210859150104177824u }, - { 1140309429676786649u, 1381786968815111140u }, { 1425386787095983311u, 1727233711018888925u }, - { 6393419502297367043u, 2159042138773611156u }, { 13219259225790630210u, 1349401336733506972u }, - { 16524074032238287762u, 1686751670916883715u }, { 16043406521870471799u, 2108439588646104644u }, - { 803757039314269066u, 1317774742903815403u }, { 14839754354425000045u, 1647218428629769253u }, - { 4714634887749086344u, 2059023035787211567u }, { 9864175832484260821u, 1286889397367007229u }, - { 16941905809032713930u, 1608611746708759036u }, { 2730638187581340797u, 2010764683385948796u }, - { 10930020904093113806u, 1256727927116217997u }, { 18274212148543780162u, 1570909908895272496u }, - { 4396021111970173586u, 1963637386119090621u }, { 5053356204195052443u, 1227273366324431638u }, - { 15540067292098591362u, 1534091707905539547u }, { 14813398096695851299u, 1917614634881924434u }, - { 13870059828862294966u, 1198509146801202771u }, { 12725888767650480803u, 1498136433501503464u }, - { 15907360959563101004u, 1872670541876879330u }, { 14553786618154326031u, 1170419088673049581u }, - { 4357175217410743827u, 1463023860841311977u }, { 10058155040190817688u, 1828779826051639971u }, - { 7961007781811134206u, 2285974782564549964u }, { 14199001900486734687u, 1428734239102843727u }, - { 13137066357181030455u, 1785917798878554659u }, { 11809646928048900164u, 2232397248598193324u }, - { 16604401366885338411u, 1395248280373870827u }, { 16143815690179285109u, 1744060350467338534u }, - { 10956397575869330579u, 2180075438084173168u }, { 6847748484918331612u, 1362547148802608230u }, - { 17783057643002690323u, 1703183936003260287u }, { 17617136035325974999u, 2128979920004075359u }, - { 17928239049719816230u, 1330612450002547099u }, { 17798612793722382384u, 1663265562503183874u }, - { 13024893955298202172u, 2079081953128979843u }, { 5834715712847682405u, 1299426220705612402u }, - { 16516766677914378815u, 1624282775882015502u }, { 11422586310538197711u, 2030353469852519378u }, - { 11750802462513761473u, 1268970918657824611u }, { 10076817059714813937u, 1586213648322280764u }, - { 12596021324643517422u, 1982767060402850955u }, { 5566670318688504437u, 1239229412751781847u }, - { 2346651879933242642u, 1549036765939727309u }, { 7545000868343941206u, 1936295957424659136u }, - { 4715625542714963254u, 1210184973390411960u }, { 5894531928393704067u, 1512731216738014950u }, - { 16591536947346905892u, 1890914020922518687u }, { 17287239619732898039u, 1181821263076574179u }, - { 16997363506238734644u, 1477276578845717724u }, { 2799960309088866689u, 1846595723557147156u }, - { 10973347230035317489u, 1154122327223216972u }, { 13716684037544146861u, 1442652909029021215u }, - { 12534169028502795672u, 1803316136286276519u }, { 11056025267201106687u, 2254145170357845649u }, - { 18439230838069161439u, 1408840731473653530u }, { 13825666510731675991u, 1761050914342066913u }, - { 3447025083132431277u, 2201313642927583642u }, { 6766076695385157452u, 1375821026829739776u }, - { 8457595869231446815u, 1719776283537174720u }, { 10571994836539308519u, 2149720354421468400u }, - { 6607496772837067824u, 1343575221513417750u }, { 17482743002901110588u, 1679469026891772187u }, - { 17241742735199000331u, 2099336283614715234u }, { 15387775227926763111u, 1312085177259197021u }, - { 5399660979626290177u, 1640106471573996277u }, { 11361262242960250625u, 2050133089467495346u }, - { 11712474920277544544u, 1281333180917184591u }, { 10028907631919542777u, 1601666476146480739u }, - { 7924448521472040567u, 2002083095183100924u }, { 14176152362774801162u, 1251301934489438077u }, - { 3885132398186337741u, 1564127418111797597u }, { 9468101516160310080u, 1955159272639746996u }, - { 15140935484454969608u, 1221974545399841872u }, { 479425281859160394u, 1527468181749802341u }, - { 5210967620751338397u, 1909335227187252926u }, { 17091912818251750210u, 1193334516992033078u }, - { 12141518985959911954u, 1491668146240041348u }, { 15176898732449889943u, 1864585182800051685u }, - { 11791404716994875166u, 1165365739250032303u }, { 10127569877816206054u, 1456707174062540379u }, - { 8047776328842869663u, 1820883967578175474u }, { 836348374198811271u, 2276104959472719343u }, - { 7440246761515338900u, 1422565599670449589u }, { 13911994470321561530u, 1778206999588061986u }, - { 8166621051047176104u, 2222758749485077483u }, { 2798295147690791113u, 1389224218428173427u }, - { 17332926989895652603u, 1736530273035216783u }, { 17054472718942177850u, 2170662841294020979u }, - { 8353202440125167204u, 1356664275808763112u }, { 10441503050156459005u, 1695830344760953890u }, - { 3828506775840797949u, 2119787930951192363u }, { 86973725686804766u, 1324867456844495227u }, - { 13943775212390669669u, 1656084321055619033u }, { 3594660960206173375u, 2070105401319523792u }, - { 2246663100128858359u, 1293815875824702370u }, { 12031700912015848757u, 1617269844780877962u }, - { 5816254103165035138u, 2021587305976097453u }, { 5941001823691840913u, 1263492066235060908u }, - { 7426252279614801142u, 1579365082793826135u }, { 4671129331091113523u, 1974206353492282669u }, - { 5225298841145639904u, 1233878970932676668u }, { 6531623551432049880u, 1542348713665845835u }, - { 3552843420862674446u, 1927935892082307294u }, { 16055585193321335241u, 1204959932551442058u }, - { 10846109454796893243u, 1506199915689302573u }, { 18169322836923504458u, 1882749894611628216u }, - { 11355826773077190286u, 1176718684132267635u }, { 9583097447919099954u, 1470898355165334544u }, - { 11978871809898874942u, 1838622943956668180u }, { 14973589762373593678u, 2298278679945835225u }, - { 2440964573842414192u, 1436424174966147016u }, { 3051205717303017741u, 1795530218707683770u }, - { 13037379183483547984u, 2244412773384604712u }, { 8148361989677217490u, 1402757983365377945u }, - { 14797138505523909766u, 1753447479206722431u }, { 13884737113477499304u, 2191809349008403039u }, - { 15595489723564518921u, 1369880843130251899u }, { 14882676136028260747u, 1712351053912814874u }, - { 9379973133180550126u, 2140438817391018593u }, { 17391698254306313589u, 1337774260869386620u }, - { 3292878744173340370u, 1672217826086733276u }, { 4116098430216675462u, 2090272282608416595u }, - { 266718509671728212u, 1306420176630260372u }, { 333398137089660265u, 1633025220787825465u }, - { 5028433689789463235u, 2041281525984781831u }, { 10060300083759496378u, 1275800953740488644u }, - { 12575375104699370472u, 1594751192175610805u }, { 1884160825592049379u, 1993438990219513507u }, - { 17318501580490888525u, 1245899368887195941u }, { 7813068920331446945u, 1557374211108994927u }, - { 5154650131986920777u, 1946717763886243659u }, { 915813323278131534u, 1216698602428902287u }, - { 14979824709379828129u, 1520873253036127858u }, { 9501408849870009354u, 1901091566295159823u }, - { 12855909558809837702u, 1188182228934474889u }, { 2234828893230133415u, 1485227786168093612u }, - { 2793536116537666769u, 1856534732710117015u }, { 8663489100477123587u, 1160334207943823134u }, - { 1605989338741628675u, 1450417759929778918u }, { 11230858710281811652u, 1813022199912223647u }, - { 9426887369424876662u, 2266277749890279559u }, { 12809333633531629769u, 1416423593681424724u }, - { 16011667041914537212u, 1770529492101780905u }, { 6179525747111007803u, 2213161865127226132u }, - { 13085575628799155685u, 1383226165704516332u }, { 16356969535998944606u, 1729032707130645415u }, - { 15834525901571292854u, 2161290883913306769u }, { 2979049660840976177u, 1350806802445816731u }, - { 17558870131333383934u, 1688508503057270913u }, { 8113529608884566205u, 2110635628821588642u }, - { 9682642023980241782u, 1319147268013492901u }, { 16714988548402690132u, 1648934085016866126u }, - { 11670363648648586857u, 2061167606271082658u }, { 11905663298832754689u, 1288229753919426661u }, - { 1047021068258779650u, 1610287192399283327u }, { 15143834390605638274u, 2012858990499104158u }, - { 4853210475701136017u, 1258036869061940099u }, { 1454827076199032118u, 1572546086327425124u }, - { 1818533845248790147u, 1965682607909281405u }, { 3442426662494187794u, 1228551629943300878u }, - { 13526405364972510550u, 1535689537429126097u }, { 3072948650933474476u, 1919611921786407622u }, - { 15755650962115585259u, 1199757451116504763u }, { 15082877684217093670u, 1499696813895630954u }, - { 9630225068416591280u, 1874621017369538693u }, { 8324733676974063502u, 1171638135855961683u }, - { 5794231077790191473u, 1464547669819952104u }, { 7242788847237739342u, 1830684587274940130u }, - { 18276858095901949986u, 2288355734093675162u }, { 16034722328366106645u, 1430222333808546976u }, - { 1596658836748081690u, 1787777917260683721u }, { 6607509564362490017u, 2234722396575854651u }, - { 1823850468512862308u, 1396701497859909157u }, { 6891499104068465790u, 1745876872324886446u }, - { 17837745916940358045u, 2182346090406108057u }, { 4231062170446641922u, 1363966306503817536u }, - { 5288827713058302403u, 1704957883129771920u }, { 6611034641322878003u, 2131197353912214900u }, - { 13355268687681574560u, 1331998346195134312u }, { 16694085859601968200u, 1664997932743917890u }, - { 11644235287647684442u, 2081247415929897363u }, { 4971804045566108824u, 1300779634956185852u }, - { 6214755056957636030u, 1625974543695232315u }, { 3156757802769657134u, 2032468179619040394u }, - { 6584659645158423613u, 1270292612261900246u }, { 17454196593302805324u, 1587865765327375307u }, - { 17206059723201118751u, 1984832206659219134u }, { 6142101308573311315u, 1240520129162011959u }, - { 3065940617289251240u, 1550650161452514949u }, { 8444111790038951954u, 1938312701815643686u }, - { 665883850346957067u, 1211445438634777304u }, { 832354812933696334u, 1514306798293471630u }, - { 10263815553021896226u, 1892883497866839537u }, { 17944099766707154901u, 1183052186166774710u }, - { 13206752671529167818u, 1478815232708468388u }, { 16508440839411459773u, 1848519040885585485u }, - { 12623618533845856310u, 1155324400553490928u }, { 15779523167307320387u, 1444155500691863660u }, - { 1277659885424598868u, 1805194375864829576u }, { 1597074856780748586u, 2256492969831036970u }, - { 5609857803915355770u, 1410308106144398106u }, { 16235694291748970521u, 1762885132680497632u }, - { 1847873790976661535u, 2203606415850622041u }, { 12684136165428883219u, 1377254009906638775u }, - { 11243484188358716120u, 1721567512383298469u }, { 219297180166231438u, 2151959390479123087u }, - { 7054589765244976505u, 1344974619049451929u }, { 13429923224983608535u, 1681218273811814911u }, - { 12175718012802122765u, 2101522842264768639u }, { 14527352785642408584u, 1313451776415480399u }, - { 13547504963625622826u, 1641814720519350499u }, { 12322695186104640628u, 2052268400649188124u }, - { 16925056528170176201u, 1282667750405742577u }, { 7321262604930556539u, 1603334688007178222u }, - { 18374950293017971482u, 2004168360008972777u }, { 4566814905495150320u, 1252605225005607986u }, - { 14931890668723713708u, 1565756531257009982u }, { 9441491299049866327u, 1957195664071262478u }, - { 1289246043478778550u, 1223247290044539049u }, { 6223243572775861092u, 1529059112555673811u }, - { 3167368447542438461u, 1911323890694592264u }, { 1979605279714024038u, 1194577431684120165u }, - { 7086192618069917952u, 1493221789605150206u }, { 18081112809442173248u, 1866527237006437757u }, - { 13606538515115052232u, 1166579523129023598u }, { 7784801107039039482u, 1458224403911279498u }, - { 507629346944023544u, 1822780504889099373u }, { 5246222702107417334u, 2278475631111374216u }, - { 3278889188817135834u, 1424047269444608885u }, { 8710297504448807696u, 1780059086805761106u } -}; - -#endif // RYU_D2S_FULL_TABLE_H diff --git a/src/conv/digits.c b/src/conv/digits.c deleted file mode 100644 index bf75aa0..0000000 --- a/src/conv/digits.c +++ /dev/null @@ -1,48 +0,0 @@ - -static inline bool isbase(int c, int base) { - int val = 0; - if(isdigit(c)) { - val = c-'0'; - } - else if(islower(c)) { - val = c-'a'+10; - } - else if(isupper(c)) { - val = c-'A'+10; - } - else { - return false; - } - return val < base; -} - -static inline intl todigit(int c) { - int val = 0; - if(isdigit(c)) { - val = c-'0'; - } - else if(islower(c)) { - val = c-'a'+10; - } - else if(isupper(c)) { - val = c-'A'+10; - } - return val; -} - -static inline int fromdigit(int digit, int upper) { - int ch; - if(digit < 10) { - ch = digit+'0'; - } - else { - if(upper) { - ch = digit-10+'A'; - } - else { - ch = digit-10+'a'; - } - } - return ch; -} - diff --git a/src/conv/float.c b/src/conv/float.c deleted file mode 100644 index f0e1b7b..0000000 --- a/src/conv/float.c +++ /dev/null @@ -1,130 +0,0 @@ - - -static f64 strtod_generic(const char *restrict nptr, char **restrict endptr) { - const char *restrict str = nptr; - bool conv_performed = false; - f64 value = 0.0; - f64 coef = 1.0; - // Skip space on the beginning - while(isspace(*str)) { - ++str; - } - // Check for inf and nan - if(strpfx_i(str, "INF")) { - str += sizeof "INF"-1; - value = HUGE_VAL; - conv_performed = true; - goto finish; - } - if(strpfx_i(str, "INFINITY")) { - str += sizeof "INFINITY"-1; - value = HUGE_VAL; - conv_performed = true; - goto finish; - } - if(strpfx_i(str, "NAN")) { - str += sizeof "NAN"-1; - value = NAN; - conv_performed = true; - if(*str == '(') { - while(*str != ')') { - ++str; - } - ++str; - } - goto finish; - } - // Parse C float - if(*str == '+') { - ++str; - } - else if(*str == '-') { - coef = -1.; - ++str; - } - int base = 10; - if(strpfx_i(str, "0X")) { - str += sizeof "0X"-1; - base = 16; - } - // Parse the whole part - while(isbase(*str, base)) { - long digit = todigit(*str); - value = 10.0*value + (f64)digit; - ++str; - } - if(*str != '.') { - value = 0.0; - goto finish; - } - ++str; - // Parse the fractional part - long exp = 1; - while(isbase(*str, base)) { - long digit = todigit(*str); - f64 fract = (f64)digit; - long cexp = exp; - while(cexp-- != 0) { - fract /= (f64)base; - } - value += fract; - ++exp; - ++str; - } - // Parse the exponent - if((base == 10 && strpfx_i(str, "E")) - || (base == 16 && strpfx_i(str, "P"))) - { - ++str; - long exp = 0; - long exp_coef = 1; - if(*str == '+') { - ++str; - } - else if(*str == '-') { - exp_coef = -1; - ++str; - } - while(isdigit(*str)) { - exp = 10*exp + (long)(*str-'0'); - ++str; - } - if(exp_coef == 1) { - while(exp--!=0) value = value * base; - } - else if(exp_coef == -1) { - while(exp--!=0) value = value / base; - } - } - if(!isfinite(value)) { - errno = ERANGE; - value = coef*HUGE_VAL; - } - conv_performed = true; - finish: - if(endptr != NULL) { - if(conv_performed) { - *endptr = (char *)str; - } - else { - *endptr = (char *)nptr; - } - } - return coef*value; -} - -f64 strtod(const char *restrict nptr, char **restrict endptr) { - return strtod_generic(nptr, endptr); -} - -f32 strtof(const char *restrict nptr, char **restrict endptr) { - return (f32)strtod_generic(nptr, endptr); -} - -fl64 strtold(const char *restrict nptr, char **restrict endptr) { - return (fl64)strtod_generic(nptr, endptr); -} - -f64 atof(const char *nptr) { - return strtod(nptr, (char **)NULL); -} diff --git a/src/conv/int.c b/src/conv/int.c deleted file mode 100644 index 05afcc8..0000000 --- a/src/conv/int.c +++ /dev/null @@ -1,169 +0,0 @@ - -static intull strtoi_generic(const char *restrict nptr, - char **restrict endptr, - int inbase, - intl *coefptr, - intull int_max) { - const char *restrict str = nptr; - intull value = 0; - int digits_read = 0; - bool is_signed = (coefptr != NULL); - intl coef = 1; - // Find max{abs(int)}. Signed integers have negative, - // whose absolute value is 1 bigger than int_max. - intull int_abs_max = int_max; - if(is_signed) { - ++int_abs_max; - } - if(!IN_RANGE(0, inbase, 36)) { - goto finish; - } - intull base = (intull)inbase; - // Skip space on the beginning - while(isspace(*str)) { - ++str; - } - // Parse sign - if(is_signed) { - if(*str == '-') { - coef = -1; - ++str; - } - } - if(*str == '+') { - ++str; - } - // See if we need to parse base in C-like format - // then set the base accordingly - if(strpfx_i(str, "0X")) { - ++str; - if(base == 16 || base == 0) { - ++str; - base = 16; - } - else { - goto finish; - } - } - else if(*str == '0') { - ++str; - ++digits_read; - if(base == 8 || base == 0) { - base = 8; - } - } - // Parse the string of digits in the given base. If the value - // exceeds abs(int_min) we exit with range error. - while(isbase(*str, (int)base)) { - intull digit = (intull)todigit(*str); - if(value > (int_abs_max - digit)/base) { - goto error_out_of_range; - } - value = base*value + digit; - ++str; - ++digits_read; - } - // We only allow the modulo of value equal to abs(int_min) if it is - // preceeded by the minus sign. - if(is_signed) { - if(value == int_abs_max && coef != -1) { - goto error_out_of_range; - } - } - goto finish; - error_out_of_range: - // Skip the remainder of the subject string - while(isbase(*str, (int)base)) { - ++str; - } - errno = ERANGE; - value = int_max; - goto finish; - finish:; - // If no conversion is performed we return the value of 0 and *endptr - // is set to the nptr. - bool conv_performed = (digits_read > 0); - if(!conv_performed) { - value = 0; - } - if(endptr != NULL) { - if(!conv_performed) { - *endptr = (char *)nptr; - } - else { - *endptr = (char *)str; - } - } - *coefptr = coef; - return value; -} - -intl strtol(const char *restrict nptr, char **restrict endptr, int base) { - intull int_max = (intull)LONG_MAX; - intl coef; - intull modulo = strtoi_generic(nptr, endptr, base, &coef, int_max); - intl value; - if(modulo == int_max) { - value = LONG_MIN; - } - else { - value = coef * (intl)modulo; - } - return value; -} - -intll strtoll(const char *restrict nptr, char **restrict endptr, int base) { - intull int_max = (intull)LLONG_MAX; - intl coef; - intull modulo = strtoi_generic(nptr, endptr, base, &coef, int_max); - intll value; - if(modulo == int_max) { - value = LLONG_MIN; - } - else { - value = (intll)coef * (intll)modulo; - } - return value; -} - -intul strtoul(const char *restrict nptr, char **restrict endptr, int base) { - intull int_max = (intull)ULONG_MAX; - intull value = strtoi_generic(nptr, endptr, base, NULL, int_max); - return (intul)value; -} - -intull strtoull(const char *restrict nptr, char **restrict endptr, int base) { - intull int_max = (intull)ULLONG_MAX; - return strtoi_generic(nptr, endptr, base, NULL, int_max); -} - -int atoi(const char *nptr) { - return (int)strtol(nptr, (char **)NULL, 10); -} - -long int atol(const char *nptr) { - return strtol(nptr, (char **)NULL, 10); -} - -long long int atoll(const char *nptr) { - return strtoll(nptr, (char **)NULL, 10); -} - -char *itoa(int value, char *str, int base) { - int sign = 0; - if(value < 0) { - sign = 1; - value = -value; - } - char buf[20] = {0}; - char *bufp = buf + sizeof buf - 1; - do { - *--bufp = value%base+'0'; - value /= base; - } while(value != 0); - if(sign) { - *--bufp = '-'; - } - strcpy(str, bufp); - return str; -} diff --git a/src/conv/strpfx.c b/src/conv/strpfx.c deleted file mode 100644 index b15a454..0000000 --- a/src/conv/strpfx.c +++ /dev/null @@ -1,10 +0,0 @@ - -static bool strpfx_i(char const *restrict str, char const *restrict prefix) { - while(*prefix != 0) { - if(*str == 0) break; - if(toupper(*str) != toupper(*prefix)) return false; - ++prefix; - ++str; - } - return true; -} diff --git a/src/ctype.c b/src/ctype.c deleted file mode 100644 index a6da3bd..0000000 --- a/src/ctype.c +++ /dev/null @@ -1,67 +0,0 @@ - -int isalnum(int c) { - return isalpha(c) || isdigit(c); -} - -int isalpha(int c) { - return islower(c) || isupper(c); -} - -int isblank(int c) { - return c == ' ' || c == '\t'; -} - -int iscntrl(int c) { - return IN_RANGE('\x00', c, '\x1f') || c == '\x7f'; -} - -int isdigit(int c) { - return IN_RANGE('0', c, '9'); -} - -int isgraph(int c) { - return isprint(c) && (c != ' '); -} - -int islower(int c) { - return IN_RANGE('a', c, 'z'); -} - -int isprint(int c) { - return IN_RANGE(' ', c, '\x7e'); -} - -int ispunct(int c) { - return IN_RANGE('\x21', c, '\x2f') - || IN_RANGE('\x3a', c, '\x40') - || IN_RANGE('\x5b', c, '\x60') - || IN_RANGE('\x7b', c, '\x7e'); -} - -int isspace(int c) { - return IN_RANGE('\x09', c, '\x0d') || c == ' '; -} - -int isupper(int c) { - return IN_RANGE('A', c, 'Z'); -} - -int isxdigit(int c) { - return IN_RANGE('0', c, '9') - || IN_RANGE('a', c, 'f') - || IN_RANGE('A', c, 'F'); -} - -int tolower(int c) { - if(isupper(c)) { - return c-'A'+'a'; - } - return c; -} - -int toupper(int c) { - if(islower(c)) { - return c-'a'+'A'; - } - return c; -} diff --git a/src/errno.c b/src/errno.c deleted file mode 100644 index aaf3d41..0000000 --- a/src/errno.c +++ /dev/null @@ -1,2 +0,0 @@ - -_Thread_local int errno; diff --git a/src/fenv.c b/src/fenv.c deleted file mode 100644 index 990f4da..0000000 --- a/src/fenv.c +++ /dev/null @@ -1,121 +0,0 @@ - -#define fe_masks(excepts) (((fexcept_t)(excepts)) << 7) -#define fe_flags(excepts) ((fexcept_t)(excepts)) -#define fe_excepts(masks) ((int)(masks >> 7)) - -fenv_t _fe_dfl_env = 0x1f80; - -int feclearexcept(int excepts) { - if((excepts & FE_ALL_EXCEPT) != excepts) { - return 1; - } - if(excepts == 0) { - return 0; - } - fexcept_t csr = _mm_getcsr(); - csr &= ~fe_flags(excepts); - _mm_setcsr(csr); - return 0; -} - -int fegetexceptflag(fexcept_t *flagp, int excepts) { - if((excepts & FE_ALL_EXCEPT) != excepts) { - return 1; - } - *flagp = fe_flags(excepts); - return 0; -} - -int feraiseexcept(int excepts) { - if((excepts & FE_ALL_EXCEPT) != excepts) { - return 1; - } - if(excepts == 0) { - return 0; - } - fexcept_t csr = _mm_getcsr(); - csr |= fe_flags(excepts); - _mm_setcsr(csr); - return 0; -} - -int fesetexceptflag(const fexcept_t *flagp, int excepts) { - if((excepts & FE_ALL_EXCEPT) != excepts) { - return 1; - } - if(excepts == 0) { - return 0; - } - fexcept_t flags = *flagp; - fexcept_t csr = _mm_getcsr(); - csr |= flags; - _mm_setcsr(csr); - return 0; -} - -int fetestexcept(int excepts) { - fexcept_t csr = _mm_getcsr(); - fexcept_t flags = fe_flags(excepts); - return (int)(csr & flags); -} - -int fegetround(void) { - fexcept_t csr = _mm_getcsr(); - int round = (csr >> 13) & 0x3; - return round; -} - -int fesetround(int round) { - if(!(0 <= round && round < 4)) { - return 1; - } - fexcept_t csr = _mm_getcsr(); - csr &= ~(0x3 << 13); - csr |= round << 13; - _mm_setcsr(csr); - return 0; -} - -int fegetenv(fenv_t *env) { - fenv_t csr = _mm_getcsr(); - *env = csr; - return 0; -} - -int fesetenv(fenv_t *env) { - _mm_setcsr(*env); - return 1; -} - -int feholdexcept(fenv_t *envp) { - fegetenv(envp); - feclearexcept(FE_ALL_EXCEPT); - return 0; -} - -int feupdateenv(fenv_t const *envp) { - int excepts = _mm_getcsr() & FE_ALL_EXCEPT; - _mm_setcsr(*envp); - feraiseexcept(excepts); - return 0; -} - -int _feenabletraps(int excepts) { - if((excepts & FE_ALL_EXCEPT) != excepts) { - return 1; - } - fexcept_t csr = _mm_getcsr(); - csr &= ~fe_masks(excepts); - _mm_setcsr(csr); - return 0; -} - -int _fedisabletraps(int excepts) { - if((excepts & FE_ALL_EXCEPT) != excepts) { - return 1; - } - fexcept_t csr = _mm_getcsr(); - csr |= fe_masks(excepts); - _mm_setcsr(csr); - return 0; -} diff --git a/src/linux/crt_ctors.c b/src/linux/crt_ctors.c new file mode 100644 index 0000000..974e521 --- /dev/null +++ b/src/linux/crt_ctors.c @@ -0,0 +1,32 @@ + +#include + +// NOTE: These symbols are provided by the linker +#define attribute_hidden __attribute__((__visibility__("hidden"))) +extern void (*__preinit_array_start []) (int, char **, char **) attribute_hidden; +extern void (*__preinit_array_end []) (int, char **, char **) attribute_hidden; +extern void (*__init_array_start []) (int, char **, char **) attribute_hidden; +extern void (*__init_array_end []) (int, char **, char **) attribute_hidden; +extern void (*__fini_array_start []) (void) attribute_hidden; +extern void (*__fini_array_end []) (void) attribute_hidden; + +// extern void _init(); +// extern void _fini(); + +// These will be called by __libc_start_main +void __libc_global_init(int argc, char **argv, char **envp) { + // _init(); + u64 size = (u64)__init_array_end - (u64)__init_array_start; + for(u64 i = 0; i != size; ++i) { + (*__init_array_start[i])(argc, argv, envp); + } +} + +void __libc_global_fini(int argc, char **argv, char **envp) { + u64 size = (u64)__fini_array_end - (u64)__fini_array_start; + u64 i = size; + while(i-- > 0) { + (*__fini_array_start[i])(); + } + // _fini(); +} diff --git a/src/linux/crt_entry.asm b/src/linux/crt_entry.asm new file mode 100644 index 0000000..530c357 --- /dev/null +++ b/src/linux/crt_entry.asm @@ -0,0 +1,39 @@ + +bits 64 + +section .text + +global _start +; global _init +; global _fini +extern __libc_global_fini +extern __libc_global_init +extern __libc_start_main +extern main + +; _init: +; push ebp +; mov ebp, esp +; _fini: + +_start: + xor ebp, ebp + ;; Save rtld_fini address to r9 + mov r9, rdx + ;; Get argc and argv from the stack + pop rsi + mov rdx, qword [rsp] + ;; Align stack to 16, push junk and stack ptr + and rsi, ~0xf + push rax + push rsp + ;; Push fini and init sections + mov rcx, __libc_global_init wrt ..got + mov r8, __libc_global_fini wrt ..got + mov rdi, main + ;; Call start main + call __libc_start_main wrt ..plt + ;; No idea why halt it, I guess that's a funny + ;; way to crash your application if the function we called + ;; returns instead of calling the exit syscall + hlt diff --git a/src/linux/entry.c b/src/linux/entry.c new file mode 100644 index 0000000..3295a0e --- /dev/null +++ b/src/linux/entry.c @@ -0,0 +1,11 @@ + +void __libc_start_main( + int (*main)(int, char**, char**), + int argc, char **argv, + int (*init)(int, char**, char**), + void (*fini)(void), + void (*rtld_fini)(void), + void *stack_end +) { + syscall_exit(0); +} diff --git a/src/linux/syscall.c b/src/linux/syscall.c new file mode 100644 index 0000000..1133361 --- /dev/null +++ b/src/linux/syscall.c @@ -0,0 +1,137 @@ + +#if os_is_linux() + +#define SYS_read 0 +#define SYS_write 1 +#define SYS_open 2 +#define SYS_close 3 +#define SYS_stat 4 +#define SYS_fstat 5 +#define SYS_lstat 6 +#define SYS_poll 7 +#define SYS_lseek 8 +#define SYS_mmap 9 +#define SYS_mprotect 10 +#define SYS_munmap 11 +#define SYS_brk 12 +#define SYS_rt_sigaction 13 +#define SYS_rt_sigprocmask 14 +#define SYS_rt_sigreturn 15 +#define SYS_ioctl 16 +#define SYS_pread64 17 +#define SYS_pwrite64 18 +#define SYS_readv 19 +#define SYS_writev 20 +#define SYS_access 21 +#define SYS_pipe 22 +#define SYS_select 23 +#define SYS_sched_yield 24 +#define SYS_mremap 25 +#define SYS_msync 26 +#define SYS_mincore 27 +#define SYS_madvise 28 +#define SYS_shmget 29 +#define SYS_shmat 30 +#define SYS_shmctl 31 +#define SYS_dup 32 +#define SYS_dup2 33 +#define SYS_pause 34 +#define SYS_nanosleep 35 +#define SYS_getitimer 36 +#define SYS_alarm 37 +#define SYS_setitimer 38 +#define SYS_getpid 39 +#define SYS_sendfile 40 +#define SYS_socket 41 +#define SYS_connect 42 +#define SYS_accept 43 +#define SYS_sendto 44 +#define SYS_recvfrom 45 +#define SYS_sendmsg 46 +#define SYS_recvmsg 47 +#define SYS_shutdown 48 +#define SYS_bind 49 +#define SYS_listen 50 +#define SYS_getsockname 51 +#define SYS_getpeername 52 +#define SYS_socketpair 53 +#define SYS_setsockopt 54 +#define SYS_getsockopt 55 +#define SYS_clone 56 +#define SYS_fork 57 +#define SYS_vfork 58 +#define SYS_execve 59 +#define SYS_exit 60 + +// Syscall stubs + +static __inline i64 __syscall0(i64 n) { + i64 ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n) : "rcx", "r11", "memory"); + return ret; +} + +static __inline i64 __syscall1(i64 n, i64 a1) { + i64 ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "rcx", "r11", "memory"); + return ret; +} + +static __inline i64 __syscall2(i64 n, i64 a1, i64 a2) { + i64 ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2) + : "rcx", "r11", "memory"); + return ret; +} + +static __inline i64 __syscall3(i64 n, i64 a1, i64 a2, i64 a3) { + i64 ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3) : "rcx", "r11", "memory"); + return ret; +} + +static __inline i64 __syscall4(i64 n, i64 a1, i64 a2, i64 a3, i64 a4) { + i64 ret; + register i64 r10 __asm__("r10") = a4; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10): "rcx", "r11", "memory"); + return ret; +} + +static __inline i64 __syscall5(i64 n, i64 a1, i64 a2, i64 a3, i64 a4, i64 a5) { + i64 ret; + register i64 r10 __asm__("r10") = a4; + register i64 r8 __asm__("r8") = a5; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10), "r"(r8) : "rcx", "r11", "memory"); + return ret; +} + +static __inline i64 __syscall6(i64 n, i64 a1, i64 a2, i64 a3, i64 a4, i64 a5, i64 a6) { + i64 ret; + register i64 r10 __asm__("r10") = a4; + register i64 r8 __asm__("r8") = a5; + register i64 r9 __asm__("r9") = a6; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10), "r"(r8), "r"(r9) : "rcx", "r11", "memory"); + return ret; +} + +// Syscall wrappers + +static inline i64 syscall_read(u32 fd, char *buf, u64 count) { + return __syscall3(SYS_read, (i64)fd, (i64)buf, (i64)count); +} + +static inline i64 syscall_write(u32 fd, char const *buf, u64 count) { + return __syscall3(SYS_write, (i64)fd, (i64)buf, (u64)count); +} + +static inline i64 syscall_exit(int code) { + return __syscall1(SYS_exit, (i64)code); +} + +#else +#error "syscall.h should only be included in LINUX code" +#endif \ No newline at end of file diff --git a/src/locale.c b/src/locale.c deleted file mode 100644 index a394f4a..0000000 --- a/src/locale.c +++ /dev/null @@ -1,61 +0,0 @@ - -#define _LC_FIRST 0 -#define _LC_LAST 5 - -static struct lconv _locale; -static char _locale_str[16]; - -// Even if the user doesn't enable LIB_EXT1 we still have it existing -size_t strnlen_s(const char *s, size_t maxsize); - -char *setlocale(int category, const char *locale) { - if (_LC_FIRST <= category && category <= _LC_LAST) return NULL; - if (locale == NULL) return _locale_str; - - // Validate the string a bit - size_t locale_len = strnlen_s(locale, sizeof(_locale_str)); - if (locale_len == 0 || locale_len >= sizeof(_locale_str)) return NULL; - - if(strcmp(locale, "C") == 0) { - switch (category) { - case LC_ALL: { - _locale.decimal_point = "."; // fuck the french, the german, the russians and the rest of the wrongthinkers - _locale.thousands_sep = ""; - _locale.grouping = ""; - _locale.mon_decimal_point = ""; - _locale.mon_thousands_sep = ""; - _locale.mon_grouping = ""; - _locale.positive_sign = ""; - _locale.negative_sign = ""; - _locale.currency_symbol = ""; - _locale.frac_digits = CHAR_MAX; - _locale.p_cs_precedes = CHAR_MAX; - _locale.n_cs_precedes = CHAR_MAX; - _locale.p_sep_by_space = CHAR_MAX; - _locale.n_sep_by_space = CHAR_MAX; - _locale.p_sign_posn = CHAR_MAX; - _locale.n_sign_posn = CHAR_MAX; - _locale.int_curr_symbol = ""; - _locale.int_frac_digits = CHAR_MAX; - _locale.int_p_cs_precedes = CHAR_MAX; - _locale.int_n_cs_precedes = CHAR_MAX; - _locale.int_p_sep_by_space = CHAR_MAX; - _locale.int_n_sep_by_space = CHAR_MAX; - _locale.int_p_sign_posn = CHAR_MAX; - _locale.int_n_sign_posn = CHAR_MAX; - break; - } - - default: return NULL; - } - } else { - return NULL; - } - - memcpy(_locale_str, locale, locale_len); - return _locale_str; -} - -struct lconv *localeconv(void) { - return &_locale; -} diff --git a/src/math/basic.c b/src/math/basic.c deleted file mode 100644 index 8f6cd31..0000000 --- a/src/math/basic.c +++ /dev/null @@ -1,140 +0,0 @@ - -double fabs(double x) { - union {double f; uint64_t i;} u = {x}; - u.i &= -1ULL/2; - return u.f; -} - -float fabsf(float x) { - union {float f; uint32_t i;} u = {x}; - u.i &= 0x7fffffff; - return u.f; -} - -long double fabsl(long double x) { - return fabs(x); -} - -double fdim(double x, double y) { - if (isnan(x)) return x; - if (isnan(y)) return y; - return x > y ? x - y : 0; -} - -float fdimf(float x, float y) { - if (isnan(x)) return x; - if (isnan(y)) return y; - return x > y ? x - y : 0; -} - -long double fdiml(long double x, long double y) { - return fdim(x, y); -} - -double fmax(double x, double y) { - if (isnan(x)) return y; - if (isnan(y)) return x; - /* handle signed zeros, see C99 Annex F.9.9.2 */ - if (signbit(x) != signbit(y)) - return signbit(x) ? y : x; - return x < y ? y : x; -} - -float fmaxf(float x, float y) { - if (isnan(x)) return y; - if (isnan(y)) return x; - /* handle signed zeroes, see C99 Annex F.9.9.2 */ - if (signbit(x) != signbit(y)) - return signbit(x) ? y : x; - return x < y ? y : x; -} - -long double fmaxl(long double x, long double y) { - return fmax(x, y); -} - -double fmin(double x, double y) { - if (isnan(x)) return y; - if (isnan(y)) return x; - /* handle signed zeros, see C99 Annex F.9.9.2 */ - if (signbit(x) != signbit(y)) - return signbit(x) ? x : y; - return x < y ? x : y; -} - -float fminf(float x, float y) { - if (isnan(x)) return y; - if (isnan(y)) return x; - /* handle signed zeros, see C99 Annex F.9.9.2 */ - if (signbit(x) != signbit(y)) - return signbit(x) ? x : y; - return x < y ? x : y; -} - -long double fminl(long double x, long double y) { - return fmin(x, y); -} - -#ifdef __CUIK__ -#warning "Cuik doesn't support the FMA intrinsics... fix that NeGate" -double fma(double x, double y, double z) { - return (x * y) + z; -} - -float fmaf(float x, float y, float z) { - return (x * y) + z; -} - -long double fmal(long double x, long double y, long double z) { - return (x * y) + z; -} - -double sqrt(double x) { - return 0.0; -} - -float sqrtf(float x) { - return 0.0; -} -#else -double fma(double x, double y, double z) { - __m128d xd = _mm_set_sd(x); - __m128d yd = _mm_set_sd(y); - __m128d zd = _mm_set_sd(z); - __m128d rd = _mm_fmadd_sd(xd, yd, zd); - double res = _mm_cvtsd_f64(rd); - return res; -} - -float fmaf(float x, float y, float z) { - __m128 xd = _mm_set_ss(x); - __m128 yd = _mm_set_ss(y); - __m128 zd = _mm_set_ss(z); - __m128 rd = _mm_fmadd_ss(xd, yd, zd); - float res = _mm_cvtss_f32(rd); - return res; -} - -long double fmal(long double x, long double y, long double z) { - return fma(x, y, z); -} - -double sqrt(double x) { - __m128d xd = _mm_set_sd(x); - __m128d yd = _mm_set_sd(0); - __m128d rd = _mm_sqrt_sd(xd, yd); - double res = _mm_cvtsd_f64(rd); - return res; -} - -float sqrtf(float x) { - __m128 xd = _mm_set_ss(x); - __m128 rd = _mm_sqrt_ss(xd); - float res = _mm_cvtss_f32(rd); - return res; -} - -long double sqrtl(long double x) { - return sqrt(x); -} -#endif diff --git a/src/math/bits.c b/src/math/bits.c deleted file mode 100644 index c399c59..0000000 --- a/src/math/bits.c +++ /dev/null @@ -1,100 +0,0 @@ - -// This thing doesn't compile branchlessly on MSVC lmao -// This is a branchless version of fpclassify -// The way it works is by assuming the following structure of float class -// bit 2 | bit 1 | bit 0 -// e n m -// e is 1 for infinities and nan, 0 otherwise -// n is 1 for normal numbers, 0 otherwise -// m is 1 for nan and subnormal numbers, 0 otherwise -// This leaves the following values for classes: -// 0 - FP_ZERO -// 1 - FP_SUBNORMAL -// 2 - FP_NORMAL -// 4 - FP_INFINITE -// 5 - FP_NAN -int _fpclassify(f64 x) { - // First, extract bits - u64 bits = F64_BITS(x); - i64 exp = F64_BEXP(bits); - i64 mant = F64_MANT(bits); - // Get the number that's only zero when exp = 0x7ff - i64 ee = F64_BEXP_MAX - exp; - // Invert it to get number that's 1 iff x is infinity or nan - i64 e = !(ee); - // The value (ee*exp) is zero in two cases: - // exp = 0x7ff, (infinities, nan) - // exp = 0 (zero, subnormal) - // We negate this to make it so that this value is 1 only if number is not - // normal - i64 nn = !(ee*exp); - // Negate the previous thing. Now n is 1 iff number is normal - i64 n = !nn; - // m is 1 if mantissa is nonzero and the number is not normal - i64 m = !!mant & nn; - // Construct the float class - return (e<<2) | (n<<1) | m; -} - -// Same recipe as above, different constants -int _fpclassifyf(float x) { - u64 bits = F32_BITS(x); - i64 exp = F32_BEXP(bits); - i64 mant = F32_MANT(bits); - i64 ee = F32_BEXP_MAX - exp; - i64 e = !(ee); - i64 nn = !(ee*exp); - i64 n = !nn; - i64 m = !!mant & nn; - return (e<<2) | (n<<1) | m; -} - -int _fpclassifyl(fl64 x) { - return _fpclassify((f64)x); -} - - -int _signbit(f64 x) { - return F64_BITS(x)>>63; -} - -int _signbitf(float x) { - return F32_BITS(x)>>31; -} - -int _signbitl(fl64 x) { - return _signbit((f64)x); -} - -f64 copysign(f64 x, f64 y) { - u64 xbits = F64_BITS(x); - u64 ybits = F64_BITS(y); - xbits &= ~(UINT64_C(1)<<63); - xbits |= ybits & (UINT64_C(1)<<63); - return F64_CONS(xbits); -} - -float copysignf(float x, float y) { - u32 xbits = F32_BITS(x); - u32 ybits = F32_BITS(y); - xbits &= ~(UINT32_C(1)<<31); - xbits |= ybits & (1u<<31); - return F64_CONS(xbits); -} - -fl64 copysignl(fl64 x, fl64 y) { - return copysign((f64)x, (f64)y); -} - -f64 nan(const char *s) { - return NAN; -} - -float nanf(const char *s) { - return NAN; -} - -fl64 nanl(const char *s) { - return NAN; -} - diff --git a/src/math/cordic/cordic_data.h b/src/math/cordic/cordic_data.h deleted file mode 100644 index a208623..0000000 --- a/src/math/cordic/cordic_data.h +++ /dev/null @@ -1,202 +0,0 @@ -double tK = 0x1.b7b2b62cef828p-1; - -double hK = 0x1.a2166ada47ca4p-1; - -double ttable[] = { - 0x1.dac670561bb4fp-2, - 0x1.f5b75f92c80ddp-3, - 0x1.fd5ba9aac2f6ep-4, - 0x1.ff55bb72cfdeap-5, - 0x1.ffd55bba97625p-6, - 0x1.fff555bbb729bp-7, - 0x1.fffd555bbba97p-8, - 0x1.ffff5555bbbb7p-9, - 0x1.ffffd5555bbbcp-10, - 0x1.fffff55555bbcp-11, - 0x1.fffffd55555bcp-12, - 0x1.ffffff555555cp-13, - 0x1.ffffffd555556p-14, - 0x1.fffffff555555p-15, - 0x1.fffffffd55555p-16, - 0x1.ffffffff55555p-17, - 0x1.ffffffffd5555p-18, - 0x1.fffffffff5555p-19, - 0x1.fffffffffd555p-20, - 0x1.ffffffffff555p-21, - 0x1.ffffffffffd55p-22, - 0x1.fffffffffff55p-23, - 0x1.fffffffffffd5p-24, - 0x1.ffffffffffff5p-25, - 0x1.ffffffffffffdp-26, - 0x1.fffffffffffffp-27, - 0x1.0000000000000p-27, - 0x1.0000000000000p-28, - 0x1.0000000000000p-29, - 0x1.0000000000000p-30, - 0x1.0000000000000p-31, - 0x1.0000000000000p-32, - 0x1.0000000000000p-33, - 0x1.0000000000000p-34, - 0x1.0000000000000p-35, - 0x1.0000000000000p-36, - 0x1.0000000000000p-37, - 0x1.0000000000000p-38, - 0x1.0000000000000p-39, - 0x1.0000000000000p-40, - 0x1.0000000000000p-41, - 0x1.0000000000000p-42, - 0x1.0000000000000p-43, - 0x1.0000000000000p-44, - 0x1.0000000000000p-45, - 0x1.0000000000000p-46, - 0x1.0000000000000p-47, - 0x1.0000000000000p-48, - 0x1.0000000000000p-49, - 0x1.0000000000000p-50, - 0x1.0000000000000p-51, - 0x1.0000000000000p-52, - 0x1.0000000000000p-53, - 0x1.0000000000000p-54, - 0x1.0000000000000p-55, - 0x1.0000000000000p-56, - 0x1.0000000000000p-57, - 0x1.0000000000000p-58, - 0x1.0000000000000p-59, - 0x1.0000000000000p-60, - 0x1.0000000000000p-61, - 0x1.0000000000000p-62, - 0x1.0000000000000p-63, -}; - -double htable[] = { - 0x1.193ea7aad030bp-1, - 0x1.058aefa811452p-2, - 0x1.015891c9eaef8p-3, - 0x1.005588ad375adp-4, - 0x1.001558891aee2p-5, - 0x1.000555888ad1dp-6, - 0x1.000155588891bp-7, - 0x1.000055558888bp-8, - 0x1.0000155558889p-9, - 0x1.0000055555889p-10, - 0x1.0000015555589p-11, - 0x1.0000005555559p-12, - 0x1.0000001555556p-13, - 0x1.0000000555555p-14, - 0x1.0000000155555p-15, - 0x1.0000000055555p-16, - 0x1.0000000015555p-17, - 0x1.0000000005555p-18, - 0x1.0000000001555p-19, - 0x1.0000000000555p-20, - 0x1.0000000000155p-21, - 0x1.0000000000055p-22, - 0x1.0000000000015p-23, - 0x1.0000000000005p-24, - 0x1.0000000000001p-25, - 0x1.0000000000000p-26, - 0x1.0000000000000p-27, - 0x1.0000000000000p-28, - 0x1.0000000000000p-29, - 0x1.0000000000000p-30, - 0x1.0000000000000p-31, - 0x1.0000000000000p-32, - 0x1.0000000000000p-33, - 0x1.0000000000000p-34, - 0x1.0000000000000p-35, - 0x1.0000000000000p-36, - 0x1.0000000000000p-37, - 0x1.0000000000000p-38, - 0x1.0000000000000p-39, - 0x1.0000000000000p-40, - 0x1.0000000000000p-41, - 0x1.0000000000000p-42, - 0x1.0000000000000p-43, - 0x1.0000000000000p-44, - 0x1.0000000000000p-45, - 0x1.0000000000000p-46, - 0x1.0000000000000p-47, - 0x1.0000000000000p-48, - 0x1.0000000000000p-49, - 0x1.0000000000000p-50, - 0x1.0000000000000p-51, - 0x1.0000000000000p-52, - 0x1.0000000000000p-53, - 0x1.0000000000000p-54, - 0x1.0000000000000p-55, - 0x1.0000000000000p-56, - 0x1.0000000000000p-57, - 0x1.0000000000000p-58, - 0x1.0000000000000p-59, - 0x1.0000000000000p-60, - 0x1.0000000000000p-61, - 0x1.0000000000000p-62, - 0x1.0000000000000p-63, -}; - -double ptable[] = { - 0x1.0000000000000p-1, - 0x1.0000000000000p-2, - 0x1.0000000000000p-3, - 0x1.0000000000000p-4, - 0x1.0000000000000p-5, - 0x1.0000000000000p-6, - 0x1.0000000000000p-7, - 0x1.0000000000000p-8, - 0x1.0000000000000p-9, - 0x1.0000000000000p-10, - 0x1.0000000000000p-11, - 0x1.0000000000000p-12, - 0x1.0000000000000p-13, - 0x1.0000000000000p-14, - 0x1.0000000000000p-15, - 0x1.0000000000000p-16, - 0x1.0000000000000p-17, - 0x1.0000000000000p-18, - 0x1.0000000000000p-19, - 0x1.0000000000000p-20, - 0x1.0000000000000p-21, - 0x1.0000000000000p-22, - 0x1.0000000000000p-23, - 0x1.0000000000000p-24, - 0x1.0000000000000p-25, - 0x1.0000000000000p-26, - 0x1.0000000000000p-27, - 0x1.0000000000000p-28, - 0x1.0000000000000p-29, - 0x1.0000000000000p-30, - 0x1.0000000000000p-31, - 0x1.0000000000000p-32, - 0x1.0000000000000p-33, - 0x1.0000000000000p-34, - 0x1.0000000000000p-35, - 0x1.0000000000000p-36, - 0x1.0000000000000p-37, - 0x1.0000000000000p-38, - 0x1.0000000000000p-39, - 0x1.0000000000000p-40, - 0x1.0000000000000p-41, - 0x1.0000000000000p-42, - 0x1.0000000000000p-43, - 0x1.0000000000000p-44, - 0x1.0000000000000p-45, - 0x1.0000000000000p-46, - 0x1.0000000000000p-47, - 0x1.0000000000000p-48, - 0x1.0000000000000p-49, - 0x1.0000000000000p-50, - 0x1.0000000000000p-51, - 0x1.0000000000000p-52, - 0x1.0000000000000p-53, - 0x1.0000000000000p-54, - 0x1.0000000000000p-55, - 0x1.0000000000000p-56, - 0x1.0000000000000p-57, - 0x1.0000000000000p-58, - 0x1.0000000000000p-59, - 0x1.0000000000000p-60, - 0x1.0000000000000p-61, - 0x1.0000000000000p-62, - 0x1.0000000000000p-63, -}; - diff --git a/src/math/cordic/cordic_dataf.h b/src/math/cordic/cordic_dataf.h deleted file mode 100644 index ccfa432..0000000 --- a/src/math/cordic/cordic_dataf.h +++ /dev/null @@ -1,106 +0,0 @@ -float tKf = 0x1.b7b2b62cef828p-1; - -float hKf = 0x1.a2166ada47ca4p-1; - -float ttablef[] = { - 0x1.dac670561bb4fp-2, - 0x1.f5b75f92c80ddp-3, - 0x1.fd5ba9aac2f6ep-4, - 0x1.ff55bb72cfdeap-5, - 0x1.ffd55bba97625p-6, - 0x1.fff555bbb729bp-7, - 0x1.fffd555bbba97p-8, - 0x1.ffff5555bbbb7p-9, - 0x1.ffffd5555bbbcp-10, - 0x1.fffff55555bbcp-11, - 0x1.fffffd55555bcp-12, - 0x1.ffffff555555cp-13, - 0x1.ffffffd555556p-14, - 0x1.fffffff555555p-15, - 0x1.fffffffd55555p-16, - 0x1.ffffffff55555p-17, - 0x1.ffffffffd5555p-18, - 0x1.fffffffff5555p-19, - 0x1.fffffffffd555p-20, - 0x1.ffffffffff555p-21, - 0x1.ffffffffffd55p-22, - 0x1.fffffffffff55p-23, - 0x1.fffffffffffd5p-24, - 0x1.ffffffffffff5p-25, - 0x1.ffffffffffffdp-26, - 0x1.fffffffffffffp-27, - 0x1.0000000000000p-27, - 0x1.0000000000000p-28, - 0x1.0000000000000p-29, - 0x1.0000000000000p-30, - 0x1.0000000000000p-31, -}; - -float htablef[] = { - 0x1.193ea7aad030bp-1, - 0x1.058aefa811452p-2, - 0x1.015891c9eaef8p-3, - 0x1.005588ad375adp-4, - 0x1.001558891aee2p-5, - 0x1.000555888ad1dp-6, - 0x1.000155588891bp-7, - 0x1.000055558888bp-8, - 0x1.0000155558889p-9, - 0x1.0000055555889p-10, - 0x1.0000015555589p-11, - 0x1.0000005555559p-12, - 0x1.0000001555556p-13, - 0x1.0000000555555p-14, - 0x1.0000000155555p-15, - 0x1.0000000055555p-16, - 0x1.0000000015555p-17, - 0x1.0000000005555p-18, - 0x1.0000000001555p-19, - 0x1.0000000000555p-20, - 0x1.0000000000155p-21, - 0x1.0000000000055p-22, - 0x1.0000000000015p-23, - 0x1.0000000000005p-24, - 0x1.0000000000001p-25, - 0x1.0000000000000p-26, - 0x1.0000000000000p-27, - 0x1.0000000000000p-28, - 0x1.0000000000000p-29, - 0x1.0000000000000p-30, - 0x1.0000000000000p-31, -}; - -float ptablef[] = { - 0x1.0000000000000p-1, - 0x1.0000000000000p-2, - 0x1.0000000000000p-3, - 0x1.0000000000000p-4, - 0x1.0000000000000p-5, - 0x1.0000000000000p-6, - 0x1.0000000000000p-7, - 0x1.0000000000000p-8, - 0x1.0000000000000p-9, - 0x1.0000000000000p-10, - 0x1.0000000000000p-11, - 0x1.0000000000000p-12, - 0x1.0000000000000p-13, - 0x1.0000000000000p-14, - 0x1.0000000000000p-15, - 0x1.0000000000000p-16, - 0x1.0000000000000p-17, - 0x1.0000000000000p-18, - 0x1.0000000000000p-19, - 0x1.0000000000000p-20, - 0x1.0000000000000p-21, - 0x1.0000000000000p-22, - 0x1.0000000000000p-23, - 0x1.0000000000000p-24, - 0x1.0000000000000p-25, - 0x1.0000000000000p-26, - 0x1.0000000000000p-27, - 0x1.0000000000000p-28, - 0x1.0000000000000p-29, - 0x1.0000000000000p-30, - 0x1.0000000000000p-31, -}; - diff --git a/src/math/cordic/cordic_datal.h b/src/math/cordic/cordic_datal.h deleted file mode 100644 index 7e23664..0000000 --- a/src/math/cordic/cordic_datal.h +++ /dev/null @@ -1,202 +0,0 @@ -long double tKl = 0x1.b7b2b62cef828p-1; - -long double hKl = 0x1.a2166ada47ca4p-1; - -long double ttablel[] = { - 0x1.dac670561bb4fp-2, - 0x1.f5b75f92c80ddp-3, - 0x1.fd5ba9aac2f6ep-4, - 0x1.ff55bb72cfdeap-5, - 0x1.ffd55bba97625p-6, - 0x1.fff555bbb729bp-7, - 0x1.fffd555bbba97p-8, - 0x1.ffff5555bbbb7p-9, - 0x1.ffffd5555bbbcp-10, - 0x1.fffff55555bbcp-11, - 0x1.fffffd55555bcp-12, - 0x1.ffffff555555cp-13, - 0x1.ffffffd555556p-14, - 0x1.fffffff555555p-15, - 0x1.fffffffd55555p-16, - 0x1.ffffffff55555p-17, - 0x1.ffffffffd5555p-18, - 0x1.fffffffff5555p-19, - 0x1.fffffffffd555p-20, - 0x1.ffffffffff555p-21, - 0x1.ffffffffffd55p-22, - 0x1.fffffffffff55p-23, - 0x1.fffffffffffd5p-24, - 0x1.ffffffffffff5p-25, - 0x1.ffffffffffffdp-26, - 0x1.fffffffffffffp-27, - 0x1.0000000000000p-27, - 0x1.0000000000000p-28, - 0x1.0000000000000p-29, - 0x1.0000000000000p-30, - 0x1.0000000000000p-31, - 0x1.0000000000000p-32, - 0x1.0000000000000p-33, - 0x1.0000000000000p-34, - 0x1.0000000000000p-35, - 0x1.0000000000000p-36, - 0x1.0000000000000p-37, - 0x1.0000000000000p-38, - 0x1.0000000000000p-39, - 0x1.0000000000000p-40, - 0x1.0000000000000p-41, - 0x1.0000000000000p-42, - 0x1.0000000000000p-43, - 0x1.0000000000000p-44, - 0x1.0000000000000p-45, - 0x1.0000000000000p-46, - 0x1.0000000000000p-47, - 0x1.0000000000000p-48, - 0x1.0000000000000p-49, - 0x1.0000000000000p-50, - 0x1.0000000000000p-51, - 0x1.0000000000000p-52, - 0x1.0000000000000p-53, - 0x1.0000000000000p-54, - 0x1.0000000000000p-55, - 0x1.0000000000000p-56, - 0x1.0000000000000p-57, - 0x1.0000000000000p-58, - 0x1.0000000000000p-59, - 0x1.0000000000000p-60, - 0x1.0000000000000p-61, - 0x1.0000000000000p-62, - 0x1.0000000000000p-63, -}; - -long double htablel[] = { - 0x1.193ea7aad030bp-1, - 0x1.058aefa811452p-2, - 0x1.015891c9eaef8p-3, - 0x1.005588ad375adp-4, - 0x1.001558891aee2p-5, - 0x1.000555888ad1dp-6, - 0x1.000155588891bp-7, - 0x1.000055558888bp-8, - 0x1.0000155558889p-9, - 0x1.0000055555889p-10, - 0x1.0000015555589p-11, - 0x1.0000005555559p-12, - 0x1.0000001555556p-13, - 0x1.0000000555555p-14, - 0x1.0000000155555p-15, - 0x1.0000000055555p-16, - 0x1.0000000015555p-17, - 0x1.0000000005555p-18, - 0x1.0000000001555p-19, - 0x1.0000000000555p-20, - 0x1.0000000000155p-21, - 0x1.0000000000055p-22, - 0x1.0000000000015p-23, - 0x1.0000000000005p-24, - 0x1.0000000000001p-25, - 0x1.0000000000000p-26, - 0x1.0000000000000p-27, - 0x1.0000000000000p-28, - 0x1.0000000000000p-29, - 0x1.0000000000000p-30, - 0x1.0000000000000p-31, - 0x1.0000000000000p-32, - 0x1.0000000000000p-33, - 0x1.0000000000000p-34, - 0x1.0000000000000p-35, - 0x1.0000000000000p-36, - 0x1.0000000000000p-37, - 0x1.0000000000000p-38, - 0x1.0000000000000p-39, - 0x1.0000000000000p-40, - 0x1.0000000000000p-41, - 0x1.0000000000000p-42, - 0x1.0000000000000p-43, - 0x1.0000000000000p-44, - 0x1.0000000000000p-45, - 0x1.0000000000000p-46, - 0x1.0000000000000p-47, - 0x1.0000000000000p-48, - 0x1.0000000000000p-49, - 0x1.0000000000000p-50, - 0x1.0000000000000p-51, - 0x1.0000000000000p-52, - 0x1.0000000000000p-53, - 0x1.0000000000000p-54, - 0x1.0000000000000p-55, - 0x1.0000000000000p-56, - 0x1.0000000000000p-57, - 0x1.0000000000000p-58, - 0x1.0000000000000p-59, - 0x1.0000000000000p-60, - 0x1.0000000000000p-61, - 0x1.0000000000000p-62, - 0x1.0000000000000p-63, -}; - -long double ptablel[] = { - 0x1.0000000000000p-1, - 0x1.0000000000000p-2, - 0x1.0000000000000p-3, - 0x1.0000000000000p-4, - 0x1.0000000000000p-5, - 0x1.0000000000000p-6, - 0x1.0000000000000p-7, - 0x1.0000000000000p-8, - 0x1.0000000000000p-9, - 0x1.0000000000000p-10, - 0x1.0000000000000p-11, - 0x1.0000000000000p-12, - 0x1.0000000000000p-13, - 0x1.0000000000000p-14, - 0x1.0000000000000p-15, - 0x1.0000000000000p-16, - 0x1.0000000000000p-17, - 0x1.0000000000000p-18, - 0x1.0000000000000p-19, - 0x1.0000000000000p-20, - 0x1.0000000000000p-21, - 0x1.0000000000000p-22, - 0x1.0000000000000p-23, - 0x1.0000000000000p-24, - 0x1.0000000000000p-25, - 0x1.0000000000000p-26, - 0x1.0000000000000p-27, - 0x1.0000000000000p-28, - 0x1.0000000000000p-29, - 0x1.0000000000000p-30, - 0x1.0000000000000p-31, - 0x1.0000000000000p-32, - 0x1.0000000000000p-33, - 0x1.0000000000000p-34, - 0x1.0000000000000p-35, - 0x1.0000000000000p-36, - 0x1.0000000000000p-37, - 0x1.0000000000000p-38, - 0x1.0000000000000p-39, - 0x1.0000000000000p-40, - 0x1.0000000000000p-41, - 0x1.0000000000000p-42, - 0x1.0000000000000p-43, - 0x1.0000000000000p-44, - 0x1.0000000000000p-45, - 0x1.0000000000000p-46, - 0x1.0000000000000p-47, - 0x1.0000000000000p-48, - 0x1.0000000000000p-49, - 0x1.0000000000000p-50, - 0x1.0000000000000p-51, - 0x1.0000000000000p-52, - 0x1.0000000000000p-53, - 0x1.0000000000000p-54, - 0x1.0000000000000p-55, - 0x1.0000000000000p-56, - 0x1.0000000000000p-57, - 0x1.0000000000000p-58, - 0x1.0000000000000p-59, - 0x1.0000000000000p-60, - 0x1.0000000000000p-61, - 0x1.0000000000000p-62, - 0x1.0000000000000p-63, -}; - diff --git a/src/math/cordic/maketab.py b/src/math/cordic/maketab.py deleted file mode 100644 index 055d754..0000000 --- a/src/math/cordic/maketab.py +++ /dev/null @@ -1,58 +0,0 @@ - -import math; - -import os; -import sys; - -abspath = os.path.abspath(sys.argv[0]) -dname = os.path.dirname(abspath) -os.chdir(dname) - -data=[ - ('cordic_dataf.h', 'float', 'f', 32), - ('cordic_data.h', 'double', '', 64), - ('cordic_datal.h', 'long double', 'l', 64), -] - -for f in data: - fname = f[0] - ftype = f[1] - s = f[2] - N = f[3] - - f = open(fname, 'w') - - tK = 1 - for i in range(1, N): - tK *= math.cos(math.atan(2**(-i))); - f.write(ftype + ' tK' + s + ' = ' + float.hex(tK) + ';\n') - f.write('\n') - - hK = 1 - for i in range(1, N): - hK *= math.cos(math.atanh(2**(-i))); - f.write(ftype + ' hK' + s + ' = ' + float.hex(hK) + ';\n') - f.write('\n') - - f.write(ftype + ' ttable' + s + '[] = {\n'); - for i in range(1, N): - v = math.atan(2**(-i)); - f.write(' ' + float.hex(v) + ',\n') - f.write('};\n') - f.write('\n') - - f.write(ftype + ' htable' + s + '[] = {\n'); - for i in range(1, N): - v = math.atanh(2**(-i)); - f.write(' ' + float.hex(v) + ',\n') - f.write('};\n') - f.write('\n') - - f.write(ftype + ' ptable' + s + '[] = {\n'); - for i in range(1, N): - v = 2**(-i); - f.write(' ' + float.hex(v) + ',\n') - f.write('};\n') - f.write('\n') - - f.close(); diff --git a/src/math/division.c b/src/math/division.c deleted file mode 100644 index 8932d6e..0000000 --- a/src/math/division.c +++ /dev/null @@ -1,248 +0,0 @@ - -double remquo(double x, double y, int *quo) { - union {double f; uint64_t i;} ux = {x}, uy = {y}; - int ex = ux.i>>52 & 0x7ff; - int ey = uy.i>>52 & 0x7ff; - int sx = ux.i>>63; - int sy = uy.i>>63; - uint32_t q; - uint64_t i; - uint64_t uxi = ux.i; - - *quo = 0; - if (uy.i<<1 == 0 || isnan(y) || ex == 0x7ff) - return (x*y)/(x*y); - if (ux.i<<1 == 0) - return x; - - /* normalize x and y */ - if (!ex) { - for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1); - uxi <<= -ex + 1; - } else { - uxi &= -1ULL >> 12; - uxi |= 1ULL << 52; - } - if (!ey) { - for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1); - uy.i <<= -ey + 1; - } else { - uy.i &= -1ULL >> 12; - uy.i |= 1ULL << 52; - } - - q = 0; - if (ex < ey) { - if (ex+1 == ey) - goto end; - return x; - } - - /* x mod y */ - for (; ex > ey; ex--) { - i = uxi - uy.i; - if (i >> 63 == 0) { - uxi = i; - q++; - } - uxi <<= 1; - q <<= 1; - } - i = uxi - uy.i; - if (i >> 63 == 0) { - uxi = i; - q++; - } - if (uxi == 0) - ex = -60; - else - for (; uxi>>52 == 0; uxi <<= 1, ex--); -end: - /* scale result and decide between |x| and |x|-|y| */ - if (ex > 0) { - uxi -= 1ULL << 52; - uxi |= (uint64_t)ex << 52; - } else { - uxi >>= -ex + 1; - } - ux.i = uxi; - x = ux.f; - if (sy) - y = -y; - if (ex == ey || (ex+1 == ey && (2*x > y || (2*x == y && q%2)))) { - x -= y; - q++; - } - q &= 0x7fffffff; - *quo = sx^sy ? -(int)q : (int)q; - return sx ? -x : x; -} - -float remquof(float x, float y, int *quo) { - union {float f; uint32_t i;} ux = {x}, uy = {y}; - int ex = ux.i>>23 & 0xff; - int ey = uy.i>>23 & 0xff; - int sx = ux.i>>31; - int sy = uy.i>>31; - uint32_t q; - uint32_t i; - uint32_t uxi = ux.i; - - *quo = 0; - if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) - return (x*y)/(x*y); - if (ux.i<<1 == 0) - return x; - - /* normalize x and y */ - if (!ex) { - for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1); - uxi <<= -ex + 1; - } else { - uxi &= -1U >> 9; - uxi |= 1U << 23; - } - if (!ey) { - for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); - uy.i <<= -ey + 1; - } else { - uy.i &= -1U >> 9; - uy.i |= 1U << 23; - } - - q = 0; - if (ex < ey) { - if (ex+1 == ey) - goto end; - return x; - } - - /* x mod y */ - for (; ex > ey; ex--) { - i = uxi - uy.i; - if (i >> 31 == 0) { - uxi = i; - q++; - } - uxi <<= 1; - q <<= 1; - } - i = uxi - uy.i; - if (i >> 31 == 0) { - uxi = i; - q++; - } - if (uxi == 0) - ex = -30; - else - for (; uxi>>23 == 0; uxi <<= 1, ex--); -end: - /* scale result and decide between |x| and |x|-|y| */ - if (ex > 0) { - uxi -= 1U << 23; - uxi |= (uint32_t)ex << 23; - } else { - uxi >>= -ex + 1; - } - ux.i = uxi; - x = ux.f; - if (sy) - y = -y; - if (ex == ey || (ex+1 == ey && (2*x > y || (2*x == y && q%2)))) { - x -= y; - q++; - } - q &= 0x7fffffff; - *quo = sx^sy ? -(int)q : (int)q; - return sx ? -x : x; -} - - -long double remquol(long double x, long double y, int *quo) { - return remquo(x, y, quo); -} - -double remainder(double x, double y) { - int q; - return remquo(x, y, &q); -} - -float remainderf(float x, float y) { - int q; - return remquof(x, y, &q); -} - -long double remainderl(long double x, long double y) { - return remainder(x, y); -} - -double modf(double x, double *iptr) { - union {double f; uint64_t i;} u = {x}; - uint64_t mask; - int e = (int)(u.i>>52 & 0x7ff) - 0x3ff; - - /* no fractional part */ - if (e >= 52) { - *iptr = x; - if (e == 0x400 && u.i<<12 != 0) /* nan */ - return x; - u.i &= 1ULL<<63; - return u.f; - } - - /* no integral part*/ - if (e < 0) { - u.i &= 1ULL<<63; - *iptr = u.f; - return x; - } - - mask = -1ULL>>12>>e; - if ((u.i & mask) == 0) { - *iptr = x; - u.i &= 1ULL<<63; - return u.f; - } - u.i &= ~mask; - *iptr = u.f; - return x - u.f; -} - -float modff(float x, float *iptr) { - union {float f; uint32_t i;} u = {x}; - uint32_t mask; - int e = (int)(u.i>>23 & 0xff) - 0x7f; - - /* no fractional part */ - if (e >= 23) { - *iptr = x; - if (e == 0x80 && u.i<<9 != 0) { /* nan */ - return x; - } - u.i &= 0x80000000; - return u.f; - } - /* no integral part */ - if (e < 0) { - u.i &= 0x80000000; - *iptr = u.f; - return x; - } - - mask = 0x007fffff>>e; - if ((u.i & mask) == 0) { - *iptr = x; - u.i &= 0x80000000; - return u.f; - } - u.i &= ~mask; - *iptr = u.f; - return x - u.f; -} - -long double modfl(long double x, long double *iptr) { - double d; - long double r = modf(x, &d); - *iptr = d; - return r; -} diff --git a/src/math/gen_math.c b/src/math/gen_math.c deleted file mode 100644 index 700ad30..0000000 --- a/src/math/gen_math.c +++ /dev/null @@ -1,28 +0,0 @@ - -static double LN2 = 0.693147180559945309417232121458176; -static double HALF_PI = 1.570796326794896619231321691639751; -static double PI = 3.141592653589793238462643383279502; -static double LOG2E = 1.442695040888963407359924681001892; - -#define countof(arr) (sizeof arr/sizeof arr[0]) - -#define ftype float -#define suffix(name) name ## f -#include "cordic/cordic_dataf.h" -#include "gen_math.h" -#undef ftype -#undef suffix - -#define ftype double -#define suffix(name) name -#include "cordic/cordic_data.h" -#include "gen_math.h" -#undef ftype -#undef suffix - -#define ftype long double -#define suffix(name) name ## l -#include "cordic/cordic_datal.h" -#include "gen_math.h" -#undef ftype -#undef suffix diff --git a/src/math/gen_math.h b/src/math/gen_math.h deleted file mode 100644 index 23c97a5..0000000 --- a/src/math/gen_math.h +++ /dev/null @@ -1,228 +0,0 @@ - -static ftype suffix(cordic)( - ftype x0, // x initial value - ftype y0, // y initial value - ftype z0, // initial 'angle' - int m, // system: 1 for trig, -1 for hyperbolic - int v, // mode: 1 for vectoring, 0 for rotation - ftype *c, // output x - ftype *s // output y -) { - int tab_count = 0; - ftype *tab = NULL; - if(m == 1) { - tab = suffix(ttable); - tab_count = countof(suffix(ttable)); - } - else if(m == -1) { - tab = suffix(htable); - tab_count = countof(suffix(htable)); - } - ftype x = x0; - ftype y = y0; - ftype z = z0; - for(int i = 0; i != tab_count; ++i) { - ftype sign; - if(v) sign = (y < 0)? 1 : -1; - else sign = (z < 0)? -1 : 1; - ftype x1 = suffix(fma)(suffix(ptable)[i], -m*sign*y, x); - ftype y1 = suffix(fma)(suffix(ptable)[i], x*sign, y); - x = x1; - y = y1; - z = suffix(fma)(tab[i], -sign, z); - } - if(c!=NULL) *c = x; - if(s!=NULL) *s = y; - return z; -} - -ftype suffix(sin)(ftype x) { - if(isinf(x)) return NAN; - if(isnan(x)) return NAN; - int k; - ftype alpha = suffix(remquo)(x, HALF_PI, &k); - if(x == 0) return x; - k = (((k % 4) +4) %4); - ftype sinx; - ftype cosx; - suffix(cordic)(suffix(tK), 0, alpha, 1, 0, &cosx, &sinx); - switch(k) { - case 0: return sinx; - case 1: return cosx; - case 2: return -sinx; - case 3: return -cosx; - } - return 0; -} - -ftype suffix(cos)(ftype x) { - if(isinf(x)) return NAN; - if(isnan(x)) return NAN; - int k; - ftype alpha = suffix(remquo)(x, HALF_PI, &k); - k = (((k % 4) +4) %4); - ftype sinx; - ftype cosx; - suffix(cordic)(suffix(tK), 0, alpha, 1, 0, &cosx, &sinx); - switch(k) { - case 0: return cosx; - case 1: return -sinx; - case 2: return -cosx; - case 3: return sinx; - } - return 0; -} - -ftype suffix(tan)(ftype x) { - if(isinf(x)) return NAN; - if(isnan(x)) return NAN; - int k; - ftype alpha = suffix(remquo)(x, HALF_PI, &k); - if(x == 0) return x; - k = (((k % 2) +2) %2); - ftype sinx; - ftype cosx; - suffix(cordic)(suffix(tK), 0, alpha, 1, 0, &cosx, &sinx); - switch(k) { - case 0: return sinx/cosx; - case 1: return -cosx/sinx; - } - return 0; -} - -ftype suffix(cot)(ftype x) { - if(x == 0) return x; - if(isinf(x)) return NAN; - if(isnan(x)) return NAN; - int k; - ftype alpha = suffix(remquo)(x, HALF_PI, &k); - k = (((k % 2) +2) %2); - ftype sinx; - ftype cosx; - suffix(cordic)(suffix(tK), 0, alpha, 1, 0, &cosx, &sinx); - switch(k) { - case 0: return cosx/sinx; - case 1: return -sinx/cosx; - } - return 0; -} - -ftype suffix(exp)(ftype x) { - if(x == 0) return x; - if(isinf(x)) return NAN; - if(isnan(x)) return NAN; - ftype t = x*LOG2E; - int64_t k = (int64_t)t; - x = (t - (ftype)k) / LOG2E; - ftype xx = x*x; - ftype xxx = xx*x; - ftype xxxx = xx*xx; - ftype xxxxx = xxx*xx; - ftype expx = 1+x + xx/2.0 + xxx/6.0+ xxxx/24.0 + xxxxx/720.0; - if(k>0) expx *= 2.0; - if(k>0) while(k-- > 0) expx *= 2.0; - if(k<0) while(k++ < 0) expx /= 2.0; - return expx; -} - -ftype suffix(atan)(ftype x) { - if(x == 0) return x; - if(isinf(x)) return INFINITY; - if(isnan(x)) return NAN; - ftype atan; - if(x > 1) { - atan = HALF_PI - suffix(cordic)(x, 1, 0, 1, 1, NULL, NULL); - } - else if(x < -1) { - atan = -HALF_PI + suffix(cordic)(-x, 1, 0, 1, 1, NULL, NULL); - } - else { - atan = suffix(cordic)(1, x, 0, 1, 1, NULL, NULL); - } - return atan; -} - -ftype suffix(acos)(ftype x) { - if(x == 0) return HALF_PI; - if(x == -1) return PI; - if(x == 1) return 0; - if(isinf(x)) return INFINITY; - if(isnan(x)) return NAN; - if(fabs(x) > 1) return NAN; - ftype atan; - x = sqrt(fma(-x,x,1))/x; - if(x > 1) { - atan = HALF_PI - suffix(cordic)(x, 1, 0, 1, 1, NULL, NULL); - } - else if(x < -1) { - atan = -HALF_PI + suffix(cordic)(-x, 1, 0, 1, 1, NULL, NULL); - } - else { - atan = suffix(cordic)(1, x, 0, 1, 1, NULL, NULL); - } - if(x < 0) atan += PI; - return atan; -} - -ftype suffix(asin)(ftype x) { - if(x == 0) return 0; - if(x == -1) return -HALF_PI; - if(x == 1) return HALF_PI; - if(isinf(x)) return INFINITY; - if(isnan(x)) return NAN; - if(fabs(x) > 1) return NAN; - ftype atan; - x /= sqrt(fma(-x,x,1)); - if(x > 1) { - atan = HALF_PI - suffix(cordic)(x, 1, 0, 1, 1, NULL, NULL); - } - else if(x < -1) { - atan = -HALF_PI + suffix(cordic)(-x, 1, 0, 1, 1, NULL, NULL); - } - else { - atan = suffix(cordic)(1, x, 0, 1, 1, NULL, NULL); - } - return atan; -} - -// ftype suffix(exp)(ftype x) { -// if(isnan(x)) return NAN; -// if(x > 0 && isinf(x)) return +INFINITY; -// if(x < 0 && isinf(x)) return +0.0; -// if(x == 0) return 1.0; -// if(x > 709.8) { -// #if math_errhandling & MATH_ERREXCEPT -// feraiseexcept(FE_OVERFLOW); -// #endif -// #if math_errhandling & MATH_ERRNO -// errno = ERANGE; -// #endif -// return +INFINITY; -// } -// if(x < -708.4) { -// #if math_errhandling & MATH_ERREXCEPT -// feraiseexcept(FE_OVERFLOW); -// #endif -// #if math_errhandling & MATH_ERRNO -// errno = ERANGE; -// #endif -// return 0; -// } -// ftype e = 1.0; -// ftype xp = 1.0; -// ftype f = 1; -// for(uint64_t i = 1; i != 10; ++i) { -// f *= i; -// xp *= x; -// e += xp / f; -// } -// return e; -// } - -ftype suffix(exp2)(ftype x) { - return suffix(exp)(x * LN2); -} - -ftype suffix(expm1)(ftype x) { - return suffix(exp)(x) - 1.0; -} diff --git a/src/math/round.c b/src/math/round.c deleted file mode 100644 index d19c744..0000000 --- a/src/math/round.c +++ /dev/null @@ -1,522 +0,0 @@ - -#define asuint64(x) ((union {f64 f; uint64_t i;}){x}).i -#define asdouble(x) ((union {f64 f; uint64_t i;}){x}).f - -#if defined(__GNUC__) || defined(__clang__) - #define just_do_it(v) do{__attribute__((unused)) volatile f64 t = v;}while(0) -#else - #define just_do_it(v) do{volatile f64 t = v;}while(0) -#endif - -f64 nearbyint(f64 x) { - #pragma STDC FENV_ACCESS ON - u64 bits = F64_BITS(x); - i64 bexp = F64_BEXP(bits); - u64 bmant = F64_MANT(bits); - // 1. Get rid of special cases, exp = 0x7ff, and exp < 0x3ff - // Return x unmodified if inf, nan - if(bexp == 0x7ff) { - return x; - } - int mode = fegetround(); - // Get exponent for (integer_mantissa * 2^exp) representation - i64 exp = bexp - 0x3ff - 52; - int s = F64_SIGN(bits); - // This value is 0 if no increment is required, and 1 if the absolute value - // increases by 1 - int c; - { - // Check if we need to round towards 0 or towards 1 - // (assumes specific values in rounding modes in fenv.h) - int a = (mode&2)>>1; - int b = mode&1; - int mask = ((a^b)<<1)|(a^b); - int d = 2 - mode&mask; - c = s ^ d; - } - // If the whole mantissa is after a point, such that the first digit is 0, - // then the value is closer to 0 these values are all zeroes, subnormal - // numbers and very small normal numbers - if(exp < -53) { - // Return 0 if exponent and mantissa are zero - if(bexp == 0 && bmant == 0) { - return x; - } - // For subnormal and normal numbers we round them either towards 0 or 1 - // and then call it a day - u64 new_bexp = (u64)((1-c)&0x3ff) << F64_MANT_BITS; - u64 new_sign = (u64)s << 63; - u64 new_bits = new_sign | new_bexp; - return F64_CONS(new_bits); - } - // 2. Get fractional and whole bits of the mantissa - u64 mant = bmant | ((u64)1 << 52); - if(exp >= 0) { - // Already an integer - return x; - } - // if e.g. mantissa is 0b101.., and exponent is -2, the value is 0b101*2^-2 - // or 0b1.01, meaning there are 2 fractional digits - int nfrac_digs = -exp; - u64 frac_mask = (((u64)1<<(nfrac_digs))-1); - u64 frac_mant = mant & frac_mask; - // The mantissas for 1.0 and 0.5 - u64 one = (((u64)1<<(nfrac_digs))); - u64 half = one >> 1; - // 3. Round the float based on the value of c - // we'll first fix up c to include other rounding modes - c |= (mode == FE_UPWARD) & ((~s)&1); - c |= (mode == FE_DOWNWARD) & s; - c |= (mode == FE_TONEAREST) & (frac_mant >= half); - // Drop fractional bits - u64 new_mant = mant & ~frac_mant; - // Add 1 to float if required - if(c) { - new_mant += one; - if(new_mant > ((u64)1 << 53)) { - new_mant >>= 1; - exp += 1; - } - } - new_mant &= F64_MANT_MASK; - u64 new_bits = new_mant; - new_bits |= (exp+0x3ff+52) << F64_MANT_BITS; - new_bits |= (u64)s << (F64_MANT_BITS + F64_BEXP_BITS); - f64 result = F64_CONS(new_bits); - return result; -} - -f32 nearbyintf(f32 x) { - #pragma STDC FENV_ACCESS ON - u64 bits = F32_BITS(x); - i64 bexp = F32_BEXP(bits); - u64 bmant = F32_MANT(bits); - if(bexp == 0x7f) { - return x; - } - int mode = fegetround(); - i64 exp = bexp - 0x3f - 52; - int s = F32_SIGN(bits); - int c; - { - int a = (mode&2)>>1; - int b = mode&1; - int mask = ((a^b)<<1)|(a^b); - int d = 2 - mode&mask; - c = s ^ d; - } - if(exp < -24) { - if(bexp == 0 && bmant == 0) { - return x; - } - u64 new_bexp = (u64)((1-c)&0x3f) << F32_MANT_BITS; - u64 new_sign = (u64)s << 63; - u64 new_bits = new_sign | new_bexp; - return F32_CONS(new_bits); - } - u64 mant = bmant | ((u64)1 << 23); - if(exp >= 0) { - return x; - } - int nfrac_digs = -exp; - u64 frac_mask = (((u64)1<<(nfrac_digs))-1); - u64 frac_mant = mant & frac_mask; - u64 one = (((u64)1<<(nfrac_digs))); - u64 half = one >> 1; - c |= (mode == FE_UPWARD) & ((~s)&1); - c |= (mode == FE_DOWNWARD) & s; - c |= (mode == FE_TONEAREST) & (frac_mant >= half); - u64 new_mant = mant & ~frac_mant; - if(c) { - new_mant += one; - if(new_mant > ((u64)1 << 24)) { - new_mant >>= 1; - exp += 1; - } - } - new_mant &= F32_MANT_MASK; - u64 new_bits = new_mant; - new_bits |= (exp+0x3f+23) << F32_MANT_BITS; - new_bits |= (u64)s << (F32_MANT_BITS + F32_BEXP_BITS); - f64 result = F32_CONS(new_bits); - return result; -} - -fl64 nearbyintl(fl64 x) { - return nearbyint((f64)x); -} - -f64 nextafter(f64 x, f64 y) { - union {f64 f; uint64_t i;} ux={x}, uy={y}; - uint64_t ax, ay; - int e; - if (isnan(x) || isnan(y)) return x + y; - if (ux.i == uy.i) return y; - ax = ux.i & -1ULL/2; - ay = uy.i & -1ULL/2; - if (ax == 0) { - if (ay == 0) return y; - ux.i = (uy.i & 1ULL<<63) | 1; - } else if (ax > ay || ((ux.i ^ uy.i) & 1ULL<<63)) { - ux.i--; - } - else { - ux.i++; - } - e = ux.i >> 52 & 0x7f; - /* raise overflow if ux.f is infinite and x is finite */ - if (e == 0x7f) just_do_it(x+x); - /* raise underflow if ux.f is subnormal or zero */ - if (e == 0) just_do_it(x*x + ux.f*ux.f); - return ux.f; -} - -f32 nextafterf(f32 x, f32 y) { - union {f32 f; uint32_t i;} ux={x}, uy={y}; - uint32_t ax, ay, e; - - if (isnan(x) || isnan(y)) return x + y; - if (ux.i == uy.i) return y; - ax = ux.i & 0x7fffffff; - ay = uy.i & 0x7fffffff; - if (ax == 0) { - if (ay == 0) return y; - ux.i = (uy.i & 0x80000000) | 1; - } else if (ax > ay || ((ux.i ^ uy.i) & 0x80000000)) { - ux.i--; - } - else { - ux.i++; - } - e = ux.i & 0x7f800000; - /* raise overflow if ux.f is infinite and x is finite */ - if (e == 0x7f800000) just_do_it(x+x); - /* raise underflow if ux.f is subnormal or zero */ - if (e == 0) just_do_it(x*x + ux.f*ux.f); - return ux.f; -} - -fl64 nextafterl(fl64 x, fl64 y) { - return nextafter(x, y); -} - -f64 nexttoward(f64 x, fl64 y) { - return nextafter(x, y); -} - -f32 nexttowardf(f32 x, fl64 y) { - union {f32 f; uint32_t i;} ux = {x}; - uint32_t e; - if (isnan(x) || isnan(y)) return x + y; - if (x == y) return y; - if (x == 0) { - ux.i = 1; - if (signbit(y)) ux.i |= 0x80000000; - } else if (x < y) { - if (signbit(x)) ux.i--; - else ux.i++; - } else { - if (signbit(x)) ux.i++; - else ux.i--; - } - e = ux.i & 0x7f800000; - /* raise overflow if ux.f is infinite and x is finite */ - if (e == 0x7f800000) just_do_it(x+x); - /* raise underflow if ux.f is subnormal or zero */ - if (e == 0) just_do_it(x*x + ux.f*ux.f); - return ux.f; -} - -fl64 nexttowardl(fl64 x, fl64 y) { - return nextafterl(x, y); -} - -f64 rint(f64 x) { - static const double_t toint = 1/DBL_EPSILON; - union {f64 f; uint64_t i;} u = {x}; - int e = u.i>>52 & 0x7ff; - int s = u.i>>63; - f64 y; - if (e >= 0x3ff+52) return x; - if (s) y = x - toint + toint; - else y = x + toint - toint; - if (y == 0) return s ? -0.0 : +0.0; - return y; -} - -f32 rintf(f32 x) { - static const f32 toint = 1/FLT_EPSILON; - union {f32 f; uint32_t i;} u = {x}; - int e = u.i>>23 & 0xff; - int s = u.i>>31; - f32 y; - if (e >= 0x7f+23) return x; - if (s) y = x - toint + toint; - else y = x + toint - toint; - if (y == 0) return s ? -0.0f : 0.0f; - return y; -} - -fl64 rintl(fl64 x) { - return rint(x); -} - -#if LONG_MAX < 1U<<53 && defined(FE_INEXACT) - static long lrint_slow(f64 x) - { - #pragma STDC FENV_ACCESS ON - int e; - e = fetestexcept(FE_INEXACT); - x = rint(x); - if (!e && (x > LONG_MAX || x < LONG_MIN)) - feclearexcept(FE_INEXACT); - /* conversion */ - return x; - } - - long lrint(f64 x) - { - uint32_t abstop = asuint64(x)>>32 & 0x7fffffff; - uint64_t sign = asuint64(x) & (1ULL << 63); - - if (abstop < 0x41dfffff) { - /* |x| < 0x7ffffc00, no overflow */ - double_t toint = asdouble(asuint64(1/DBL_EPSILON) | sign); - double_t y = x + toint - toint; - return (long)y; - } - return lrint_slow(x); - } -#else - long lrint(f64 x) { - return rint(x); - } -#endif - -long lrintf(f32 x) { - return rintf(x); -} - -long lrintl(fl64 x) { - return lrint(x); -} - -long long llrint(f64 x) { - return rint(x); -} - -long long llrintf(f32 x) { - return rintf(x); -} - -long long llrintl(fl64 x) { - return llrint(x); -} - -f64 round(f64 x) { - static const double_t toint = 1/DBL_EPSILON; - union {f64 f; uint64_t i;} u = {x}; - int e = u.i >> 52 & 0x7ff; - double_t y; - if (e >= 0x3ff+52) return x; - if (u.i >> 63) x = -x; - if (e < 0x3ff-1) { - /* raise inexact if x!=0 */ - just_do_it(x + toint); - return 0*u.f; - } - y = x + toint - toint - x; - if (y > 0.5) y = y + x - 1; - else if (y <= -0.5) y = y + x + 1; - else y = y + x; - if (u.i >> 63) y = -y; - return y; -} - -f32 roundf(f32 x) { - static const double_t toint = 1/FLT_EPSILON; - union {f32 f; uint32_t i;} u = {x}; - int e = u.i >> 23 & 0xff; - float_t y; - if (e >= 0x7f+23) return x; - if (u.i >> 31) x = -x; - if (e < 0x7f-1) { - just_do_it(x + toint); - return 0*u.f; - } - y = x + toint - toint - x; - if (y > 0.5f) y = y + x - 1; - else if (y <= -0.5f) y = y + x + 1; - else y = y + x; - if (u.i >> 31) y = -y; - return y; -} - -fl64 roundl(fl64 x) { - return round(x); -} - -long lround(f64 x) { - return round(x); -} - -long lroundf(f32 x) { - return roundf(x); -} - -long lroundl(fl64 x) { - return roundl(x); -} - -long long llround(f64 x) { - return round(x); -} - -long long llroundf(f32 x) { - return roundf(x); -} - -long long llroundl(fl64 x) { - return roundl(x); -} - -f64 ceil(f64 x) { - static const double_t toint = 1/DBL_EPSILON; - union {f64 f; uint64_t i;} u = {x}; - int e = u.i >> 52 & 0x7ff; - double_t y; - - if (e >= 0x3ff+52 || x == 0) - return x; - /* y = int(x) - x, where int(x) is an integer neighbor of x */ - if (u.i >> 63) - y = x - toint + toint - x; - else - y = x + toint - toint - x; - /* special case because of non-nearest rounding modes */ - if (e <= 0x3ff-1) { - just_do_it(y); - return u.i >> 63 ? -0.0 : 1; - } - if (y < 0) - return x + y + 1; - return x + y; -} - -f32 ceilf(f32 x) { - union {f32 f; uint32_t i;} u = {x}; - int e = (int)(u.i >> 23 & 0xff) - 0x7f; - uint32_t m; - - if (e >= 23) - return x; - if (e >= 0) { - m = 0x007fffff >> e; - if ((u.i & m) == 0) - return x; - just_do_it(x + 0x1p120f); - if (u.i >> 31 == 0) - u.i += m; - u.i &= ~m; - } else { - just_do_it(x + 0x1p120f); - if (u.i >> 31) - u.f = -0.0; - else if (u.i << 1) - u.f = 1.0; - } - return u.f; -} - -fl64 ceill(fl64 x) { - return ceil(x); -} - -f64 floor(f64 x) { - static const double_t toint = 1/DBL_EPSILON; - union {f64 f; uint64_t i;} u = {x}; - int e = u.i >> 52 & 0x7ff; - double_t y; - if (e >= 0x3ff+52 || x == 0) - return x; - /* y = int(x) - x, where int(x) is an integer neighbor of x */ - if (u.i >> 63) - y = x - toint + toint - x; - else - y = x + toint - toint - x; - /* special case because of non-nearest rounding modes */ - if (e <= 0x3ff-1) { - just_do_it(y); - return u.i >> 63 ? -1 : 0; - } - if (y > 0) - return x + y - 1; - return x + y; -} - -f32 floorf(f32 x) { - union {f32 f; uint32_t i;} u = {x}; - int e = (int)(u.i >> 23 & 0xff) - 0x7f; - uint32_t m; - - if (e >= 23) - return x; - if (e >= 0) { - m = 0x007fffff >> e; - if ((u.i & m) == 0) - return x; - just_do_it(x + 0x1p120f); - if (u.i >> 31) - u.i += m; - u.i &= ~m; - } else { - just_do_it(x + 0x1p120f); - if (u.i >> 31 == 0) - u.i = 0; - else if (u.i << 1) - u.f = -1.0; - } - return u.f; -} - -fl64 floorl(fl64 x) { - return floor(x); -} - -f64 trunc(f64 x) { - union {f64 f; uint64_t i;} u = {x}; - int e = (int)(u.i >> 52 & 0x7ff) - 0x3ff + 12; - uint64_t m; - - if (e >= 52 + 12) - return x; - if (e < 12) - e = 1; - m = -1ULL >> e; - if ((u.i & m) == 0) - return x; - just_do_it(x + 0x1p120f); - u.i &= ~m; - return u.f; -} - -f32 truncf(f32 x) { - union {f32 f; uint32_t i;} u = {x}; - int e = (int)(u.i >> 23 & 0xff) - 0x7f + 9; - uint32_t m; - - if (e >= 23 + 9) - return x; - if (e < 9) - e = 1; - m = -1U >> e; - if ((u.i & m) == 0) - return x; - just_do_it(x + 0x1p120f); - u.i &= ~m; - return u.f; -} - -fl64 truncl(fl64 x) { - return trunc(x); -} diff --git a/src/os_linux/linux_environment.c b/src/os_linux/linux_environment.c deleted file mode 100644 index f73eb1c..0000000 --- a/src/os_linux/linux_environment.c +++ /dev/null @@ -1,85 +0,0 @@ - -#include -#include - -// Exit routines -#define ATEXIT_FUNC_COUNT 64 -#define ATQEXIT_FUNC_COUNT 64 -static void (*atexit_funcs [ATEXIT_FUNC_COUNT])(void); -static void (*atqexit_funcs[ATQEXIT_FUNC_COUNT])(void); -static int atexit_func_count; -static int atqexit_func_count; - -static char **get_command_args(int *argcp); - -// TODO: Instead of using static arrays, allocate this memory dynamically -static char cmdline[4096]; -static char *cmdargs[1024]; -extern int main(int argc, char** argv); - - -void _start() { - srand(0); - setlocale(LC_ALL, "C"); - - int argc; - char **argv = get_command_args(&argc); - int exit_code = main(argc, argv); - - exit(exit_code); -} - -_Noreturn void quick_exit(int status) { - while(atqexit_func_count--) { - atqexit_funcs[atqexit_func_count](); - } - _exit(status); -} - -_Noreturn void exit(int status) { - while(atexit_func_count--) { - atexit_funcs[atqexit_func_count](); - } - // _close_io(); - _exit(status); -} - -_Noreturn void _Exit(int status) { - _exit(status); -} - -_Noreturn void abort(void) { - // raise(SIGABRT); - _exit(-69); -} - -int atexit(void (*func)(void)) { - if (atexit_func_count >= ATEXIT_FUNC_COUNT) { - return 0; - } - atexit_funcs[atexit_func_count++] = func; - return 1; -} - -int at_quick_exit(void (*func)(void)) { - if(atqexit_func_count >= ATQEXIT_FUNC_COUNT) { - return 0; - } - atqexit_funcs[atqexit_func_count++] = func; - return 1; -} - -static char **get_command_args(int *argcp) { - int fd = open("/proc/self/cmdline", O_RDONLY); - ssize_t size = read(fd, cmdline, sizeof cmdline); - ssize_t i = 0; - ssize_t cmd_idx = 0; - while(i != size) { - cmdargs[cmd_idx] = &cmdline[i]; - while(cmdline[i] != 0) { - ++i; - } - ++i; - } - return cmdargs; -} diff --git a/src/os_linux/syscalls.asm b/src/os_linux/syscalls.asm deleted file mode 100644 index 21fa358..0000000 --- a/src/os_linux/syscalls.asm +++ /dev/null @@ -1,9 +0,0 @@ - -bits 64 -segment .text - -global _exit -_exit: - mov rax, 60 - syscall - ret diff --git a/src/os_win/assert.c b/src/os_win/assert.c deleted file mode 100644 index a72add5..0000000 --- a/src/os_win/assert.c +++ /dev/null @@ -1,64 +0,0 @@ - -#include - -#pragma comment(lib, "user32.lib") -#pragma comment(lib, "DbgHelp.lib") - -static void _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", - // " %d: %s\n", - // (int)(frames-i-1), - // //symbol->Address, - // symbol->Name - // ); - } - free(symbol); -} - - -void _assert( - char const *cond, - char const *func, - char const *file, - int line -) { - if(GetConsoleWindow() == NULL) { - // 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); -display_msg: - int reaction = MessageBoxA(NULL, buf, "Assertion Failed", 0x00000032L); - switch(reaction) { - case IDABORT: abort(); - case IDRETRY: goto display_msg; - case IDCONTINUE: return; - } - } - 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"); - _print_stack_trace(); - abort(); - } -} diff --git a/src/os_win/chkstk.asm b/src/os_win/chkstk.asm deleted file mode 100644 index 5ab5b5b..0000000 --- a/src/os_win/chkstk.asm +++ /dev/null @@ -1,28 +0,0 @@ - -bits 64 - -segment .text - -global __chkstk -__chkstk: - sub rsp, 0x10 - mov [rsp], r10 - mov [rsp+0x8], r11 - xor r11, r11 - lea r10, [rsp+0x18] - sub r10, rax - cmovb r10, r11 - mov r11, gs:[0x10] - cmp r10, r11 - jnb .end - and r10w, 0xf000 -.loop: - lea r11, [r11-0x1000] - mov byte [r11], 0x0 - cmp r10, r11 - jnz .loop -.end: - mov r10, [rsp] - mov r11, [rsp+0x8] - add rsp, 0x10 - ret diff --git a/src/os_win/cmdline.c b/src/os_win/cmdline.c deleted file mode 100644 index 99ec0c5..0000000 --- a/src/os_win/cmdline.c +++ /dev/null @@ -1,116 +0,0 @@ - -#define CMDLINE_CMD_MAX 32767 -#define CMDLINE_ARGV_MAX (16384+(98298+(int)sizeof(char*))/(int)sizeof(char*)) - -// https://github.com/skeeto/scratch/blob/master/misc/cmdline.c#L27 -static int cmdline_to_argv8(const wchar_t *cmd, char **argv) { - int argc = 1; // worst case: argv[0] is an empty string - int state = 6; // special argv[0] state - int slash = 0; - char *buf = (char *)(argv + 16384); // second half: byte buffer - - argv[0] = buf; - while (*cmd) { - int c = *cmd++; - if (c>>10 == 0x36 && *cmd>>10 == 0x37) { // surrogates? - c = 0x10000 + ((c - 0xd800)<<10) + (*cmd++ - 0xdc00); - } - - switch (state) { - case 0: switch (c) { // outside token - case 0x09: - case 0x20: continue; - case 0x22: argv[argc++] = buf; - state = 2; - continue; - case 0x5c: argv[argc++] = buf; - slash = 1; - state = 3; - break; - default : argv[argc++] = buf; - state = 1; - } break; - case 1: switch (c) { // inside unquoted token - case 0x09: - case 0x20: *buf++ = 0; - state = 0; - continue; - case 0x22: state = 2; - continue; - case 0x5c: slash = 1; - state = 3; - break; - } break; - case 2: switch (c) { // inside quoted token - case 0x22: state = 5; - continue; - case 0x5c: slash = 1; - state = 4; - break; - } break; - case 3: - case 4: switch (c) { // backslash sequence - case 0x22: buf -= (1 + slash) >> 1; - if (slash & 1) { - state -= 2; - break; - } // fallthrough - default : cmd--; - state -= 2; - continue; - case 0x5c: slash++; - } break; - case 5: switch (c) { // quoted token exit - default : cmd--; - state = 1; - continue; - case 0x22: state = 1; - } break; - case 6: switch (c) { // begin argv[0] - case 0x09: - case 0x20: *buf++ = 0; - state = 0; - continue; - case 0x22: state = 8; - continue; - default : state = 7; - } break; - case 7: switch (c) { // unquoted argv[0] - case 0x09: - case 0x20: *buf++ = 0; - state = 0; - continue; - } break; - case 8: switch (c) { // quoted argv[0] - case 0x22: *buf++ = 0; - state = 0; - continue; - } break; - } - - switch (c & 0x1f0880) { // WTF-8/UTF-8 encoding - case 0x00000: *buf++ = 0x00 | ((c >> 0) ); break; - case 0x00080: *buf++ = 0xc0 | ((c >> 6) ); - *buf++ = 0x80 | ((c >> 0) & 63); break; - case 0x00800: - case 0x00880: *buf++ = 0xe0 | ((c >> 12) ); - *buf++ = 0x80 | ((c >> 6) & 63); - *buf++ = 0x80 | ((c >> 0) & 63); break; - default : *buf++ = 0xf0 | ((c >> 18) ); - *buf++ = 0x80 | ((c >> 12) & 63); - *buf++ = 0x80 | ((c >> 6) & 63); - *buf++ = 0x80 | ((c >> 0) & 63); - } - } - - *buf = 0; - argv[argc] = 0; - return argc; -} - -static char **get_command_args(int *argc_ptr) { - static char *argv_buffer[CMDLINE_ARGV_MAX]; - wchar_t *cmdline = GetCommandLineW(); - *argc_ptr = cmdline_to_argv8(cmdline, argv_buffer); - return argv_buffer; -} diff --git a/src/os_win/cookie.c b/src/os_win/cookie.c deleted file mode 100644 index 4eb7941..0000000 --- a/src/os_win/cookie.c +++ /dev/null @@ -1,15 +0,0 @@ - -u64 __security_cookie; - -void __security_init_cookie() { - // They say it's a random number so I generated - // one using numbergenerator.org - __security_cookie = 0xb26e04cc62ba48aULL; -} - -void __security_check_cookie(u64 retrieved) { - if(__security_cookie != retrieved) { - // printf("Bro you've got a buffer overrun\n"); - abort(); - } -} diff --git a/src/os_win/entry.c b/src/os_win/entry.c deleted file mode 100644 index a71f554..0000000 --- a/src/os_win/entry.c +++ /dev/null @@ -1,42 +0,0 @@ - -#pragma weak main -#pragma weak wmain -#pragma weak WinMain - -int main(int argc, char** argv); -// int wmain(int argc, wchar_t** argv, wchar_t **envp); -// int WinMain(HINSTANCE inst, HINSTANCE pinst, LPSTR cmdline, int showcmd); - -_Noreturn void mainCRTStartup() { - _setup_eh(); - _setup_heap(); - _setup_timer(); - _io_init(); - __security_init_cookie(); - - srand(0); - setlocale(LC_ALL, "C"); - - int argc; - char **args = get_command_args(&argc); - int exit_code = main(argc, args); - - exit(exit_code); -} - -/*_Noreturn void WinMainCRTStartup() { - _setup_eh(); - _setup_heap(); - _setup_timer(); - _io_init(); - __security_init_cookie(); - - srand(0); - setlocale(LC_ALL, "C"); - - HINSTANCE inst = GetModuleHandle(NULL); - LPSTR cmdline = GetCommandLineA(); - int exit_code = WinMain(inst, 0, cmdline, SW_SHOWDEFAULT); - - exit(exit_code); -}*/ diff --git a/src/os_win/env.c b/src/os_win/env.c deleted file mode 100644 index 8cdcd46..0000000 --- a/src/os_win/env.c +++ /dev/null @@ -1,138 +0,0 @@ - -// Windows symbols because windows -int _fltused=0; - -#pragma comment(lib, "kernel32.lib") - -// Exit routines -#define ATEXIT_FUNC_COUNT 64 -#define ATQEXIT_FUNC_COUNT 64 -static void (*atexit_funcs [ATEXIT_FUNC_COUNT])(void); -static void (*atqexit_funcs[ATQEXIT_FUNC_COUNT])(void); -static int atexit_func_count; -static int atqexit_func_count; - -static char **get_command_args(int *argc_ptr); - -_Noreturn void _Exit(int status) { - ExitProcess(status); - #if defined(_MSC_VER) - __assume(0); - #elif defined(__GNUC__) - __builtin_unreachable(); - #endif -} - -_Noreturn void quick_exit(int status) { - while(atqexit_func_count--) { - atqexit_funcs[atqexit_func_count](); - } - _Exit(status); -} - -_Noreturn void exit(int status) { - while(atexit_func_count--) { - atexit_funcs[atqexit_func_count](); - } - _io_close(); - _Exit(status); -} - -_Noreturn void abort(void) { - raise(SIGABRT); - _Exit(-69); -} - -int atexit(void (*func)(void)) { - if (atexit_func_count >= ATEXIT_FUNC_COUNT) { - return 0; - } - atexit_funcs[atexit_func_count++] = func; - return 1; -} - -int at_quick_exit(void (*func)(void)) { - if(atqexit_func_count >= ATQEXIT_FUNC_COUNT) { - return 0; - } - atqexit_funcs[atqexit_func_count++] = func; - return 1; -} - -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; -} - -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 = {0}; - - 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; -} - -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; -} - diff --git a/src/os_win/file.c b/src/os_win/file.c deleted file mode 100644 index 6756c7b..0000000 --- a/src/os_win/file.c +++ /dev/null @@ -1,628 +0,0 @@ - -enum FileMode { - MODE_INPUT, - MODE_OUTPUT, - MODE_UPDATE, -} typedef FileMode; - -enum FileType { - FILE_BINARY, - FILE_TEXT, -} typedef FileType; - -struct FileBuffer typedef FileBuffer; -struct FileBuffer { - int is_internal; - int mode; - size_t size; - void *data; - size_t written; -}; - -struct FILE { - 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; -FILE *stdin; -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 *_file_tracker = NULL; - -static void _file_track(FILE *stream) { - if(_file_tracker != NULL) { - _file_tracker->next = stream; - stream->prev = _file_tracker; - stream->next = NULL; - _file_tracker = stream; - } - else { - _file_tracker = stream; - stream->prev = NULL; - stream->next = NULL; - } -} - -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) _file_tracker = prev; -} - -// Multithreaded access - -static inline void _file_lock_init(FILE *stream) { - mtx_init(&stream->lock, mtx_plain); -} - -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->io_mode = io_mode; - stream->bt_mode = bt_mode; - _file_lock_init(stream); - _file_track(stream); - return stream; -} - -static inline void _file_close(FILE *stream) { - _file_lock(stream); - CloseHandle(stream->handle); - _file_untrack(stream); - _file_unlock(stream); - _file_lock_destroy(stream); - free(stream); -} - -static void _io_init() { - HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE); - HANDLE hstderr = GetStdHandle(STD_ERROR_HANDLE); - HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE); - - 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 = (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 it will work someday - SetConsoleOutputCP(CP_UTF8); -} - -static void _io_close() { - while(_file_tracker != NULL) { - FILE *stream = _file_tracker; - fclose(stream); - _file_tracker = _file_tracker->next; - } -} - -// 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; - 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 = MODE_INPUT; break; - case 'w': io_mode = MODE_OUTPUT; break; - case 'a': io_mode = MODE_UPDATE; break; - default: return 0; - } - while(*mode) switch(*mode++) { - case '+': flag_p = 1; break; - case 'b': flag_b = 1; break; - case 'x': flag_x = 1; break; - default: return 0; - } - bt_mode = flag_b? FILE_BINARY : FILE_TEXT; - switch(io_mode) { - 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 MODE_OUTPUT: { - access = GENERIC_WRITE | (flag_p? GENERIC_READ : 0); - share = 0; - disp = CREATE_ALWAYS; - if(flag_x) { - disp = CREATE_NEW; - } - } break; - case MODE_UPDATE: { - access = GENERIC_READ | GENERIC_WRITE; - share = 0; - disp = OPEN_ALWAYS; - } break; - } - win_mode->access = access; - win_mode->share = share; - win_mode->disp = disp; - *pio_mode = io_mode; - *pbt_mode = bt_mode; - return 1; -} - -// 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 = _file_create(handle, io_mode, bt_mode); - void *buffer_data = malloc(BUFSIZ); - stream->buffer = (FileBuffer) {1, _IOFBF, BUFSIZ, buffer_data}; - return stream; -} - -FILE *freopen(const char *restrict name, const char *restrict mode, FILE *restrict stream) { - if(stream == NULL) { - return NULL; - } - fflush(stream); - 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; - if(name == NULL) { - // This codepath doesn't work - HANDLE handle = ReOpenFile(stream->handle, access, share, flags); - if(handle == INVALID_HANDLE_VALUE) { - return NULL; - } - } - else { - CloseHandle(stream->handle); - HANDLE handle = CreateFileA(name, access, share, NULL, disp, flags, NULL); - if(handle == INVALID_HANDLE_VALUE) { - return NULL; - } - *stream = (FILE) {0}; - stream->handle = handle; - stream->io_mode = io_mode; - stream->bt_mode = bt_mode; - } - return stream; -} - -int fclose(FILE *stream) { - if(fflush(stream) == EOF) { - return EOF; - } - if(stream->buffer.is_internal) { - free(stream->buffer.data); - } - if(!CloseHandle(stream->handle)) { - return EOF; - } - if(stream->temp) { - BOOL ok = DeleteFileA(stream->temp_name); - free(stream->temp_name); - if(!ok) { - return EOF; - } - } - _file_untrack(stream); - return 0; -} - -// 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; - if(buffer->written != 0) { - size_t size = buffer->written; - void *data = buffer->data; - 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; -} - -int ferror(FILE *stream) { - return stream->err; -} - -void clearerr(FILE *stream) { - stream->eof = 0; - stream->err = 0; -} - -void perror(char const *s) { - // printf("%s: %s\n", s, strerror(errno)); -} - -// File reads/writes - -int fputc(int c, FILE *stream) { - _file_lock(stream); - FileBuffer *buffer = &stream->buffer; - int res = c; - if(buffer->mode == _IONBF) { - unsigned char str[1] = {c}; - DWORD bytes_written; - BOOL ok = WriteFile(stream->handle, &str, 1, &bytes_written, NULL); - if(!ok) { - res = EOF; - stream->err = 1; - goto end; - } - - } - else { - unsigned char *data = buffer->data; - data[buffer->written++] = (unsigned char)c; - int needs_flush; - needs_flush = (buffer->written == buffer->size); - if(buffer->mode == _IOLBF) { - needs_flush |= (c == '\n'); - } - if(needs_flush) { - if(fflush(stream) == EOF) { - goto end; - } - } - } -end: - _file_unlock(stream); - return res; -} - -int fgetc(FILE *stream) { - _file_lock(stream); - int res = 0; - FileBuffer *buffer = &stream->buffer; - int read_from_disk = 1; - if(buffer->mode != _IONBF) { - unsigned char *data = buffer->data; - if(buffer->written != 0) { - read_from_disk = 0; - res = data[--buffer->written]; - } - } - if(read_from_disk) { - unsigned char buf[1]; - DWORD bytes_read; - BOOL ok = ReadFile(stream->handle, buf, 1, &bytes_read, NULL); - if(bytes_read != 1) { - res = EOF; - stream->eof = 1; - goto end; - } - if(!ok) { - res = EOF; - goto end; - } - res = buf[0]; - } -end: - _file_unlock(stream); - return res; -} - -int ungetc(int c, FILE *stream) { - _file_lock(stream); - int res; - FileBuffer *buffer = &stream->buffer; - if(buffer->mode == _IONBF) { - res = EOF; - goto end; - } - else { - if(c == EOF) { - res = EOF; - goto end; - } - if(buffer->written == buffer->size) { - res = EOF; - goto end; - } - unsigned char *data = buffer->data; - data[buffer->written++] = (unsigned char)c; - res = c; - } -end: - _file_unlock(stream); - return res; -} - -size_t fwrite(void const *restrict buffer, size_t size, size_t count, FILE *restrict stream) { - _file_lock(stream); - unsigned char const *bytes = (unsigned char const*)buffer; - size_t num_written; - for(num_written = 0; num_written < count; ++num_written) { - for(size_t bytes_written = 0; bytes_written < size; ++bytes_written) { - int ch = fputc(bytes[bytes_written], stream); - if(ch == EOF) { - goto end; - } - } - bytes += size; - } -end: - _file_unlock(stream); - return num_written; -} - -size_t fread(void *restrict buffer, size_t size, size_t count, FILE *restrict stream) { - _file_lock(stream); - unsigned char *bytes = (unsigned char *)buffer; - size_t num_read; - for(num_read = 0; num_read < count; ++num_read) { - for(size_t bytes_read = 0; bytes_read < size; ++bytes_read) { - int ch = fgetc(stream); - if(ch == EOF) { - goto end; - } - bytes[bytes_read] = ch; - } - bytes += size; - } -end: - _file_unlock(stream); - return num_read; -} - -int getchar(void) { - return fgetc(stdin); -} - -int putchar(int ch) { - return fputc(ch, stdout); -} - -char *fgets(char *restrict str, int count, FILE *restrict stream) { - if(count < 1) { - return str; - } - if(count == 1) { - str[0] = 0; - return str; - } - _file_lock(stream); - int i; - for(i = 0; i < count-1; ++i) { - int c = fgetc(stream); - if(c == EOF) { - stream->eof = 1; - if(i == 0) { - return NULL; - } - break; - } - str[i] = c; - if(c == '\n') { - ++i; - break; - } - } - str[i] = 0; - _file_unlock(stream); - return str; -} - -int fputs(char const *str, FILE *stream) { - _file_lock(stream); - int res = 0; - while(*str) { - int c = fputc(*str++, stream); - if(c == EOF) { - res = EOF; - break; - } - } - _file_unlock(stream); - return res; -} - -int puts(char const *str) { - int res = fputs(str, stdout); - if(res == EOF) return EOF; - return putchar('\n'); -} - -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. - DWORD pos_lo = SetFilePointer(stream->handle, offset, NULL, whence); - if(pos_lo == INVALID_SET_FILE_POINTER) { - return -1L; - } - return 0; -} - -int fsetpos(FILE *stream, const fpos_t *pos) { - LONG pos_lo = (LONG)(pos->offset & 0xffffffff); - DWORD status = SetFilePointer(stream->handle, pos_lo, NULL, 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/mem.c b/src/os_win/mem.c deleted file mode 100644 index 23b6172..0000000 --- a/src/os_win/mem.c +++ /dev/null @@ -1,129 +0,0 @@ - -#define DEFAULT_ALIGNMENT 16 - -static HANDLE heap_handle; - -static bool _is_power_of_two(size_t s) { - return (s & (s-1)) == 0; -} - -static intptr_t _align_forward(intptr_t p, size_t a) { - return (p+a-1)&~(a-1); -} - - -static void _setup_heap() { - heap_handle = GetProcessHeap(); - if (heap_handle == NULL) { - ExitProcess(-42069); - } -} - -struct AllocationTag typedef AllocationTag; -struct AllocationTag { - void *ptr; - size_t size; -}; - -// Retrieve the tag using allocated pointer -static AllocationTag *_mem_block_tag(void *user_ptr) { - AllocationTag *tag = (void *)((char *)user_ptr - sizeof(AllocationTag)); - return tag; -} - -// Calculate the block size that is enough to hold user data, the tag, and -// the necessary free space in case the pointer from HeapAlloc needs further -// alignment -static size_t _mem_min_block_size(size_t alignment, size_t user_size) { - size_t size = user_size + sizeof(AllocationTag); - if(alignment > 8) { - size += alignment; - } - return size; -} - -// Calculate the start of the user data, such that it's aligned, attach the tag -// to the allocated pointer -static void *_mem_block_setup(void *block_start, size_t block_size, size_t alignment) { - intptr_t block_start_i = (intptr_t)block_start; - intptr_t aligned_block_start_i = _align_forward(block_start_i, alignment); - intptr_t free_space = aligned_block_start_i - block_start_i; - if(free_space < sizeof(AllocationTag)) { - aligned_block_start_i += alignment; - } - AllocationTag *tag = _mem_block_tag(block_start); - tag->ptr = block_start; - tag->size = block_size; - return (void *)aligned_block_start_i; -} - -void *_mem_alloc(size_t alignment, size_t size) { - // HeapAlloc is guaranteed to return 8-byte aligned pointer, - // so if our alignment is 8 or less we don't have to overallocate. - // otherwise we'll reserve extra `alignment` bytes to later adjust our - // memory buffer according to required alignment. - size_t block_size = _mem_min_block_size(alignment, size); - void *block_start = HeapAlloc(heap_handle, 0, block_size); - memset(block_start, 0, block_size); - if(block_start == NULL) { - return NULL; - } - return _mem_block_setup(block_start, block_size, alignment); -} - -void *aligned_alloc(size_t alignment, size_t size) { - if(size == 0) { - return NULL; - } - if(alignment == 0) { - alignment = 8; - } - if(!_is_power_of_two(alignment)) { - return NULL; - } - return _mem_alloc(alignment, size); -} - -void *calloc(size_t nmemb, size_t size) { - if(nmemb == 0 || size == 0) { - return NULL; - } - if(nmemb > SIZE_MAX/size) { - return NULL; - } - return _mem_alloc(DEFAULT_ALIGNMENT, nmemb * size); -} - -void free(void *ptr) { - if(ptr == NULL) { - return; - } - AllocationTag *tag = (void *)((char *)ptr - sizeof(AllocationTag)); - HeapFree(heap_handle, 0, tag->ptr); -} - -void *malloc(size_t size) { - if(size == 0) { - return NULL; - } - return _mem_alloc(DEFAULT_ALIGNMENT, size); -} - -void *realloc(void *ptr, size_t size) { - if (ptr == NULL) { - if (size == 0) { - return NULL; - } - return _mem_alloc(DEFAULT_ALIGNMENT, size); - } else if (size == 0) { - free(ptr); - return NULL; - } else { - AllocationTag *tag = _mem_block_tag(ptr); - void *old_block = tag->ptr; - size_t new_block_size = _mem_min_block_size(DEFAULT_ALIGNMENT, size); - void *new_block = HeapReAlloc(heap_handle, 0, old_block, new_block_size); - return _mem_block_setup(new_block, new_block_size, DEFAULT_ALIGNMENT); - } -} - diff --git a/src/os_win/signal.c b/src/os_win/signal.c deleted file mode 100644 index 0298799..0000000 --- a/src/os_win/signal.c +++ /dev/null @@ -1,85 +0,0 @@ - -#define _countof(arr) (sizeof (arr) / sizeof ((arr)[0])) - -typedef struct SignalMapping { - DWORD code; - int signal; -} SignalMapping; - -static SignalMapping map[] = { - {EXCEPTION_ACCESS_VIOLATION, SIGSEGV}, - {EXCEPTION_IN_PAGE_ERROR, SIGSEGV}, - {EXCEPTION_ARRAY_BOUNDS_EXCEEDED, SIGSEGV}, - {EXCEPTION_DATATYPE_MISALIGNMENT, SIGALIGN}, - {EXCEPTION_BREAKPOINT, SIGBREAK}, - {EXCEPTION_FLT_DENORMAL_OPERAND, SIGFPE}, - {EXCEPTION_FLT_DIVIDE_BY_ZERO, SIGFPE}, - {EXCEPTION_FLT_INEXACT_RESULT, SIGFPE}, - {EXCEPTION_FLT_INVALID_OPERATION, SIGFPE}, - {EXCEPTION_FLT_OVERFLOW, SIGFPE}, - {EXCEPTION_FLT_STACK_CHECK, SIGFPE}, - {EXCEPTION_FLT_UNDERFLOW, SIGFPE}, - {EXCEPTION_ILLEGAL_INSTRUCTION, SIGILL}, - {EXCEPTION_INT_DIVIDE_BY_ZERO, SIGFPE}, - {EXCEPTION_INT_OVERFLOW, SIGFPE}, - {EXCEPTION_PRIV_INSTRUCTION, SIGILL}, - {EXCEPTION_SINGLE_STEP, SIGSTEP}, -}; - -static LONG _win32_handler(EXCEPTION_POINTERS *ExceptionInfo) { - EXCEPTION_RECORD *exception = ExceptionInfo->ExceptionRecord; - DWORD code = exception->ExceptionCode; - int signal = -1; - for(int mapping = 0; mapping != _countof(map); ++mapping) { - if(code == map[mapping].code) { - signal = map[mapping].signal; - } - } - if(signal != -1) { - raise(signal); - } - return EXCEPTION_CONTINUE_SEARCH; -} - - -static 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/os_win/thread.c b/src/os_win/thread.c deleted file mode 100644 index a720433..0000000 --- a/src/os_win/thread.c +++ /dev/null @@ -1,362 +0,0 @@ - -// Note(bumbread): -// https://gist.github.com/wbenny/6d7fc92e9b5c3194ce56bf8c60d6191d - -#pragma comment(linker, "/merge:.CRT=.rdata") - -#pragma section(".CRT$XLA", read) -__declspec(allocate(".CRT$XLA")) const PIMAGE_TLS_CALLBACK __xl_a = NULL; - -#pragma section(".CRT$XLZ", read) -__declspec(allocate(".CRT$XLZ")) const PIMAGE_TLS_CALLBACK __xl_z = NULL; - -#pragma section(".CRT$XLM", read) -__declspec(allocate(".CRT$XLM")) extern const PIMAGE_TLS_CALLBACK TlsCallbackArray; - -char _tls_start = 0; -char _tls_end = 0; -unsigned int _tls_index = 0; - -const IMAGE_TLS_DIRECTORY _tls_used = { - (ULONG_PTR)&_tls_start, - (ULONG_PTR)&_tls_end, - (ULONG_PTR)&_tls_index, - (ULONG_PTR)(&__xl_a + 1), -}; - -static void _thread_cleanup(); - -VOID NTAPI _tls_callback( - PVOID DllHandle, - DWORD Reason, - PVOID Reserved - ) -{ - switch(Reason) { - case DLL_THREAD_ATTACH: break; - case DLL_THREAD_DETACH: { - _thread_cleanup(); - } break; - case DLL_PROCESS_ATTACH: break; - case DLL_PROCESS_DETACH: break; - } - // __debugbreak(); -} - -const PIMAGE_TLS_CALLBACK TlsCallbackArray = { &_tls_callback }; - -// NOTE: debug mutexes will follow the recursive logic but error if they -// actually recurse, this is slower than doing plain logic but it helps -// debug weird mutex errors. -// -// Based on these posts: -// https://preshing.com/20120305/implementing-a-recursive-mutex/ -// https://preshing.com/20120226/roll-your-own-lightweight-mutex/ - -typedef struct UserClosure { - thrd_start_t func; - void* arg; -} UserClosure; - -static DWORD _thread_call_user(void* arg) { - UserClosure info = *((UserClosure*) arg); - int result = info.func(info.arg); - free(arg); - return (DWORD) result; -} - -thrd_t thrd_current(void) { - return (thrd_t){ GetCurrentThread() }; -} - -int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { - UserClosure* info = malloc(sizeof(UserClosure)); - if (info == NULL) { - return thrd_nomem; - } - - info->func = func; - info->arg = arg; - - // technically thrd_start_t and LPTHREAD_START_ROUTINE aren't the same - // but are close enough to be ABI compatible, namely a difference in - // signedness of the return val. - thr->handle = CreateThread(NULL, 0, _thread_call_user, info, 0, NULL); - return thr->handle != NULL ? thrd_success : thrd_error; -} - -int thrd_detach(thrd_t thr) { - return CloseHandle(thr.handle) != 0 ? thrd_success : thrd_error; -} - -int thrd_equal(thrd_t thr0, thrd_t thr1) { - return GetThreadId(thr0.handle) == GetThreadId(thr1.handle); -} - -int thrd_join(thrd_t thr, int *res) { - DWORD wait = WaitForSingleObject(thr.handle, INFINITE); - if (wait == WAIT_FAILED) { - return thrd_error; - } else if (wait == WAIT_TIMEOUT) { - return thrd_timedout; - } - - if (res != NULL) { - // snatch that exit code - DWORD ures; - if (GetExitCodeThread(thr.handle, &ures) == 0) { - CloseHandle(thr.handle); - return thrd_error; - } - - *res = (int) ures; - } - - CloseHandle(thr.handle); - return thrd_success; -} - -void thrd_yield(void) { - Sleep(0); -} - -_Noreturn void thrd_exit(int res) { - _thread_cleanup(); - ExitThread((DWORD)res); - __builtin_unreachable(); -} - -// TSS functions - -#define TSS_KEYS_MAX 1088 - -static tss_dtor_t _tss_dtors[TSS_KEYS_MAX]; -static bool _tss_init[TSS_KEYS_MAX]; - -static void _thread_cleanup() { - for(int i = 0; i != TSS_DTOR_ITERATIONS; ++i) { - for(unsigned k = 1; k != TSS_KEYS_MAX; ++k) { - if(!_tss_init[k]) { - continue; - } - void *data = TlsGetValue(k); - if(data == NULL) { - continue; - } - TlsSetValue(k, NULL); - if(_tss_dtors[k]) { - _tss_dtors[k](data); - } - } - } -} - -int tss_create(tss_t *key, tss_dtor_t dtor) { - DWORD tls_index = TlsAlloc(); - if(tls_index == TLS_OUT_OF_INDEXES) { - return thrd_error; - } - key->tls_index = tls_index; - if(tls_index >= TSS_KEYS_MAX) { - __debugbreak(); - TlsFree(tls_index); - return thrd_error; - } - _tss_init[tls_index] = true; - _tss_dtors[tls_index] = dtor; - return thrd_success; -} - -void tss_delete(tss_t key) { - _tss_init[key.tls_index] = false; - _tss_dtors[key.tls_index] = NULL; - TlsFree(key.tls_index); -} - -void *tss_get(tss_t key) { - void *data = TlsGetValue(key.tls_index); - if(data == NULL && GetLastError() != ERROR_SUCCESS) { - return NULL; - } - return data; -} - -int tss_set(tss_t key, void *val) { - if(!TlsSetValue(key.tls_index, val)) { - return thrd_error; - } - return thrd_success; -} - -// Call once - -static BOOL _call_once_trampoline(PINIT_ONCE init_once, PVOID param, PVOID *ctx) { - void (*user_func)(void) = param; - user_func(); - return TRUE; -} - -void call_once(once_flag *flag, void (*func)(void)) { - void *funcp = func; - InitOnceExecuteOnce((void *)flag, _call_once_trampoline, funcp, NULL); -} - -// Condition variables - -int cnd_init(cnd_t *cond) { - InitializeConditionVariable((void *)cond); - return thrd_success; -} - -int cnd_broadcast(cnd_t *cond) { - WakeAllConditionVariable((void *)cond); - return thrd_success; -} - -void cnd_destroy(cnd_t *cond) { - return; // Does nothing -} - -int cnd_signal(cnd_t *cond) { - WakeConditionVariable((void *)cond); - return thrd_success; -} - -int cnd_wait(cnd_t *cond, mtx_t *mtx) { - return thrd_error; // TODO after mutexes -} - -int cnd_timedwait(cnd_t *restrict cond, mtx_t *restrict mtx, const struct timespec *restrict ts) { - return thrd_error; // TODO after mutexes -} - -// Mutex functions - -void mtx_destroy(mtx_t *mtx) { - CloseHandle(mtx->semaphore); -} - -int mtx_init(mtx_t *mtx, int type) { - *mtx = (mtx_t){ - .type = type, - .semaphore = CreateSemaphore(NULL, 0, 1, NULL) - }; - - if (type == mtx_timed) { - // TODO(NeGate): implement timed mutexes - return thrd_error; - } - - return thrd_success; -} - -int mtx_lock(mtx_t *mtx) { - bool try_recursive = (mtx->type == mtx_recursive); - #ifdef _DEBUG - try_recursive = true; - #endif - - if (try_recursive) { - DWORD tid = GetCurrentThreadId(); - - if (atomic_fetch_add_explicit(&mtx->counter, 1, memory_order_acquire) > 1) { - if (tid != mtx->owner) { - WaitForSingleObject(mtx->semaphore, INFINITE); - } else { - // we recursive and already locked - #ifdef _DEBUG - if (mtx->type != mtx_recursive) { - return thrd_error; - } - #endif - } - } - - mtx->owner = tid; - mtx->recursion++; - } else { - if (atomic_fetch_add_explicit(&mtx->counter, 1, memory_order_acquire) > 1) { - WaitForSingleObject(mtx->semaphore, INFINITE); - } - } - - return thrd_success; -} - -int mtx_timedlock(mtx_t *restrict mtx, const struct timespec *restrict ts) { - return thrd_error; -} - -int mtx_trylock(mtx_t *mtx) { - bool try_recursive = (mtx->type == mtx_recursive); - #ifdef _DEBUG - try_recursive = true; - #endif - - if (try_recursive) { - DWORD tid = GetCurrentThreadId(); - - // Do we own this mutex on this thread already? - if (mtx->owner == tid) { - #ifdef _DEBUG - if (mtx->type != mtx_recursive) { - return thrd_error; - } - #endif - - atomic_fetch_add(&mtx->counter, 1); - } else { - int expected = 1; - if (!atomic_compare_exchange_strong(&mtx->counter, &expected, 0)) { - return thrd_busy; - } - - mtx->owner = tid; - } - - mtx->recursion++; - return thrd_success; - } else { - int expected = 1; - if (!atomic_compare_exchange_strong(&mtx->counter, &expected, 0)) { - return thrd_busy; - } - - return thrd_success; - } -} - -int mtx_unlock(mtx_t *mtx) { - bool try_recursive = (mtx->type == mtx_recursive); - #if _DEBUG - try_recursive = true; - #endif - - if (try_recursive) { - DWORD tid = GetCurrentThreadId(); - if (tid != mtx->owner) return thrd_error; - - unsigned long recur = --mtx->recursion; - if (recur == 0) { - mtx->owner = 0; - } - - if (atomic_fetch_sub_explicit(&mtx->counter, 1, memory_order_release) > 0) { - if (recur == 0) ReleaseSemaphore(mtx->semaphore, 1, NULL); - else { - #ifdef _DEBUG - if (mtx->type != mtx_recursive) { - return thrd_error; - } - #endif - } - } - } else { - // release? - if (atomic_fetch_sub_explicit(&mtx->counter, 1, memory_order_release) > 0) { - ReleaseSemaphore(mtx->semaphore, 1, NULL); - } - } - - return thrd_success; -} diff --git a/src/os_win/time.c b/src/os_win/time.c deleted file mode 100644 index 3beadd8..0000000 --- a/src/os_win/time.c +++ /dev/null @@ -1,439 +0,0 @@ - -#define NS_PER_SEC 1000000000 -#define NS_PER_MS 1000000 - -#define TIME_TICKS_PER_SEC 1000000000ULL -#define FT_TICKS_BEFORE_UNIX_EPOCH 116444736000000000ULL - -typedef struct tm tm_t; - -// Store the time since we started running the process -static uint64_t timer_freq; -static uint64_t timer_start; - -// Initialize timers - -static void _setup_timer(void) { - LARGE_INTEGER freq, start; - QueryPerformanceFrequency(&freq); - QueryPerformanceCounter(&start); - timer_start = start.QuadPart; - timer_freq = freq.QuadPart; -} - -// Timestamp utilitity functions - -static ULONGLONG _time_filetime_to_ns(FILETIME ft) { - ULARGE_INTEGER ft64 = { - .LowPart = ft.dwLowDateTime, - .HighPart = ft.dwHighDateTime, - }; - ULONGLONG fticks = ft64.QuadPart; - return fticks * 100; -} - -static ULONGLONG _time_utc_ns() { - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - ULONGLONG ticks = _time_filetime_to_ns(ft); - ULONGLONG unix_ns = (ticks - FT_TICKS_BEFORE_UNIX_EPOCH*100); - return unix_ns; -} - -static ULONGLONG _time_mono_ns() { - ULONGLONG time_ms = GetTickCount64(); - ULONGLONG time_ns = time_ms * NS_PER_MS; - return time_ns; -} - -static ULONGLONG _time_process_ns() { - FILETIME _1; - FILETIME _2; - FILETIME ktime; - FILETIME utime; - HANDLE current_process = GetCurrentProcess(); - if(GetProcessTimes(current_process, &_1, &_2, &ktime, &utime) == 0) { - abort(); - } - ULONGLONG kernel_time = _time_filetime_to_ns(ktime); - ULONGLONG user_time = _time_filetime_to_ns(utime); - ULONGLONG cpu_time = kernel_time + user_time; - return cpu_time; -} - -static ULONGLONG _time_thread_ns() { - FILETIME _1; - FILETIME _2; - FILETIME ktime; - FILETIME utime; - HANDLE current_thread = GetCurrentThread(); - if(GetThreadTimes(current_thread, &_1, &_2, &ktime, &utime) == 0) { - abort(); - } - ULONGLONG kernel_time = _time_filetime_to_ns(ktime); - ULONGLONG user_time = _time_filetime_to_ns(utime); - ULONGLONG cpu_time = kernel_time + user_time; - return cpu_time; -} - -// Timer functions - -clock_t clock(void) { - LARGE_INTEGER curr; - if (!QueryPerformanceCounter(&curr)) { - return -1; - } - if (curr.QuadPart < timer_start) { - return -1; - } - clock_t ticks = curr.QuadPart - timer_start; - // Same as (ticks / timer_freq * CLOCKS_PER_SEC) but more precise - return ticks / timer_freq * CLOCKS_PER_SEC - + ticks % timer_freq * CLOCKS_PER_SEC / timer_freq; -} - -time_t time(time_t *timer) { - ULONGLONG unix_nanos = _time_utc_ns(); - time_t timer_ticks = unix_nanos; - if(timer != NULL) { - *timer = timer_ticks; - } - return timer_ticks; -} - -double difftime(time_t time1, time_t time0) { - double resolution = (double)TIME_TICKS_PER_SEC; - if(time1 >= time0) return (double)(time1 - time0) / resolution; - else return -(double)(time0 - time1) / resolution; -} - -int timespec_get(struct timespec *ts, int base) { - ULONGLONG current_ns; - switch(base) { - case TIME_UTC: current_ns = _time_utc_ns(); break; - case TIME_MONOTONIC: current_ns = _time_mono_ns(); break; - case TIME_ACTIVE: current_ns = _time_process_ns(); break; - case TIME_THREAD_ACTIVE: current_ns = _time_thread_ns(); break; - default: return 0; - } - ts->tv_sec = current_ns / NS_PER_SEC; - ts->tv_nsec = current_ns; - return base; -} - -int timespec_getres(struct timespec *ts, int base) { - switch(base) { - case TIME_UTC: return NS_PER_SEC; - case TIME_MONOTONIC: return NS_PER_SEC; - case TIME_ACTIVE: return NS_PER_SEC; - case TIME_THREAD_ACTIVE: return NS_PER_SEC; - default: return 0; - } -} - -// Human-readable time - -const int _days_in_month[12] = { - 31,28, 31,30,31, 30,31,31, 30,31,30, 31 -}; - -const int _month_days_since_year_start[12] = { - 0, - 31, - 31+28, - 31+28+31, - 31+28+31+30, - 31+28+31+30+31, - 31+28+31+30+31+30, - 31+28+31+30+31+30+31, - 31+28+31+30+31+30+31+31, - 31+28+31+30+31+30+31+31+30, - 31+28+31+30+31+30+31+31+30+31, - 31+28+31+30+31+30+31+31+30+31+30, -}; - -static bool _is_leap_year(int year) { - if(year % 400 == 0) { - return true; - } - if(year % 100 == 0) { - return false; - } - if(year % 4 == 0) { - return true; - } - return false; -} - -static int _leap_years_before(int year) { - year--; - return (year / 4) - (year / 100) + (year / 400); -} - -static int _leap_years_between(int start, int end) { - return _leap_years_before(end) - _leap_years_before(start + 1); -} - -static int _whole_days_since_year_start(int year, int mon, int day) { - int days = _month_days_since_year_start[mon] + day; - if(mon > 1 || (mon == 1 && day > 27)) { - if(_is_leap_year(year)) { - days += 1; - } - } - return days; -} - -static void _tm_adjust(tm_t *time) { - long long year = 1900 + time->tm_year; - long long mon = time->tm_mon; - long long day = time->tm_mday - 1; - long long hour = time->tm_hour; - long long min = time->tm_min; - long long sec = time->tm_sec; - // Adjust - if(sec < 0) { - min -= (-sec+59)/60; - sec = (sec%60 + 60) % 60; - } - else if(sec >= 60) { - min += sec / 60; - sec %= 60; - } - if(min < 0) { - hour -= (-min+59)/60; - min = (min%60 + 60) % 60; - } - else if(min >= 60) { - hour += min / 60; - min %= 60; - } - if(hour < 0) { - day -= (-hour+23)/24; - hour = (hour%24 + 24) % 24; - } - else if(hour >= 24) { - day += hour / 24; - hour %= 24; - } - if(mon < 0) { - year -= (-mon+11)/12; - mon = (mon%12+12)%12; - } - else if(mon >= 12) { - year += mon / 12; - mon %= 12; - } - if(day < 0) { - for(;;) { - int mon_prev = mon - 1; - int year_prev = year; - if(mon_prev == -1) { - mon_prev = 11; - year_prev -= 1; - } - int days_in_prev_month = _days_in_month[mon_prev]; - if(mon_prev == 1 && _is_leap_year(year_prev)) { - days_in_prev_month += 1; - } - if(-day > days_in_prev_month) { - day += days_in_prev_month; - mon -= 1; - if(mon == -1) { - mon = 11; - year -= 1; - } - } - else { - break; // Can't subtract any whole months, exit the loop - } - } - if(day < 0) { - mon -= 1; - day = _days_in_month[mon] + day; - if(mon == -1) { - mon = 11; - year -= 1; - } - } - } - else { - for(;;) { - int days_in_month = _days_in_month[mon]; - if(mon == 1 && _is_leap_year(year)) { - days_in_month += 1; - } - if(day < days_in_month) { - break; - } - day -= days_in_month; - mon += 1; - } - } - // Refill the struct with normalized time - time->tm_year = year - 1900; - time->tm_mon = mon; - time->tm_mday = day + 1; - time->tm_hour = hour; - time->tm_min = min; - time->tm_sec = sec; -} - -time_t mktime(tm_t *time) { - // Get the human-readable time from the structure - _tm_adjust(time); - long long year = 1900 + time->tm_year; - long long mon = time->tm_mon; - long long day = time->tm_mday - 1; - long long hour = time->tm_hour; - long long min = time->tm_min; - long long sec = time->tm_sec; - if(year < 1970) { - return (time_t)(-1); - } - // Calculate unix timestamp - time_t timestamp; - timestamp = (year - 1970) * 365 + _leap_years_between(1970, year); - time_t days_since_year = _whole_days_since_year_start(year, mon, day); - timestamp = timestamp + days_since_year; - time_t days_since_epoch = timestamp; - timestamp = timestamp * 24 + hour; - timestamp = timestamp * 60 + min; - timestamp = timestamp * 60 + sec; - timestamp = timestamp * NS_PER_SEC; - // Refill the week day and year day - time->tm_wday = (days_since_epoch % 7 + 4) % 7; // 1970-01-01 is thursday (wday=4) - time->tm_yday = days_since_year; - time->tm_isdst = -1; - return timestamp; -} - -// Breaking-down of the time - -tm_t *gmtime(const time_t *timer) { - tm_t *time = malloc(sizeof(tm_t)); - time_t timestamp = *timer; - timestamp /= NS_PER_SEC; - time->tm_sec = timestamp % 60; - timestamp /= 60; - time->tm_min = timestamp % 60; - timestamp /= 60; - time->tm_hour = timestamp % 24; - timestamp /= 24; - int year = 1970; - int days = timestamp; - int days_since_epoch = days; - // Start subtracting 400,100,4-year-stretches - const int DAYS_IN_400_YEARS = 365 * 400 + 97; - const int DAYS_IN_100_YEARS = 365 * 100 + 24; - const int DAYS_IN_4_YEARS = 365 * 4 + 1; - year += (days / DAYS_IN_400_YEARS) * 400; - days %= DAYS_IN_400_YEARS; - year += (days / DAYS_IN_100_YEARS) * 100; - days %= DAYS_IN_100_YEARS; - year += (days / DAYS_IN_4_YEARS) * 4; - days %= DAYS_IN_4_YEARS; - // Count remaining up-to 3 years in a loop - for(;;) { - int this_year_days = 365 + _is_leap_year(year); - if(days < this_year_days) { - break; - } - year += 1; - days -= this_year_days; - } - // Find the current month - int days_since_year = days; - int month = 0; - for(;;) { - int days_in_month = _days_in_month[month] + _is_leap_year(year); - if(days < days_in_month) { - break; - } - days -= days_in_month; - month += 1; - } - time->tm_year = year - 1900; - time->tm_mon = month; - time->tm_mday = days + 1; - time->tm_wday = (days_since_epoch % 7 + 4) % 7; // 1970-01-01 is thursday (wday=4) - time->tm_yday = days_since_year; - time->tm_isdst = -1; - return time; -} - -static bool _offset_utc_time_to_local(tm_t *time) { - TIME_ZONE_INFORMATION tz; - if(GetTimeZoneInformation(&tz) == TIME_ZONE_ID_INVALID) { - return false; - } - int bias = tz.Bias; - time->tm_min -= bias; - mktime(time); - return true; -} - -tm_t *localtime(const time_t *timer) { - tm_t *utc_time = gmtime(timer); - if(!_offset_utc_time_to_local(utc_time)) { - return NULL; - } - return utc_time; -} - -// String formatting - -static void _time_str_print2(char *str, int v) { - char hi = (v/10)%10 + '0'; - char lo = v%10 + '0'; - str[0] = hi; - str[1] = lo; -} - -static void _time_str_print4(char *str, int v) { - char c1 = (v/1000)%10 + '0'; - char c2 = (v/100)%10 + '0'; - char c3 = (v/10)%10 + '0'; - char c4 = v%10 + '0'; - str[0] = c1; - str[1] = c2; - str[2] = c3; - str[3] = c4; -} - -char *asctime(const struct tm *time) { - static const char wday_name[7][5] = { - "Sun ", "Mon ", "Tue ", "Wed ", "Thu ", "Fri ", "Sat ", - }; - static const char mon_name[12][5] = { - "Jan ", "Feb ", "Mar ", "Apr ", "May ", "Jun ", - "Jul ", "Aug ", "Sep ", "Oct ", "Nov ", "Dec ", - }; - char *buf = calloc(1, 26); - if(buf == NULL) { - return NULL; - } - strcpy(buf, wday_name[time->tm_wday]); - strcat(buf, mon_name[time->tm_mon]); - char *str = buf+8; - _time_str_print2(str+0, time->tm_mday); - _time_str_print2(str+3, time->tm_hour); - _time_str_print2(str+6, time->tm_min); - _time_str_print2(str+9, time->tm_sec); - str[2] = ' '; - str[5] = ':'; - str[8] = ':'; - str[11] = ' '; - _time_str_print4(str+12, 1900+time->tm_year); - str[16] = '\n'; - str[17] = 0; - return buf; -} - -char *ctime(const time_t *timer) { - return asctime(localtime(timer)); -} - -size_t strftime(char *restrict s, size_t size, const char *restrict fmt, const tm_t *restrict time) { - return 0; -} diff --git a/src/os_win/win.h b/src/os_win/win.h deleted file mode 100644 index ea936d4..0000000 --- a/src/os_win/win.h +++ /dev/null @@ -1,13 +0,0 @@ - -#pragma once - -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include - -static void _setup_timer(void); -static void _setup_eh(); -static void _setup_heap(); -static void _io_close(); \ No newline at end of file diff --git a/src/stdlib/algorithm.c b/src/stdlib/algorithm.c deleted file mode 100644 index 5e0ce28..0000000 --- a/src/stdlib/algorithm.c +++ /dev/null @@ -1,82 +0,0 @@ - -int abs(int n) { - if(n < 0) return -n; - return n; -} - -long absl(long n) { - if(n < 0) return -n; - return n; -} - -long long absll(long long n) { - if(n < 0) return -n; - return n; -} - -div_t div(int x, int y) { - div_t res; - res.quot = x / y; - res.rem = x % y; - return res; -} - -ldiv_t ldiv(long x, long y) { - ldiv_t res; - res.quot = x / y; - res.rem = x % y; - return res; -} - -lldiv_t lldiv(long long x, long long y) { - lldiv_t res; - res.quot = x / y; - res.rem = x % y; - return res; -} - -const void *bsearch( - const void *key, - const void *base, - size_t nmemb, - size_t size, - int (*compar)(const void *, const void *) -) { - size_t left = 0; - size_t right = nmemb; - - const char* buffer = base; - while (left < right) { - size_t middle = (left + right) / 2; - - int cmp = compar(&buffer[middle * size], key); - if (cmp == 0) return &buffer[left * size]; - if (cmp < 0) left = middle + 1; - else right = middle; - } - - return NULL; -} - -void qsort( - void *base, - size_t nmemb, - size_t size, - int (*diff)(const void *, const void *) -) { - // Ima be doing bublbe sort for now - char *bytes = base; - for(size_t i = 0; i != nmemb-1; ++i) { - for(size_t j = 0; j < nmemb-i-1; ++j) { - char *this = bytes+j*size; - char *that = this+size; - if(diff(this, that) > 0) { - for(size_t b=0;b!=size;++b) { - char temp = this[b]; - this[b] = that[b]; - that[b] = temp; - } - } - } - } -} diff --git a/src/stdlib/multibyte.c b/src/stdlib/multibyte.c deleted file mode 100644 index cb660f0..0000000 --- a/src/stdlib/multibyte.c +++ /dev/null @@ -1,21 +0,0 @@ - -int mblen(const char *s, size_t n) { - return mbtowc((wchar_t*)0, s, n); -} - -int mbtowc(wchar_t *restrict pwc, const char *restrict s, size_t n) { - return 0; -} - -size_t mbstowcs(wchar_t *restrict pwcs, const char *restrict s, size_t n) { - return 0; -} - -int wctomb(char *s, wchar_t wchar) { - return 0; -} - -size_t wcstombs(char *restrict s, const wchar_t *restrict pwcs, size_t n) { - return 0; -} - diff --git a/src/stdlib/random.c b/src/stdlib/random.c deleted file mode 100644 index fec9654..0000000 --- a/src/stdlib/random.c +++ /dev/null @@ -1,15 +0,0 @@ - -// TODO: the code for rand/srand was shamelessly copied -// from C11 standard's example and is a simple LCG. -// gotta implement a better random function, or no idc - -static int last_random_number; - -int rand(void) { - last_random_number = last_random_number * 1103515245 + 12345; - return (unsigned int)(last_random_number/65536) % RAND_MAX; -} - -void srand(unsigned int seed) { - last_random_number = seed; -} diff --git a/src/string.c b/src/string.c deleted file mode 100644 index 33c9ea7..0000000 --- a/src/string.c +++ /dev/null @@ -1,243 +0,0 @@ - -void *memcpy(void *restrict to, void const *restrict from, size_t n) { - u8 *restrict dst = to; - u8 const *restrict src = from; - while (n--) { - *dst++ = *src++; - } - return dst; -} - -void *memmove(void *to, const void *from, size_t n) { - u8 *dst = to; - u8 const *src = from; - if (src != dst) { - if (src < dst) { - // reverse copy - for (size_t i = n; i--;) dst[i] = src[i]; - } else { - // normal copy - for (size_t i = 0; i < n; i++) dst[i] = src[i]; - } - } - return dst; -} - -char *strcpy(char *restrict dst, char const *restrict src) { - size_t i = 0; - for(i = 0; src[i]; ++i) { - dst[i] = src[i]; - } - dst[i] = 0; - return dst; -} - -char *strncpy(char *restrict dst, char const *restrict src, size_t n) { - size_t i; - for(i = 0; i != n && src[i]; ++i) { - dst[i] = src[i]; - } - for(; i != n; ++i) { - dst[i] = 0; - } - return dst; -} - - -char *strcat(char *restrict dst, const char *restrict src) { - size_t start = strlen(dst); - return strcpy(dst+start, src); -} - -char *strncat(char *restrict dst, char const *restrict src, size_t n) { - size_t start = strlen(dst); - strncpy(dst+start, src, n); - return dst; -} - - -int memcmp(void const *p1, void const *p2, size_t n) { - u8 const *s1 = p1; - u8 const *s2 = p2; - size_t i; - for(i = 0; i != n; ++i) { - if(s1[i] != s2[i]) break; - } - if(i != n) { - if(s1[i] < s2[i]) return -1; - if(s1[i] > s2[i]) return 1; - } - return 0; -} - -void *memset(void *s, int c, size_t n) { - u8 *restrict buf = s; - while (n--) { - *buf++ = c; - } - return s; -} - -int strcmp(char const *s1, char const *s2) { - size_t i; - for(i = 0; s1[i] && s2[i]; ++i) { - if(s1[i] != s2[i]) break; - } - if(s1[i] < s2[i]) return -1; - if(s1[i] > s2[i]) return +1; - return 0; -} - -int strncmp(const char *s1, const char *s2, size_t n) { - size_t i; - for(i = 0; i != n && s1[i] && s2[i]; ++i) { - if(s1[i] != s2[i]) break; - } - if(s1[i] < s2[i]) return -1; - if(s1[i] > s2[i]) return +1; - return 0; -} - -int strcoll(const char *s1, const char *s2) { - return strcmp(s1, s2); -} - -// TODO: I don't quite understand the intent nor use behind this function -// so I'm just going to ignore locales for now. -size_t strxfrm(char *restrict s1, const char *restrict s2, size_t n) { - size_t len = strlen(s2); - if(s1 != NULL && n != 0) { - for(size_t i = 0; i != n; ++i) { - *s1 = *s2; - } - } - return len; -} - -void *memchr(const void *ptr, int c, size_t n) { - const char *s = ptr; - for(size_t i = 0; i != n; ++i) { - if(s[i] == c) { - // Casting away const because clang warnings - return (void *)(s+i); - } - } - return NULL; -} - -char *strchr(const char *s, int c) { - do { - if(*s == c) return (char *)s; - } while(*s++); - return NULL; -} - -size_t strspn(const char *s1, const char *s2) { - size_t i = 0; - for(; *s1; ++s1) { - if(strchr(s2, *s1) == NULL) { - break; - } - ++i; - } - return i; -} - -size_t strcspn(const char *s1, const char *s2) { - size_t i = 0; - for(; *s1; ++s1) { - if(strchr(s2, *s1) != NULL) { - break; - } - ++i; - } - return i; -} - -char *strpbrk(const char *s1, const char *s2) { - while(*s1) { - if(strchr(s2, *s1) == NULL) { - break; - } - ++s1; - } - return (char *)s1; -} - -char *strrchr(const char *s, int c) { - char const *last = NULL; - for(; *s != 0; ++s) { - if(*s == c) last = s; - } - return (char *)last; -} - -char *strstr(const char *s1, const char *s2) { - if(*s2 == 0) return (char *)s1; - size_t len = strlen(s2); - for(; *s1 != 0; ++s1) { - if(strncmp(s1, s2, len) == 0) return (char *)s1; - } - return NULL; -} - -// TODO: there may be restrict-related UB -char *strtok(char *restrict s1, const char *restrict s2) { - static char *str; - return strtok_r(s1, s2, &str); -} - -char *strtok_r(char *restrict s1, const char *restrict s2, char **restrict ctx) { - if(s1 != NULL) *ctx = s1; - if(*ctx == NULL) return NULL; - - size_t junk_len = strspn(*ctx, s2); - char *tok_start = *ctx + junk_len; - if(*tok_start == 0) { - *ctx = NULL; - return NULL; - } - - size_t tok_len = strcspn(*ctx, s2); - - char *tok_end = tok_start + tok_len; - *tok_end = 0; - *ctx = tok_end+1; - - return tok_start; -} - -char *strerror(int errnum) { - switch(errnum) { - case 0: return "No errors"; - case EDOM: return "Value is outside of domain of the function"; - case EILSEQ: return "Illegal byte sequence"; - case ERANGE: return "Value is out of range"; - } - return "Unkown error"; -} - -size_t strlen(const char *s) { - size_t i = 0; - while (s[i]) { - i++; - } - return i; -} - -size_t strnlen_s(const char *s, size_t maxsize) { - if (s == NULL) return 0; - size_t i = 0; - while (s[i] && i < maxsize) { - i++; - } - return i; -} - -char *strdup(const char *str1) { - if(str1 == NULL) return NULL; - size_t len = strlen(str1); - char *copy = calloc(len+1, 1); - strcpy(copy, str1); - return copy; -} diff --git a/src/uchar.c b/src/uchar.c deleted file mode 100644 index 0c94c00..0000000 --- a/src/uchar.c +++ /dev/null @@ -1,126 +0,0 @@ - -// size_t mbrtoc16( -// char16_t *restrict pc16, -// char const *restrict s, -// size_t n, -// mbstate_t *restrict ps -// ) { -// // Figure out the conversion state -// static mbstate_t static_mbstate = {0}; -// if(ps == NULL) ps = &static_mbstate; -// if(s == NULL) { -// *ps = (mbstate_t) {0xd800}; -// return 0; -// } -// // Check leftovers, using 0xd800 as "no leftover" marker because it -// // doesn't encode a valid character. -// if(ps->leftover == 0xd800) { -// // Decode the UTF-8 encoded codepoint -// char32_t code_point; -// int mblen = utf8_chdec((char8_t *)s, n, &code_point); -// if(mblen == UNI_ESTRLN) return (size_t)(-2); -// if(mblen <= 0) goto invalid_seq; -// // Encode the codepoint into UTF-16 string -// char16_t str[2]; -// int c16len = utf16_chenc(str, 2, code_point); -// if(c16len <= 0) goto invalid_seq; -// // Assign the decoded UTF-16 character, decide leftover -// if(pc16 != NULL) *pc16 = str[0]; -// ps->leftover = (c16len == 2? str[1] : 0xd800); -// return (size_t)mblen; -// } -// else { -// // Otherwise use and reset the leftover -// if(pc16 != NULL) *pc16 = ps->leftover; -// ps->leftover = 0xd800; -// return (size_t)(-3); -// } -// invalid_seq: -// errno = EILSEQ; -// return (size_t)(-1); -// } - - - -// size_t c16rtomb( -// char *restrict s, -// char16_t c16, -// mbstate_t *restrict ps -// ) { -// // Figure out conversion state -// static mbstate_t static_mbstate = {0}; -// if(ps == NULL) ps = &static_mbstate; -// if(s == NULL) { -// *ps = (mbstate_t) {0xd800}; -// return 0; -// } -// char32_t codepoint_to_write; -// // Check whether a high surrogate was detected in a previous call to the -// // function. If not, the high_surrogate value is 0xd800 -// if(ps->high_surrogate == 0xd800) { -// // If c16 is a surrogate record it, or throw an error -// if(uni_is_hsur(c16)) { -// ps->high_surrogate = c16; -// return 0; -// } -// else if(uni_is_lsur(c16)) { -// goto invalid_char; -// } -// // We'll just write c16 -// codepoint_to_write = c16; -// } -// // If high surrogate exists, the next character must be a low surrogate -// // so we'll write a codepoint made out of high and low surrogates -// else if(uni_is_lsur(c16)) { -// codepoint_to_write = uni_surtoc(ps->high_surrogate, c16); -// } -// else goto invalid_char; -// // Write the codepoint that we decided to write to multibyte string -// int written_len = utf8_chenc((char8_t *)s, 4, codepoint_to_write); -// if(written_len < 0) { -// goto invalid_char; -// } -// s[written_len] = 0; -// return (size_t)written_len; -// invalid_char: -// errno = EILSEQ; -// return (size_t)(-1); -// } - -// size_t mbrtoc32( -// char32_t *restrict pc32, -// char const *restrict s, -// size_t n, -// mbstate_t *restrict ps -// ) { -// if(s == NULL) { -// return 0; -// } -// char32_t code_point; -// int mblen = utf8_chdec((char8_t *)s, n, &code_point); -// if(mblen == UNI_ESTRLN) return (size_t)(-2); -// if(mblen <= 0) { -// errno = EILSEQ; -// return (size_t)(-1); -// } -// *pc32 = code_point; -// if(code_point == 0) return 0; -// return (size_t)mblen; -// } - -// size_t c32rtomb( -// char *restrict s, -// char32_t c32, -// mbstate_t *restrict ps -// ) { -// if(s == NULL) { -// *ps = (mbstate_t) {0}; -// return 0; -// } -// int mblen = utf8_chenc((char8_t *)s, 4, c32); -// if(mblen <= 0) { -// errno = EILSEQ; -// return (size_t)(-1); -// } -// return (size_t)mblen; -// } diff --git a/src/util.c b/src/util.c deleted file mode 100644 index bbfd4ce..0000000 --- a/src/util.c +++ /dev/null @@ -1,76 +0,0 @@ - -// Some of these more horizontal screen space than I consider healthy, that's -// why I define shorter versions for some of the types. long integers are -// special offenders - -// The other part of this file are the convenience macros that could be used -// mostly anywhere in the ciabatta implementation. - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; - -typedef int8_t i8; -typedef int16_t i16; -typedef int32_t i32; -typedef int64_t i64; - -typedef int_least8_t li8; -typedef int_least16_t li16; -typedef int_least32_t li32; -typedef int_least64_t li64; - -typedef int_fast8_t fi8; -typedef int_fast16_t fi16; -typedef int_fast32_t fi32; -typedef int_fast64_t fi64; - -typedef long int intl; -typedef long long int intll; -typedef unsigned int intu; -typedef unsigned long int intul; -typedef unsigned long long int intull; - -typedef float f32; -typedef double f64; -typedef long double fl64; - -typedef wchar_t wchar; - -#define IN_RANGE(start, v, end) ((start) <= (v) && (v) <= (end)) - -#define CONCAT(a,b) a ## b -#define STR_(a) #a -#define STR(a) STR_(a) - -#define F64_BITS(x) ((union {f64 f; u64 i;}){.f=x}).i -#define F64_CONS(x) ((union {f64 f; u64 i;}){.i=x}).f -#define F32_BITS(x) ((union {f32 f; u32 i;}){.f=x}).i -#define F32_CONS(x) ((union {f32 f; u32 i;}){.i=x}).f - -#define F64_MANT_MASK UINT64_C(0xfffffffffffff) -#define F64_MANT_MAX UINT64_C(0xfffffffffffff) -#define F64_MANT_BITS 52 -#define F64_BEXP_BITS 11 -#define F64_BEXP_MASK 0x7ff -#define F64_BEXP_MAX 0x7ff - -#define F32_MANT_MASK 0x7fffff -#define F32_MANT_MAX 0x7fffff -#define F32_MANT_BITS 23 -#define F32_BEXP_BITS 8 -#define F32_BEXP_MASK 0xff -#define F32_BEXP_MAX 0xff - - -#define F64_SIGN(bits) (bits >> (F64_MANT_BITS + F64_BEXP_BITS)) -#define F64_BEXP(bits) ((bits >> F64_MANT_BITS) & F64_BEXP_MASK) -#define F64_MANT(bits) ((bits) & F64_MANT_MASK) - -#define F32_SIGN(bits) (bits >> (F32_MANT_BITS + F32_BEXP_BITS)) -#define F32_BEXP(bits) ((bits >> F32_MANT_BITS) & F32_BEXP_MASK) -#define F32_MANT(bits) ((bits) & F32_MANT_MASK) - -#define MIN(a,b) ((a)<(b)?(a):(b)) -#define MAX(a,b) ((a)>(b)?(a):(b)) diff --git a/src/wchar.c b/src/wchar.c deleted file mode 100644 index 124a5a4..0000000 --- a/src/wchar.c +++ /dev/null @@ -1,99 +0,0 @@ - -size_t wcslen(const wchar_t *s) { - size_t len = 0; - while(s[len++]); - return len; -} - -wchar_t *wmemset(wchar_t *str, wchar_t c, size_t n) { - while(n--) { - str[n] = c; - } - return str; -} - -wchar_t *wmemmove(wchar_t *dst, wchar_t const *src, size_t n) { - if(dst != src) { - if(dst < src) { - for (size_t i = n; i--;) dst[i] = src[i]; - } else { - for (size_t i = 0; i < n; i++) dst[i] = src[i]; - } - } - return dst; -} - -wchar_t *wmemcpy(wchar_t *restrict dst, wchar_t const *restrict src, size_t n) { - while(n--) dst[n] = src[n]; - return (wchar_t *)dst; -} - -wchar_t *wcscpy(wchar_t *restrict dst, wchar_t const *restrict src) { - size_t i; - for(i = 0; src[i]; ++i) { - dst[i] = src[i]; - } - dst[i] = 0; - return (wchar_t *)dst; -} - -wchar_t *wcsncpy(wchar_t *restrict dst, wchar_t const *restrict src, size_t n) { - // TODO: more than one null terminator, not write if n was reached - size_t i; - for(i = 0; i != n && src[i]; ++i) { - dst[i] = src[i]; - } - dst[i] = 0; - return (wchar_t *)dst; -} - -wchar_t *wcscat(wchar_t *restrict dst, wchar_t const *restrict src) { - size_t dst_len = wcslen(dst); - size_t i; - for(i = 0; src[i]; ++i) { - dst[dst_len + i] = src[i]; - } - dst[dst_len + i] = 0; - return (wchar_t *)dst; -} - -wchar_t *wcsncat(wchar_t *restrict dst, wchar_t const *restrict src, size_t n) { - size_t dst_len = wcslen(dst); - size_t i; - for(i = 0; i != n && src[i]; ++i) { - dst[dst_len + i] = src[i]; - } - dst[dst_len + i] = 0; - return (wchar_t *)dst; -} - -int wcscmp(wchar_t const *s1, wchar_t const *s2) { - size_t i; - for(i = 0; s1[i] && s2[i]; ++i) { - if(s1[i] != s2[i]) break; - } - if(s1[i] < s2[i]) return -1; - if(s1[i] > s2[i]) return 1; - return 0; -} - -int wcsncmp(wchar_t const *s1, wchar_t const *s2, size_t n) { - size_t i; - for(i = 0; i != n && s1[i] && s2[i]; ++i) { - if(s1[i] != s2[i]) break; - } - if(s1[i] < s2[i]) return -1; - if(s1[i] > s2[i]) return 1; - return 0; -} - -int wmemcmp(wchar_t const *s1, wchar_t const *s2, size_t n) { - // TODO: OOB when ranges are equal - size_t i; - for(i = 0; i != n; ++i) { - if(s1[i] != s2[i]) break; - } - if(s1[i] < s2[i]) return -1; - if(s1[i] > s2[i]) return 1; - return 0; -} diff --git a/src/wctype.c b/src/wctype.c deleted file mode 100644 index 1bc1407..0000000 --- a/src/wctype.c +++ /dev/null @@ -1,121 +0,0 @@ - -int iswctype(wint_t wc, wctype_t desc) { - return desc(wc); -} - -wctype_t wctype(const char *property) { - if(!strcmp(property, "alnum")) return iswalnum; - if(!strcmp(property, "alpha")) return iswalpha; - if(!strcmp(property, "blank")) return iswblank; - if(!strcmp(property, "cntrl")) return iswcntrl; - if(!strcmp(property, "digit")) return iswdigit; - if(!strcmp(property, "graph")) return iswgraph; - if(!strcmp(property, "lower")) return iswlower; - if(!strcmp(property, "print")) return iswprint; - if(!strcmp(property, "punct")) return iswpunct; - if(!strcmp(property, "space")) return iswspace; - if(!strcmp(property, "upper")) return iswupper; - if(!strcmp(property, "xdigit")) return iswxdigit; - return NULL; -} - -wint_t towctrans(wint_t wc, wctrans_t desc) { - return desc(wc); -} - -wctrans_t wctrans(const char *property) { - if(!strcmp(property, "tolower")) return towlower; - if(!strcmp(property, "toupper")) return towupper; - return NULL; -} - -int iswalnum(wint_t wc) { - return iswalpha(wc) || iswdigit(wc); -} - -int iswalpha(wint_t wc) { - return iswupper(wc) || iswlower(wc); -} - -int iswblank(wint_t wc) { - return wc == ' ' || wc == '\t'; -} - -int iswcntrl(wint_t wc) { - return 0; - //return uni_classify(wc) == UCHAR_Cc; -} - -int iswdigit(wint_t wc) { - return '0' <= wc && wc <= '9'; -} - -int iswgraph(wint_t wc) { - return iswprint(wc) && !iswspace(wc); -} - -int iswlower(wint_t wc) { - return 0; - // return uni_classify(wc) == UCHAR_Ll; -} - -int iswprint(wint_t wc) { - // switch(uni_classify(wc)) { - // case UCHAR_Cc: - // case UCHAR_Cf: - // case UCHAR_Co: - // case UCHAR_Cs: - // return 0; - // } - return 1; -} - -int iswpunct(wint_t wc) { - // switch(uni_classify(wc)) { - // case UCHAR_Pc: - // case UCHAR_Pd: - // case UCHAR_Pe: - // case UCHAR_Pf: - // case UCHAR_Pi: - // case UCHAR_Po: - // case UCHAR_Ps: - // case UCHAR_Sk: - // case UCHAR_Sc: - // case UCHAR_Sm: - // case UCHAR_So: - // return 1; - // } - return 0; -} - -int iswspace(wint_t wc) { - switch(wc) { - case ' ': - case '\t': - case '\v': - case '\r': - case '\n': - case '\f': - return 1; - } - return 0; -} - -int iswupper(wint_t wc) { - // return uni_classify(wc) == UCHAR_Lu; - return 0; -} - -int iswxdigit(wint_t wc) { - return iswdigit(wc) || ('a'<=wc && wc<='f') || ('A'<= wc && wc<='F'); -} - -wint_t towlower(wint_t wc) { - // return uni_tolower(wc); - return wc; -} - -wint_t towupper(wint_t wc) { - return wc; - // return uni_toupper(wc); -} diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..78865b9 --- /dev/null +++ b/test.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +if [ "$1" != "-shared" ]; then + clang -static -nostdlib tests/empty.c lib/ciabatta.a -Iinclude +else + clang -fPIE tests/empty.c -c -o tests/empty.o + ld -no-pie -nostdlib lib/entry.o tests/empty.o lib/ciabatta.so lib/ctors.o -Iinclude +fi \ No newline at end of file diff --git a/tests/crt.c b/tests/crt.c index e0b554d..d05cb78 100644 --- a/tests/crt.c +++ b/tests/crt.c @@ -1,799 +1,10 @@ -// Framework for testing of the CRT library. This file is supposed to be linked -// to the ciabatta, so there is a possibility that the runtime that the testing -// suite relies on is broken, which is why to decrease the chance of it crashing -// because of that, I minimize that dependency. Therefore this testing suite -// avoids the following: -// - Heap allocations -// - Calls to high-level functions like printf, preferring low-level fwrite instead -// - Calling other CRT functions other than for the purpose of testing them - -// Dependencies -#include -#include -#include -#include -#include -#include - -// Tested -#include -#include -#include - -// MEMORY - -#define TEST_MEMORY_SIZE 8*1024*1024 -static uint8_t test_memory[TEST_MEMORY_SIZE]; -static uint64_t test_memory_head = TEST_MEMORY_SIZE; - -static void *mem_alloc(uint64_t size) { - if(test_memory_head < size) { - fputs("Out of memory. Can't continue testing!!", stderr); - return NULL; - } - test_memory_head -= size; - return &test_memory[test_memory_head]; -} - -// RANDOM NUMBER GENERATOR (RNG) - -static unsigned long random_seed = 0; - -unsigned long random(void) { - random_seed = random_seed * 2147001325 + 715136305; - return 0x31415926 ^ ((random_seed >> 16) + (random_seed << 16)); -} - -unsigned long random_between(int lo, int hi) { - return (random() % (1+hi - lo)) + lo; -} - -// FORMATTING AND IO - -bool fmt_xml_escapes = false; - -static void fprintc(FILE *file, char c) { - fputc(c, file); -} - -static void fprints(FILE *file, char *str) { - while(*str != 0) { - fputc(*str++, file); - } -} - -static void fprintc_maybe_xml(FILE *file, char c) { - if(c == '"' && fmt_xml_escapes) { - fprints(file, """); - } - else if(c == '&' && fmt_xml_escapes) { - fprints(file, "&"); - } - else if(c == '<' && fmt_xml_escapes) { - fprints(file, "<"); - } - else if(c == '>' && fmt_xml_escapes) { - fprints(file, ">"); - } - else if(c == '\'' && fmt_xml_escapes) { - fprints(file, "'"); - } - else { - fprintc(file, c); - } -} - -static void fprintd(FILE *file, int32_t number, int width) { - if(number < 0) { - fprintc(file, '-'); - number = -number; - } - char buffer[20] = {0}; - char *str = buffer + sizeof buffer - 1; - do { - *--str = number%10+'0'; - number /= 10; - } while(number != 0); - int num_digits = (int)((buffer + sizeof buffer - 1) - str); - int pad_width = width - num_digits; - while(pad_width-- > 0) { - fprintc(file, '0'); - } - fprints(file, str); -} - -static void fprintu(FILE *file, uint32_t number, int width) { - char buffer[20] = {0}; - char *str = buffer + sizeof buffer; - do { - *--str = number%10+'0'; - number /= 10; - } while(number != 0); - int num_digits = (int)((buffer + sizeof buffer - 1) - str); - int pad_width = width - num_digits; - while(pad_width-- > 0) { - fprintc(file, '0'); - } - fprints(file, str); -} - -static void fvprint_fmt(FILE *file, char *fmt, va_list args) { - while(*fmt != 0) { - if(*fmt != '%') { - fprintc(file, *fmt); - } - else { - ++fmt; - int width = 0; - while('0' <= *fmt && *fmt <= '9') { - width = 10*width + *fmt-'0'; - ++fmt; - } - if(*fmt == 'c') { - int ch = va_arg(args, int); - fprintc_maybe_xml(file, ch); - } - else if(*fmt == '%') { - fprintc(file, '%'); - } - else if(*fmt == 's') { - char *str = va_arg(args, char*); - while(*str != 0) { - fprintc_maybe_xml(file, *str); - ++str; - } - } - else if(*fmt == 'd') { - int32_t i = va_arg(args, int32_t); - fprintd(file, i, width); - } - else if(*fmt == 'u') { - uint32_t u = va_arg(args, uint32_t); - fprintu(file, u, width); - } - } - ++fmt; - } -} - -static void fprint_fmt(FILE *file, char *fmt, ...) { - va_list args; - va_start(args, fmt); - fvprint_fmt(file, fmt, args); - va_end(args); -} - -static void printc(char c) { - fprintc(stdout, c); -} - -static void prints(char *str) { - fprints(stdout, str); -} - -static void printd(int32_t number, int width) { - fprintd(stdout, number, width); -} - -static void printu(uint32_t number, int width) { - fprintu(stdout, number, width); -} - -static void print_fmt(char *fmt, ...) { - va_list args; - va_start(args, fmt); - fvprint_fmt(stdout, fmt, args); - va_end(args); -} - -static void sprint_fmt(char *dst, char *fmt, ...) { - va_list args; - va_start(args, fmt); - while(*fmt != 0) { - if(*fmt != '%') { - *dst++ = *fmt; - } - else { - ++fmt; - int width = 0; - while('0' <= *fmt && *fmt <= '9') { - width = 10*width + *fmt-'0'; - ++fmt; - } - if(*fmt == 'c') { - int ch = va_arg(args, int); - *dst++ = ch; - } - else if(*fmt == 's') { - char *str = va_arg(args, char*); - while((*dst++ = *str++)); - } - else if(*fmt == 'd') { - int32_t i = va_arg(args, int32_t); - if(i < 0) { - i = -i; - *dst++ = '-'; - } - char buffer[20] = {0}; - char *str = buffer + sizeof buffer; - do { - *--str = i%10+'0'; - i /= 10; - } while(i != 0); - int num_digits = (int)((buffer + sizeof buffer - 1) - str); - int pad_width = width - num_digits; - while(pad_width-- > 0) { - *dst++ = '0'; - } - while((*dst++ = *str++)); - } - else if(*fmt == 'u') { - uint32_t u = va_arg(args, uint32_t); - char buffer[20] = {0}; - char *str = buffer + sizeof buffer; - do { - *--str = u%10+'0'; - u /= 10; - } while(u != 0); - int num_digits = (int)((buffer + sizeof buffer - 1) - str); - int pad_width = width - num_digits; - while(pad_width-- > 0) { - *dst++ = '0'; - } - while((*dst++ = *str++)); - } - } - ++fmt; - } - *dst = 0; - va_end(fmt); -} - -static void term_color_green() { - prints("\x1b[32m"); -} - -static void term_color_red() { - prints("\x1b[31m"); -} - -static void term_color_yellow() { - prints("\x1b[33m"); -} - -static void term_color_reset() { - prints("\x1b[0m"); -} - -// TEST SUITE FUNCTIONS - -// This stuff is for saving results of tests to be a bit more flexible with printing -// test results -struct Test typedef Test; -struct Test_Feature typedef Test_Feature; - -struct Test_Feature { - Test_Feature *next; - char *name; - int test_count; - int success_count; - Test *test_head; -}; - -struct Test { - Test *next; - char *condition_str; - char *error_msg; - int line; - bool is_succeeded; -}; - -static Test_Feature *reverse_test_lists(Test_Feature *features_reversed) { - Test_Feature *new_head = NULL; - while(features_reversed != NULL) { - Test_Feature *reversed_next = features_reversed->next; - Test_Feature *new_prev = features_reversed; - new_prev->next = new_head; - new_head = new_prev; - features_reversed = reversed_next; - } - for(Test_Feature *feature = new_head; feature != NULL; feature = feature->next) { - Test *reversed_head = feature->test_head; - Test *head = NULL; - while(reversed_head != NULL) { - Test *reversed_next = reversed_head->next; - Test *head_prev = reversed_head; - head_prev->next = head; - head = head_prev; - reversed_head = reversed_next; - } - feature->test_head = head; - } - return new_head; -} - -static void print_test_results(Test_Feature *features) { - prints(":: Printing test results\n"); - // Iterate features - int total_test_count = 0; - int total_success_count = 0; - for(Test_Feature *feature = features; feature != NULL; feature = feature->next) { - // Update counters - total_test_count += feature->test_count; - total_success_count += feature->success_count; - // Print feature name - term_color_green(); - print_fmt("==> Feature "); - term_color_reset(); - print_fmt("%s: (%d/%d)\n", feature->name, feature->success_count, feature->test_count); - if(feature->success_count < feature->test_count) { - int test_index = 0; - for(Test *test = feature->test_head; test != NULL; test = test->next) { - if(!test->is_succeeded) { - term_color_red(); - print_fmt(" Test #%d", 1+test_index); - term_color_reset(); - print_fmt(" failed (line %d): %s\n", test->line, test->error_msg); - } - test_index += 1; - } - } - } - float success_percentage = (float) total_success_count / (float)total_test_count; - if(success_percentage < 0.5) { - term_color_red(); - } - else if(success_percentage != 1.0) { - term_color_yellow(); - } - else { - term_color_green(); - } - time_t timestamp = time(NULL); - struct tm tm = *localtime(×tamp); - print_fmt("[%4d-%2d-%2d %2d:%2d:%2d] ", 1900+tm.tm_year, 1+tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); - prints("TESTS COMPLETED: "); - printd(total_success_count, 0); - printc('/'); - printd(total_test_count, 0); - term_color_reset(); - printc('\n'); -} - -// JUNIT OUTPUT - -static void junit_write(char *path, Test_Feature *features) { - fmt_xml_escapes = true; - FILE *xml = fopen(path, "wb"); - // TODO: store tests and failures in an object instead of calculating it like that - int total_test_count = 0; - int total_success_count = 0; - for(Test_Feature *feature = features; feature != NULL; feature = feature->next) { - total_test_count += feature->test_count; - total_success_count += feature->success_count; - } - fprint_fmt(xml, "\n"); - fprint_fmt(xml, "\n", - "Ciabatta CRT functions test suite", total_test_count, total_test_count - total_success_count); - int feature_id = 0; - for(Test_Feature *feature = features; feature != NULL; feature = feature->next) { - fprint_fmt(xml, " \n", - feature_id, feature->name, feature->test_count, feature->test_count - feature->success_count); - int test_id = 0; - for(Test *test = feature->test_head; test != NULL; test = test->next) { - fprint_fmt(xml, " \n", - test_id, test->condition_str); - if(!test->is_succeeded) { - fprint_fmt(xml, " \n", - test->line, test->error_msg); - fprint_fmt(xml, "crt.c(%d):\n %s\n", test->line, test->error_msg); - fprint_fmt(xml, " \n"); - } - test_id += 1; - fprint_fmt(xml, " \n"); - } - feature_id += 1; - fprint_fmt(xml, " \n"); - } - fprint_fmt(xml, "\n"); - fclose(xml); - fmt_xml_escapes = false; -} - -// TEST MACROS - -#define XSTR(expr) #expr -#define STR(expr) XSTR(expr) - -Test_Feature *current_feature = NULL; -bool junit_output = false; -char *junit_output_path = NULL; - -#define JUNIT_START(XML_PATH) \ - junit_output = true; \ - junit_output_path = XML_PATH - -#define JUNIT_END() \ - if(junit_output) { \ - junit_write(junit_output_path, current_feature); \ - } - -#define FEATURE_START__(NAME, NUMBER) \ - { \ - print_fmt(":: Running tests for %s\n", NAME); \ - Test_Feature *feature = mem_alloc(sizeof(Test_Feature)); \ - feature->next = current_feature; \ - current_feature = feature; \ - current_feature->name = NAME; \ - current_feature->test_head = NULL; \ - current_feature->success_count = 0; \ - current_feature->test_count = 0; \ - } - -#define FEATURE_START_(NAME, NUMBER) \ - FEATURE_START__(NAME, NUMBER) - -#define FEATURE_START(NAME) \ - FEATURE_START_(NAME, __COUNTER__) - -#define FEATURE_END() - -#define TEST__(EXPR, ERROR_FMT, NUMBER, LINE, ...) \ - { \ - Test *test = mem_alloc(sizeof(Test)); \ - test->next = current_feature->test_head; \ - current_feature->test_head = test; \ - current_feature->test_head->condition_str = STR(EXPR); \ - current_feature->test_head->is_succeeded = EXPR; \ - current_feature->test_head->line = LINE; \ - if(current_feature->test_head->is_succeeded) {\ - current_feature->success_count += 1; \ - }\ - else { \ - current_feature->test_head->error_msg = mem_alloc(256); \ - sprint_fmt(current_feature->test_head->error_msg, ERROR_FMT, __VA_ARGS__); \ - }\ - current_feature->test_count += 1; \ - } - -#define TEST_(EXPR, ERROR_MSG, NUMBER, LINE, ...) \ - TEST__(EXPR, ERROR_MSG, NUMBER, LINE, __VA_ARGS__) - -#define TEST(EXPR, ERROR_MSG, ...) \ - TEST_(EXPR, ERROR_MSG, __COUNTER__, __LINE__, __VA_ARGS__) - -#define TESTS_PREPARE() \ - current_feature = reverse_test_lists(current_feature) - -#define TESTS_PRINT_RESULT() \ - print_test_results(current_feature) +#include "testing.h" int main(int argc, char **argv) { JUNIT_START("test/junit.xml"); - FEATURE_START("limits.h"); - { - // Check existing of macro definitions - #ifdef BOOL_WIDTH - TEST(BOOL_WIDTH == 8*sizeof(bool), "BOOL_WIDTH isn't correlated with sizeof(bool)"); - #else - TEST(false, "The macro BOOL_WIDTH wasn't defined"); - #endif - #ifdef CHAR_WIDTH - TEST(CHAR_WIDTH == 8, "CHAR_WIDTH isn't 8"); - #else - TEST(false, "The macro CHAR_WIDTH wasn't defined"); - #endif - #ifdef CHAR_BIT - TEST(CHAR_BIT == 8, "CHAR_BIT isn't 8"); - #else - TEST(false, "The macro CHAR_BIT wasn't defined"); - #endif - #ifdef CHAR_MIN - TEST(CHAR_MIN == -128, "CHAR_MIN isn't -128"); - #else - TEST(false, "The macro CHAR_MIN wasn't defined"); - #endif - #ifdef CHAR_MAX - TEST(CHAR_MAX == 127, "CHAR_MAX isn't 127"); - #else - TEST(false, "The macro CHAR_MAX wasn't defined"); - #endif - #ifdef MB_LEN_MAX - TEST(true, ""); - #else - TEST(false, "The macro MB_LEN_MAX wasn't defined"); - #endif - - #ifdef SCHAR_WIDTH - TEST(SCHAR_WIDTH == 8, "SCHAR_WIDTH isn't 8"); - #else - TEST(false, "The macro SCHAR_WIDTH wasn't defined"); - #endif - #ifdef SHRT_WIDTH - TEST(SHRT_WIDTH == 16, "SHRT_WIDTH isn't 16"); - #else - TEST(false, "The macro SHRT_WIDTH wasn't defined"); - #endif - #ifdef INT_WIDTH - TEST(INT_WIDTH == 32, "INT_WIDTH isn't 32"); - #else - TEST(false, "The macro INT_WIDTH wasn't defined"); - #endif - #ifdef LONG_WIDTH - TEST(LONG_WIDTH == 32, "LONG_WIDTH isn't 32"); - #else - TEST(false, "The macro LONG_WIDTH wasn't defined"); - #endif - #ifdef LLONG_WIDTH - TEST(LLONG_WIDTH == 64, "LLONG_WIDTH isn't 64"); - #else - TEST(false, "The macro LLONG_WIDTH wasn't defined"); - #endif - - #ifdef SCHAR_MIN - TEST(SCHAR_MIN == -128, "SCHAR_MIN isn't -128"); - #else - TEST(false, "The macro SCHAR_MIN wasn't defined"); - #endif - #ifdef SHRT_MIN - TEST(SHRT_MIN == -0x8000, "SHRT_MIN isn't -0x8000"); - #else - TEST(false, "The macro SHRT_MIN wasn't defined"); - #endif - #ifdef INT_MIN - TEST(INT_MIN == -0x80000000, "INT_MIN isn't -0x80000000"); - #else - TEST(false, "The macro INT_MIN wasn't defined"); - #endif - #ifdef LONG_MIN - TEST(LONG_MIN == -0x80000000l, "LONG_MIN isn't -0x80000000"); - #else - TEST(false, "The macro LONG_MIN wasn't defined"); - #endif - #ifdef LLONG_MIN - TEST(LLONG_MIN == -0x8000000000000000ll, "LLONG_MIN isn't -0x8000000000000000"); - #else - TEST(false, "The macro LLONG_MIN wasn't defined"); - #endif - - #ifdef SCHAR_MAX - TEST(SCHAR_MAX == 127, "SCHAR_MAX isn't 127"); - #else - TEST(false, "The macro SCHAR_MAX wasn't defined"); - #endif - #ifdef SHRT_MAX - TEST(SHRT_MAX == 0x7fff, "SHRT_MAX isn't 0x7fff"); - #else - TEST(false, "The macro SHRT_MAX wasn't defined"); - #endif - #ifdef INT_MAX - TEST(INT_MAX == 0x7fffffff, "INT_MAX isn't 0x7fffffff"); - #else - TEST(false, "The macro INT_MAX wasn't defined"); - #endif - #ifdef LONG_MAX - TEST(LONG_MAX == 0x7fffffff, "LONG_MAX isn't 0x7fffffff"); - #else - TEST(false, "The macro LONG_MAX wasn't defined"); - #endif - #ifdef LLONG_MAX - TEST(LLONG_MAX == 0x7fffffffffffffffll, "LLONG_MAX isn't 0x7fffffffffffffff"); - #else - TEST(false, "The macro LLONG_MAX wasn't defined"); - #endif - - #ifdef UCHAR_WIDTH - TEST(UCHAR_WIDTH == 8, "UCHAR_WIDTH isn't 8"); - #else - TEST(false, "The macro UCHAR_WIDTH wasn't defined"); - #endif - #ifdef USHRT_WIDTH - TEST(USHRT_WIDTH == 16, "USHRT_WIDTH isn't 16"); - #else - TEST(false, "The macro USHRT_WIDTH wasn't defined"); - #endif - #ifdef UINT_WIDTH - TEST(UINT_WIDTH == 32, "UINT_WIDTH isn't 32"); - #else - TEST(false, "The macro UINT_WIDTH wasn't defined"); - #endif - #ifdef ULONG_WIDTH - TEST(ULONG_WIDTH == 32, "ULONG_WIDTH isn't 32"); - #else - TEST(false, "The macro ULONG_WIDTH wasn't defined"); - #endif - #ifdef ULLONG_WIDTH - TEST(ULLONG_WIDTH == 64, "ULLONG_WIDTH isn't 64"); - #else - TEST(false, "The macro ULLONG_WIDTH wasn't defined"); - #endif - - #ifdef UCHAR_MAX - TEST(UCHAR_MAX == 255, "UCHAR_MAX isn't 255"); - #else - TEST(false, "The macro UCHAR_MAX wasn't defined"); - #endif - #ifdef USHRT_MAX - TEST(USHRT_MAX == 0xffffu, "USHRT_MAX isn't 0xffff"); - #else - TEST(false, "The macro USHRT_MAX wasn't defined"); - #endif - #ifdef UINT_MAX - TEST(UINT_MAX == 0xffffffffu, "UINT_MAX isn't 0xffffffff"); - #else - TEST(false, "The macro UINT_MAX wasn't defined"); - #endif - #ifdef ULONG_MAX - TEST(ULONG_MAX == 0xffffffffu, "ULONG_MAX isn't 0xffffffff"); - #else - TEST(false, "The macro ULONG_MAX wasn't defined"); - #endif - #ifdef ULLONG_MAX - TEST(ULLONG_MAX == 0xffffffffffffffffull, "ULLONG_MAX isn't 0xffffffffffffffffull"); - #else - TEST(false, "The macro ULLONG_MAX wasn't defined"); - #endif - - #ifdef PTRDIFF_WIDTH - TEST(true, ""); - #else - TEST(false, "The macro PTRDIFF_WIDTH isn't defined"); - #endif - #ifdef PTRDIFF_MIN - TEST(true, ""); - #else - TEST(false, "The macro PTRDIFF_MIN isn't defined"); - #endif - #ifdef PTRDIFF_MAX - TEST(true, ""); - #else - TEST(false, "The macro PTRDIFF_MAX isn't defined"); - #endif - #ifdef SIZE_WIDTH - TEST(true, ""); - #else - TEST(false, "The macro SIZE_WIDTH isn't defined"); - #endif - #ifdef SIZE_MAX - TEST(true, ""); - #else - TEST(false, "The macro SIZE_MAX isn't defined"); - #endif - #ifdef SIG_ATOMIC_WIDTH - TEST(true, ""); - #else - TEST(false, "The macro SIG_ATOMIC_WIDTH isn't defined"); - #endif - #ifdef SIG_ATOMIC_MIN - TEST(true, ""); - #else - TEST(false, "The macro SIG_ATOMIC_MIN isn't defined"); - #endif - #ifdef SIG_ATOMIC_MAX - TEST(true, ""); - #else - TEST(false, "The macro SIG_ATOMIC_MAX isn't defined"); - #endif - #ifdef WINT_WIDTH - TEST(true, ""); - #else - TEST(false, "The macro WINT_WIDTH isn't defined"); - #endif - #ifdef WINT_MIN - TEST(true, ""); - #else - TEST(false, "The macro WINT_MIN isn't defined"); - #endif - #ifdef WINT_MAX - TEST(true, ""); - #else - TEST(false, "The macro WINT_MAX isn't defined"); - #endif - #ifdef WCHAR_WIDTH - TEST(true, ""); - #else - TEST(false, "The macro WCHAR_WIDTH isn't defined"); - #endif - #ifdef WCHAR_MIN - TEST(true, ""); - #else - TEST(false, "WCHAR_MIN isn't defined"); - #endif - #ifdef WCHAR_MAX - TEST(true, ""); - #else - TEST(false, "WCHAR_MAX isn't defined"); - #endif - } - FEATURE_END(); - - FEATURE_START("ctype.h"); - { - // Test letters - for(int i = 0; i != 10; ++i) { - int letter = random_between('a', 'z'); - TEST(isalpha(letter) != 0, "isalpha('%c') returned false", letter); - TEST(isdigit(letter) == 0, "isdigit('%c') returned true", letter); - } - // Test digits - for(int i = 0; i != 10; ++i) { - int digit = random_between('0', '9'); - TEST(isalpha(digit) == 0, "isalpha('%c') returned true", digit); - TEST(isdigit(digit) != 0, "isdigit('%c') returned false", digit); - } - } - FEATURE_END(); - - FEATURE_START("IO functions (stdio.h)"); - { - static int numbers[10] = {0,1,2,3,4,5,6,7,8,9}; - // fread/fwrite - { - FILE *file = fopen("test_folder/file", "wb"); - TEST(file != NULL, "Created file is NULL"); - int cnt_written = fwrite(numbers, sizeof(int), 10, file); - TEST(cnt_written == 10, "fwrite didn't write all 10 objects"); - TEST(fclose(file) == 0, "fclose didn't close the file"); - TEST(rename("test_folder/file", "test_folder/file2") == 0, "Rename returned 0"); - file = fopen("test_folder/file2", "rb"); - TEST(file != NULL, "Created file is NULL"); - int read_numbers[10]; - int cnt_read = fread(read_numbers, sizeof(int), 10, file); - TEST(cnt_read == 10, "fread didn't read 10 objects"); - bool all_ok = true; - for(int i = 0; i != 10; ++i) { - if(read_numbers[i] != numbers[i]) { - all_ok = false; - break; - } - } - TEST(all_ok, "The elements read didn't match the elements written"); - TEST(fclose(file) == 0, "fclose didn't close the file"); - TEST(remove("test_folder/file2") == 0, "remove didn't remove the file"); - } - // Seeking and stuff - { - FILE *file = fopen("test_folder/seek", "wb"); - TEST(file != NULL, "Created file is NULL"); - TEST(fwrite(numbers, sizeof(int), 10, file) == 10, "fwrite didn't write all 10 objects"); - TEST(fflush(file) == 0, "fflush failed"); - TEST(fseek(file, 4*sizeof(int), SEEK_SET) == 0, "fseek couldn't seek to offset 4"); - int num; - TEST(fread(&num, sizeof(int), 1, file) == 1, "fread didn't read the int"); - TEST(num == 4, "Wrong value read at offset 4"); - TEST(fseek(file, -4, SEEK_END) == 0, "fseek coudn't seek to the end"); - TEST(fread(&num, sizeof(int), 1, file) == 1, "fread didn't read the int"); - TEST(num == 9, "Wrong number read"); - TEST(fclose(file) == 0, "fclose didn't close the file"); - file = fopen("test_folder/seek", "wb"); - TEST(file != NULL, "Created file is NULL"); - fpos_t nul_pos; - TEST(fgetpos(file, &nul_pos) == 0, "Couldn't get file position"); - TEST(fseek(file, 0, SEEK_END) == 0, "Couldn't seek to the end of the file"); - long file_size = ftell(file); - TEST(file_size != -1L, "ftell failed"); - TEST(fsetpos(file, &nul_pos) == 0, "Couldn't reset file position"); - TEST(ftell(file) == 0, "File position reset to wrong spot"); - } - // Getchar, ungetchar - { - char str[] = "Hello, world!"; - FILE *file = fopen("test_folder/getc", "wb"); - TEST(file != NULL, "Created file is NULL"); - TEST(fputs(str, file) >= 0, "fputs failed"); - TEST(fputc('!', file) == '!', "fputc failed"); - TEST(fflush(file) == 0, "fflush failed"); - // TEST(fclose(file) == 0, "fclose failed"); - file = freopen("test_folder/getc", "rb", file); - TEST(file != NULL, "Reopened file is NULL"); - TEST(fgets(str, sizeof str, file) == str, "fgets failed"); - TEST(fgetc(file) == '!', "fgetc read the wrong thing"); - TEST(ungetc('?', file) == '?', "ungetc failed to put a character"); - TEST(fgetc(file) == '?', "Didn't get back the same character that we unget'ed"); - TEST(fclose(file) == 0, "fclose failed"); - } - } + FEATURE_START("My feature"); + TEST(1 == 1, "Tests work"); TESTS_PREPARE(); TESTS_PRINT_RESULT(); JUNIT_END(); diff --git a/tests/empty.c b/tests/empty.c new file mode 100644 index 0000000..2b8c6ac --- /dev/null +++ b/tests/empty.c @@ -0,0 +1,4 @@ + +int main() { + return 0; +} diff --git a/tests/testing.h b/tests/testing.h new file mode 100644 index 0000000..dcbb051 --- /dev/null +++ b/tests/testing.h @@ -0,0 +1,471 @@ + +// Framework for testing of the CRT library. This file is supposed to be linked +// to the ciabatta, so there is a possibility that the runtime that the testing +// suite relies on is broken, which is why to decrease the chance of it crashing +// because of that, I minimize that dependency. Therefore this testing suite +// avoids the following: +// - Heap allocations +// - Calls to high-level functions like printf, preferring low-level fwrite instead +// - Calling other CRT functions other than for the purpose of testing them + +// Dependencies +#include +#include +#include +#include +#include +#include + +// Tested +#include +#include +#include + +// MEMORY + +#define TEST_MEMORY_SIZE 8*1024*1024 +static uint8_t test_memory[TEST_MEMORY_SIZE]; +static uint64_t test_memory_head = TEST_MEMORY_SIZE; + +static void *mem_alloc(uint64_t size) { + if(test_memory_head < size) { + fputs("Out of memory. Can't continue testing!!", stderr); + return NULL; + } + test_memory_head -= size; + return &test_memory[test_memory_head]; +} + +// RANDOM NUMBER GENERATOR (RNG) + +static unsigned long random_seed = 0; + +unsigned long random(void) { + random_seed = random_seed * 2147001325 + 715136305; + return 0x31415926 ^ ((random_seed >> 16) + (random_seed << 16)); +} + +unsigned long random_between(int lo, int hi) { + return (random() % (1+hi - lo)) + lo; +} + +// FORMATTING AND IO + +bool fmt_xml_escapes = false; + +static void fprintc(FILE *file, char c) { + fputc(c, file); +} + +static void fprints(FILE *file, char *str) { + while(*str != 0) { + fputc(*str++, file); + } +} + +static void fprintc_maybe_xml(FILE *file, char c) { + if(c == '"' && fmt_xml_escapes) { + fprints(file, """); + } + else if(c == '&' && fmt_xml_escapes) { + fprints(file, "&"); + } + else if(c == '<' && fmt_xml_escapes) { + fprints(file, "<"); + } + else if(c == '>' && fmt_xml_escapes) { + fprints(file, ">"); + } + else if(c == '\'' && fmt_xml_escapes) { + fprints(file, "'"); + } + else { + fprintc(file, c); + } +} + +static void fprintd(FILE *file, int32_t number, int width) { + if(number < 0) { + fprintc(file, '-'); + number = -number; + } + char buffer[20] = {0}; + char *str = buffer + sizeof buffer - 1; + do { + *--str = number%10+'0'; + number /= 10; + } while(number != 0); + int num_digits = (int)((buffer + sizeof buffer - 1) - str); + int pad_width = width - num_digits; + while(pad_width-- > 0) { + fprintc(file, '0'); + } + fprints(file, str); +} + +static void fprintu(FILE *file, uint32_t number, int width) { + char buffer[20] = {0}; + char *str = buffer + sizeof buffer; + do { + *--str = number%10+'0'; + number /= 10; + } while(number != 0); + int num_digits = (int)((buffer + sizeof buffer - 1) - str); + int pad_width = width - num_digits; + while(pad_width-- > 0) { + fprintc(file, '0'); + } + fprints(file, str); +} + +static void fvprint_fmt(FILE *file, char *fmt, va_list args) { + while(*fmt != 0) { + if(*fmt != '%') { + fprintc(file, *fmt); + } + else { + ++fmt; + int width = 0; + while('0' <= *fmt && *fmt <= '9') { + width = 10*width + *fmt-'0'; + ++fmt; + } + if(*fmt == 'c') { + int ch = va_arg(args, int); + fprintc_maybe_xml(file, ch); + } + else if(*fmt == '%') { + fprintc(file, '%'); + } + else if(*fmt == 's') { + char *str = va_arg(args, char*); + while(*str != 0) { + fprintc_maybe_xml(file, *str); + ++str; + } + } + else if(*fmt == 'd') { + int32_t i = va_arg(args, int32_t); + fprintd(file, i, width); + } + else if(*fmt == 'u') { + uint32_t u = va_arg(args, uint32_t); + fprintu(file, u, width); + } + } + ++fmt; + } +} + +static void fprint_fmt(FILE *file, char *fmt, ...) { + va_list args; + va_start(args, fmt); + fvprint_fmt(file, fmt, args); + va_end(args); +} + +static void printc(char c) { + fprintc(stdout, c); +} + +static void prints(char *str) { + fprints(stdout, str); +} + +static void printd(int32_t number, int width) { + fprintd(stdout, number, width); +} + +static void printu(uint32_t number, int width) { + fprintu(stdout, number, width); +} + +static void print_fmt(char *fmt, ...) { + va_list args; + va_start(args, fmt); + fvprint_fmt(stdout, fmt, args); + va_end(args); +} + +static void sprint_fmt(char *dst, char *fmt, ...) { + va_list args; + va_start(args, fmt); + while(*fmt != 0) { + if(*fmt != '%') { + *dst++ = *fmt; + } + else { + ++fmt; + int width = 0; + while('0' <= *fmt && *fmt <= '9') { + width = 10*width + *fmt-'0'; + ++fmt; + } + if(*fmt == 'c') { + int ch = va_arg(args, int); + *dst++ = ch; + } + else if(*fmt == 's') { + char *str = va_arg(args, char*); + while((*dst++ = *str++)); + } + else if(*fmt == 'd') { + int32_t i = va_arg(args, int32_t); + if(i < 0) { + i = -i; + *dst++ = '-'; + } + char buffer[20] = {0}; + char *str = buffer + sizeof buffer; + do { + *--str = i%10+'0'; + i /= 10; + } while(i != 0); + int num_digits = (int)((buffer + sizeof buffer - 1) - str); + int pad_width = width - num_digits; + while(pad_width-- > 0) { + *dst++ = '0'; + } + while((*dst++ = *str++)); + } + else if(*fmt == 'u') { + uint32_t u = va_arg(args, uint32_t); + char buffer[20] = {0}; + char *str = buffer + sizeof buffer; + do { + *--str = u%10+'0'; + u /= 10; + } while(u != 0); + int num_digits = (int)((buffer + sizeof buffer - 1) - str); + int pad_width = width - num_digits; + while(pad_width-- > 0) { + *dst++ = '0'; + } + while((*dst++ = *str++)); + } + } + ++fmt; + } + *dst = 0; + va_end(fmt); +} + +static void term_color_green() { + prints("\x1b[32m"); +} + +static void term_color_red() { + prints("\x1b[31m"); +} + +static void term_color_yellow() { + prints("\x1b[33m"); +} + +static void term_color_reset() { + prints("\x1b[0m"); +} + +// TEST SUITE FUNCTIONS + +// This stuff is for saving results of tests to be a bit more flexible with printing +// test results +struct Test typedef Test; +struct Test_Feature typedef Test_Feature; + +struct Test_Feature { + Test_Feature *next; + char *name; + int test_count; + int success_count; + Test *test_head; +}; + +struct Test { + Test *next; + char *condition_str; + char *error_msg; + int line; + bool is_succeeded; +}; + +static Test_Feature *reverse_test_lists(Test_Feature *features_reversed) { + Test_Feature *new_head = NULL; + while(features_reversed != NULL) { + Test_Feature *reversed_next = features_reversed->next; + Test_Feature *new_prev = features_reversed; + new_prev->next = new_head; + new_head = new_prev; + features_reversed = reversed_next; + } + for(Test_Feature *feature = new_head; feature != NULL; feature = feature->next) { + Test *reversed_head = feature->test_head; + Test *head = NULL; + while(reversed_head != NULL) { + Test *reversed_next = reversed_head->next; + Test *head_prev = reversed_head; + head_prev->next = head; + head = head_prev; + reversed_head = reversed_next; + } + feature->test_head = head; + } + return new_head; +} + +static void print_test_results(Test_Feature *features) { + prints(":: Printing test results\n"); + // Iterate features + int total_test_count = 0; + int total_success_count = 0; + for(Test_Feature *feature = features; feature != NULL; feature = feature->next) { + // Update counters + total_test_count += feature->test_count; + total_success_count += feature->success_count; + // Print feature name + term_color_green(); + print_fmt("==> Feature "); + term_color_reset(); + print_fmt("%s: (%d/%d)\n", feature->name, feature->success_count, feature->test_count); + if(feature->success_count < feature->test_count) { + int test_index = 0; + for(Test *test = feature->test_head; test != NULL; test = test->next) { + if(!test->is_succeeded) { + term_color_red(); + print_fmt(" Test #%d", 1+test_index); + term_color_reset(); + print_fmt(" failed (line %d): %s\n", test->line, test->error_msg); + } + test_index += 1; + } + } + } + float success_percentage = (float) total_success_count / (float)total_test_count; + if(success_percentage < 0.5) { + term_color_red(); + } + else if(success_percentage != 1.0) { + term_color_yellow(); + } + else { + term_color_green(); + } + time_t timestamp = time(NULL); + struct tm tm = *localtime(×tamp); + print_fmt("[%4d-%2d-%2d %2d:%2d:%2d] ", 1900+tm.tm_year, 1+tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + prints("TESTS COMPLETED: "); + printd(total_success_count, 0); + printc('/'); + printd(total_test_count, 0); + term_color_reset(); + printc('\n'); +} + +// JUNIT OUTPUT + +static void junit_write(char *path, Test_Feature *features) { + fmt_xml_escapes = true; + FILE *xml = fopen(path, "wb"); + // TODO: store tests and failures in an object instead of calculating it like that + int total_test_count = 0; + int total_success_count = 0; + for(Test_Feature *feature = features; feature != NULL; feature = feature->next) { + total_test_count += feature->test_count; + total_success_count += feature->success_count; + } + fprint_fmt(xml, "\n"); + fprint_fmt(xml, "\n", + "Ciabatta CRT functions test suite", total_test_count, total_test_count - total_success_count); + int feature_id = 0; + for(Test_Feature *feature = features; feature != NULL; feature = feature->next) { + fprint_fmt(xml, " \n", + feature_id, feature->name, feature->test_count, feature->test_count - feature->success_count); + int test_id = 0; + for(Test *test = feature->test_head; test != NULL; test = test->next) { + fprint_fmt(xml, " \n", + test_id, test->condition_str); + if(!test->is_succeeded) { + fprint_fmt(xml, " \n", + test->line, test->error_msg); + fprint_fmt(xml, "crt.c(%d):\n %s\n", test->line, test->error_msg); + fprint_fmt(xml, " \n"); + } + test_id += 1; + fprint_fmt(xml, " \n"); + } + feature_id += 1; + fprint_fmt(xml, " \n"); + } + fprint_fmt(xml, "\n"); + fclose(xml); + fmt_xml_escapes = false; +} + +// TEST MACROS + +#define XSTR(expr) #expr +#define STR(expr) XSTR(expr) + +Test_Feature *current_feature = NULL; +bool junit_output = false; +char *junit_output_path = NULL; + +#define JUNIT_START(XML_PATH) \ + junit_output = true; \ + junit_output_path = XML_PATH + +#define JUNIT_END() \ + if(junit_output) { \ + junit_write(junit_output_path, current_feature); \ + } + +#define FEATURE_START__(NAME, NUMBER) \ + { \ + print_fmt(":: Running tests for %s\n", NAME); \ + Test_Feature *feature = mem_alloc(sizeof(Test_Feature)); \ + feature->next = current_feature; \ + current_feature = feature; \ + current_feature->name = NAME; \ + current_feature->test_head = NULL; \ + current_feature->success_count = 0; \ + current_feature->test_count = 0; \ + } + +#define FEATURE_START_(NAME, NUMBER) \ + FEATURE_START__(NAME, NUMBER) + +#define FEATURE_START(NAME) \ + FEATURE_START_(NAME, __COUNTER__) + +#define FEATURE_END() + +#define TEST__(EXPR, ERROR_FMT, NUMBER, LINE, ...) \ + { \ + Test *test = mem_alloc(sizeof(Test)); \ + test->next = current_feature->test_head; \ + current_feature->test_head = test; \ + current_feature->test_head->condition_str = STR(EXPR); \ + current_feature->test_head->is_succeeded = EXPR; \ + current_feature->test_head->line = LINE; \ + if(current_feature->test_head->is_succeeded) {\ + current_feature->success_count += 1; \ + }\ + else { \ + current_feature->test_head->error_msg = mem_alloc(256); \ + sprint_fmt(current_feature->test_head->error_msg, ERROR_FMT, __VA_ARGS__); \ + }\ + current_feature->test_count += 1; \ + } + +#define TEST_(EXPR, ERROR_MSG, NUMBER, LINE, ...) \ + TEST__(EXPR, ERROR_MSG, NUMBER, LINE, __VA_ARGS__) + +#define TEST(EXPR, ERROR_MSG, ...) \ + TEST_(EXPR, ERROR_MSG, __COUNTER__, __LINE__, __VA_ARGS__) + +#define TESTS_PREPARE() \ + current_feature = reverse_test_lists(current_feature) + +#define TESTS_PRINT_RESULT() \ + print_test_results(current_feature) + diff --git a/tests/windows_utf8.c b/tests/windows_utf8.c deleted file mode 100644 index cd53d04..0000000 --- a/tests/windows_utf8.c +++ /dev/null @@ -1,20 +0,0 @@ - -#include -#include - -#pragma comment(lib, "user32.lib") - -int main(int argc, char **argv) { - // Print args: - printf("Arguments:\n"); - for(int i = 0; i != argc; ++i) { - char *arg = argv[i]; - printf(" %s\n", arg); - } - // Test UTF-8 support: - printf(u8"Привет, мир!\n"); - printf(u8"こんにちくわ世界!\n"); - // Try UTF-8 in winapi (doesn't use UTF-8 without manifest) - MessageBoxA(NULL, u8"Успех", u8"Ошибка", MB_OK); - return 0; -} diff --git a/tests/winmain.c b/tests/winmain.c deleted file mode 100644 index 4af4f73..0000000 --- a/tests/winmain.c +++ /dev/null @@ -1,57 +0,0 @@ - -#include -#include - -LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - -int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE p, LPSTR pCmdLine, int nCmdShow) { - const char CLASS_NAME[] = "Sample Window Class"; - assert(0); - WNDCLASS wc = { - .lpfnWndProc = WindowProc, - .hInstance = hInstance, - .lpszClassName = CLASS_NAME, - }; - RegisterClass(&wc); - HWND hwnd = CreateWindowEx( - 0, - CLASS_NAME, - "Learn to Program Windows", - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - NULL, - NULL, - hInstance, - NULL - ); - if (hwnd == NULL) { - return 0; - } - ShowWindow(hwnd, nCmdShow); - MSG msg; - while (GetMessage(&msg, NULL, 0, 0)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return 0; -} - -LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) - { - case WM_DESTROY: - PostQuitMessage(0); - return 0; - case WM_PAINT: - { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps); - - // All painting occurs here, between BeginPaint and EndPaint. - FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1)); - EndPaint(hwnd, &ps); - } - return 0; - } - return DefWindowProc(hwnd, uMsg, wParam, lParam); -} \ No newline at end of file diff --git a/utf8.rc b/utf8/utf8.rc similarity index 100% rename from utf8.rc rename to utf8/utf8.rc diff --git a/utf8.xml b/utf8/utf8.xml similarity index 100% rename from utf8.xml rename to utf8/utf8.xml