From bed817e9fb0523e46c6968136e2ff43be49cc7f1 Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Mon, 22 Sep 2025 16:57:17 -0400 Subject: [PATCH 01/25] rand --- configure.py | 2 +- include/MSL/rand.h | 17 +++++++++++++++++ src/MSL/rand.c | 9 +++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 include/MSL/rand.h create mode 100644 src/MSL/rand.c diff --git a/configure.py b/configure.py index 8f9b8327..4e6fb14e 100755 --- a/configure.py +++ b/configure.py @@ -742,7 +742,7 @@ def MatchingFor(*versions): Object(NonMatching, "MSL/math_api.c"), Object(NonMatching, "MSL/misc_io.c"), Object(NonMatching, "MSL/printf.c"), - Object(NonMatching, "MSL/rand.c"), + Object(Matching, "MSL/rand.c"), Object(NonMatching, "MSL/scanf.c"), Object(NonMatching, "MSL/string.c"), Object(NonMatching, "MSL/strtold.c"), diff --git a/include/MSL/rand.h b/include/MSL/rand.h new file mode 100644 index 00000000..64192cfb --- /dev/null +++ b/include/MSL/rand.h @@ -0,0 +1,17 @@ +#ifndef _RAND_H +#define _RAND_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int rand(); +void srand(u32 seed); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/src/MSL/rand.c b/src/MSL/rand.c new file mode 100644 index 00000000..07c26e09 --- /dev/null +++ b/src/MSL/rand.c @@ -0,0 +1,9 @@ +#include "rand.h" + +static u32 random_next = 1; + +// LCG (linear congruential generator) RNG algorithm +int rand() { + random_next = random_next * 1103515245 + 12345; + return ((random_next >> 16) & 0x7fff); +} From 3c89b18eb5f7f106701ca202618fcd4628681054 Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Mon, 22 Sep 2025 17:16:16 -0400 Subject: [PATCH 02/25] arith --- configure.py | 2 +- src/MSL/arith.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 src/MSL/arith.c diff --git a/configure.py b/configure.py index 4e6fb14e..44cbed74 100755 --- a/configure.py +++ b/configure.py @@ -729,7 +729,7 @@ def MatchingFor(*versions): Object(NonMatching, "MSL/alloc.c"), Object(NonMatching, "MSL/ansi_files.c"), Object(NonMatching, "MSL/ansi_fp.c"), - Object(NonMatching, "MSL/arith.c"), + Object(Matching, "MSL/arith.c"), Object(NonMatching, "MSL/buffer_io.c"), Object(NonMatching, "MSL/direct_io.c"), Object(NonMatching, "MSL/errno.c"), diff --git a/src/MSL/arith.c b/src/MSL/arith.c new file mode 100644 index 00000000..cb788d2a --- /dev/null +++ b/src/MSL/arith.c @@ -0,0 +1,5 @@ +#include "arith.h" + +int abs(int x) { + return ((x >> 31) ^ x) - (x >> 31); +} \ No newline at end of file From 3186f58bd6778b37197d19e9dd5bc149682f2a2d Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Mon, 22 Sep 2025 17:56:35 -0400 Subject: [PATCH 03/25] wstring and math_sun --- configure.py | 2 +- include/MSL/wstring.h | 21 ++++++++ src/MSL/math_sun.c | 11 ++++ src/MSL/wstring.c | 117 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 include/MSL/wstring.h create mode 100644 src/MSL/math_sun.c create mode 100644 src/MSL/wstring.c diff --git a/configure.py b/configure.py index 44cbed74..ffadc309 100755 --- a/configure.py +++ b/configure.py @@ -750,7 +750,7 @@ def MatchingFor(*versions): Object(NonMatching, "MSL/wctype.c"), Object(NonMatching, "MSL/wmem.c"), Object(NonMatching, "MSL/wprintf.c"), - Object(NonMatching, "MSL/wstring.c"), + Object(Matching, "MSL/wstring.c"), Object(NonMatching, "MSL/wchar_io.c"), Object(NonMatching, "MSL/uart_console_io_gcn.c"), Object(NonMatching, "MSL/abort_exit_ppc_eabi.c"), diff --git a/include/MSL/wstring.h b/include/MSL/wstring.h new file mode 100644 index 00000000..c7cba7d5 --- /dev/null +++ b/include/MSL/wstring.h @@ -0,0 +1,21 @@ +#ifndef _WSTRING_H +#define _WSTRING_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +size_t wcslen(const wchar_t*); +wchar_t* wcscpy(wchar_t*, const wchar_t*); +wchar_t* wcsncpy(wchar_t*, const wchar_t*, size_t); +wchar_t* wcscat(wchar_t*, const wchar_t*); +int wcscmp(const wchar_t*, const wchar_t*); +wchar_t* wcschr(const wchar_t*, wchar_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/MSL/math_sun.c b/src/MSL/math_sun.c new file mode 100644 index 00000000..889fde89 --- /dev/null +++ b/src/MSL/math_sun.c @@ -0,0 +1,11 @@ +#include "math.h" + +double scalbn(double x, int n) { + double value; + int exp; + + value = frexp(x, &exp); + exp += n; + + return ldexp(value, exp); +} diff --git a/src/MSL/wstring.c b/src/MSL/wstring.c new file mode 100644 index 00000000..2228b3de --- /dev/null +++ b/src/MSL/wstring.c @@ -0,0 +1,117 @@ +#include "wstring.h" + +size_t wcslen(const wchar_t* s) { + const wchar_t* ptr = s - 1; + size_t length = (size_t)-1; + wchar_t current_char; + + do { + current_char = *++ptr; + length++; + } while (current_char != 0); + + return length; +} + +wchar_t* wcscpy(wchar_t* dst, const wchar_t* src) { + wchar_t* original_dst = dst; + const wchar_t* p_src = src - 1; + wchar_t* p_dst = dst - 1; + wchar_t current_char; + + do { + current_char = *++p_src; + *++p_dst = current_char; + } while (current_char != 0); + + return original_dst; +} + +wchar_t* wcsncpy(wchar_t* dst, const wchar_t* src, unsigned long n) { + wchar_t* original_dst = dst; + const wchar_t* p_src = src - 1; + wchar_t* p_dst = dst - 1; + unsigned long count = n + 1; + wchar_t current_char; + + while (--count != 0) { + current_char = *++p_src; + *++p_dst = current_char; + + if (current_char == 0) { + while (--count != 0) { + *++p_dst = 0; + } + goto exit_func; + } + } + +exit_func: + return original_dst; +} + +wchar_t* wcscat(wchar_t* dst, const wchar_t* src) { + const wchar_t* p_src = src - 1; + wchar_t* p_dst = dst - 1; + wchar_t* original_dst = dst; + wchar_t current_char; + do { + current_char = *++p_dst; + } while (current_char != 0); + + p_dst--; + + do { + current_char = *++p_src; + *++p_dst = current_char; + } while (current_char != 0); + return original_dst; +} + +int wcscmp(const wchar_t* s1, const wchar_t* s2) { + unsigned int c1; + wchar_t c2; + const wchar_t* p1 = s1 - 1; + const wchar_t* p2 = s2 - 1; + + goto load_s1_entry; + +null_check: + if (c1 == 0) { + return 0; + } + +load_s1_entry: + c1 = (unsigned int)(*++p1); + c2 = *++p2; + + if (c1 == (unsigned int)c2) { + goto null_check; + } else { + return (int)(c1 - (unsigned int)c2); + } +} + +wchar_t* wcschr(const wchar_t* s, wchar_t c) { + const wchar_t* ptr = s - 1; + wchar_t current_char; + goto load_entry; + +compare_check: + if (current_char == c) { + return (wchar_t*)ptr; + } + +load_entry: + current_char = *++ptr; + + if (current_char != 0) { + goto compare_check; + } + + if (c == 0) { + return (wchar_t*)ptr; + } + + return NULL; +} From 9d9cdccdf69565d25057c1dfbbd7a9f2ace5a1e6 Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Mon, 22 Sep 2025 19:22:15 -0400 Subject: [PATCH 04/25] clean up wstring --- src/MSL/wstring.c | 95 ++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 59 deletions(-) diff --git a/src/MSL/wstring.c b/src/MSL/wstring.c index 2228b3de..e69c240d 100644 --- a/src/MSL/wstring.c +++ b/src/MSL/wstring.c @@ -1,12 +1,12 @@ #include "wstring.h" -size_t wcslen(const wchar_t* s) { - const wchar_t* ptr = s - 1; +size_t wcslen(const wchar_t* str) { + const wchar_t* str_ptr = str - 1; size_t length = (size_t)-1; wchar_t current_char; do { - current_char = *++ptr; + current_char = *++str_ptr; length++; } while (current_char != 0); @@ -15,13 +15,13 @@ size_t wcslen(const wchar_t* s) { wchar_t* wcscpy(wchar_t* dst, const wchar_t* src) { wchar_t* original_dst = dst; - const wchar_t* p_src = src - 1; - wchar_t* p_dst = dst - 1; + const wchar_t* src_ptr = src - 1; + wchar_t* dst_ptr = dst - 1; wchar_t current_char; do { - current_char = *++p_src; - *++p_dst = current_char; + current_char = *++src_ptr; + *++dst_ptr = current_char; } while (current_char != 0); return original_dst; @@ -29,89 +29,66 @@ wchar_t* wcscpy(wchar_t* dst, const wchar_t* src) { wchar_t* wcsncpy(wchar_t* dst, const wchar_t* src, unsigned long n) { wchar_t* original_dst = dst; - const wchar_t* p_src = src - 1; - wchar_t* p_dst = dst - 1; + const wchar_t* src_ptr = src - 1; + wchar_t* dst_ptr = dst - 1; unsigned long count = n + 1; wchar_t current_char; while (--count != 0) { - current_char = *++p_src; - *++p_dst = current_char; + current_char = *++src_ptr; + *++dst_ptr = current_char; if (current_char == 0) { while (--count != 0) { - *++p_dst = 0; + *++dst_ptr = 0; } - goto exit_func; + break; } } -exit_func: return original_dst; } wchar_t* wcscat(wchar_t* dst, const wchar_t* src) { - const wchar_t* p_src = src - 1; - wchar_t* p_dst = dst - 1; + const wchar_t* src_ptr = src - 1; + wchar_t* dst_ptr = dst - 1; wchar_t* original_dst = dst; wchar_t current_char; do { - current_char = *++p_dst; + current_char = *++dst_ptr; } while (current_char != 0); - p_dst--; + dst_ptr--; do { - current_char = *++p_src; - *++p_dst = current_char; + current_char = *++src_ptr; + *++dst_ptr = current_char; } while (current_char != 0); return original_dst; } -int wcscmp(const wchar_t* s1, const wchar_t* s2) { - unsigned int c1; - wchar_t c2; - const wchar_t* p1 = s1 - 1; - const wchar_t* p2 = s2 - 1; +int wcscmp(const wchar_t* str1, const wchar_t* str2) { + const wchar_t* str1_ptr = (wchar_t*)str1 - 1; + const wchar_t* str2_ptr = (wchar_t*)str2 - 1; + wchar_t char1, char2; - goto load_s1_entry; - -null_check: - if (c1 == 0) { - return 0; - } - -load_s1_entry: - c1 = (unsigned int)(*++p1); - c2 = *++p2; - - if (c1 == (unsigned int)c2) { - goto null_check; - } else { - return (int)(c1 - (unsigned int)c2); - } + while ((char1 = *++str1_ptr) == (char2 = *++str2_ptr)) + if (!char1) + return 0; + return char1 - char2; } -wchar_t* wcschr(const wchar_t* s, wchar_t c) { - const wchar_t* ptr = s - 1; +wchar_t* wcschr(const wchar_t* str, wchar_t chr) { + const wchar_t* str_ptr = str - 1; wchar_t current_char; - goto load_entry; -compare_check: - if (current_char == c) { - return (wchar_t*)ptr; - } - -load_entry: - current_char = *++ptr; - - if (current_char != 0) { - goto compare_check; - } + while (current_char = *++str_ptr) + if (current_char == chr) + return ((wchar_t*)str_ptr); - if (c == 0) { - return (wchar_t*)ptr; + if (chr != 0) { + return NULL; + } else { + return (wchar_t*)str_ptr; } - - return NULL; } From 697dd2a769a4f5c7886ce38161ac8ef929d3098f Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Mon, 22 Sep 2025 19:55:36 -0400 Subject: [PATCH 05/25] mem stuff --- configure.py | 4 +- include/MSL/mbstring.h | 20 ++++ include/MSL/mem_funcs.h | 18 ++++ src/MSL/errno.c | 1 + src/MSL/mbstring.c | 107 +++++++++++++++++++++ src/MSL/mem.c | 80 ++++++++++++++++ src/MSL/mem_funcs.c | 204 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 432 insertions(+), 2 deletions(-) create mode 100644 include/MSL/mbstring.h create mode 100644 include/MSL/mem_funcs.h create mode 100644 src/MSL/errno.c create mode 100644 src/MSL/mbstring.c create mode 100644 src/MSL/mem.c create mode 100644 src/MSL/mem_funcs.c diff --git a/configure.py b/configure.py index ffadc309..43e43912 100755 --- a/configure.py +++ b/configure.py @@ -732,13 +732,13 @@ def MatchingFor(*versions): Object(Matching, "MSL/arith.c"), Object(NonMatching, "MSL/buffer_io.c"), Object(NonMatching, "MSL/direct_io.c"), - Object(NonMatching, "MSL/errno.c"), + Object(Matching, "MSL/errno.c"), Object(NonMatching, "MSL/file_io.c"), Object(NonMatching, "MSL/FILE_POS.c"), Object(NonMatching, "MSL/locale.c"), Object(NonMatching, "MSL/mbstring.c"), Object(NonMatching, "MSL/mem.c"), - Object(NonMatching, "MSL/mem_funcs.c"), + Object(Matching, "MSL/mem_funcs.c"), Object(NonMatching, "MSL/math_api.c"), Object(NonMatching, "MSL/misc_io.c"), Object(NonMatching, "MSL/printf.c"), diff --git a/include/MSL/mbstring.h b/include/MSL/mbstring.h new file mode 100644 index 00000000..788f4cff --- /dev/null +++ b/include/MSL/mbstring.h @@ -0,0 +1,20 @@ +#ifndef _MBSTRING_H +#define _MBSTRING_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int __mbtowc_noconv(wchar_t*, const char*, size_t); +int __wctomb_noconv(char*, wchar_t); +int mbtowc(wchar_t*, const char*, size_t); +size_t mbstowcs(wchar_t*, const char*, size_t); +size_t wcstombs(char*, const wchar_t*, size_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/MSL/mem_funcs.h b/include/MSL/mem_funcs.h new file mode 100644 index 00000000..23bdbcc2 --- /dev/null +++ b/include/MSL/mem_funcs.h @@ -0,0 +1,18 @@ +#ifndef MEM_FUNCS_H +#define MEM_FUNCS_H + +#ifdef __cplusplus +extern "C" { +#endif + +void __copy_longs_aligned(void* pDest, const void* pSrc, unsigned long len); +void __copy_longs_rev_aligned(void* pDest, const void* pSrc, unsigned long len); +void __copy_longs_unaligned(void* pDest, const void* pSrc, unsigned long len); +void __copy_longs_rev_unaligned(void* pDest, const void* pSrc, + unsigned long len); + +#ifdef __cplusplus +} +#endif + +#endif // MEM_FUNCS_H diff --git a/src/MSL/errno.c b/src/MSL/errno.c new file mode 100644 index 00000000..507e9212 --- /dev/null +++ b/src/MSL/errno.c @@ -0,0 +1 @@ +int errno[] = {0x00000000, 0x00000000}; diff --git a/src/MSL/mbstring.c b/src/MSL/mbstring.c new file mode 100644 index 00000000..2797f511 --- /dev/null +++ b/src/MSL/mbstring.c @@ -0,0 +1,107 @@ +#include "mbstring.h" + +#include "locale.h" +#include "string.h" + +int mbtowc(wchar_t* dest, const char* s, size_t num) { + // return _current_locale.ctype_cmpt_ptr->decode_mb(dest, s, num); + return 0; // TODO: _current_locale (locale.c) +} + +int __mbtowc_noconv(wchar_t* dest, const char* src, size_t n) { + if (src == 0) { + return 0; + } + + if (n == 0) { + return -1; + } + + if (dest) { + *dest = (unsigned char)*src; + } + + if (!*src) { + return 0; + } + + return 1; +} + +int __wctomb_noconv(char* src, wchar_t cr) { + if (src == 0) { + return 0; + } + + *src = cr; + return 1; +} + +static inline int wctomb(char* src, wchar_t wchar) { + // return _current_locale.ctype_cmpt_ptr->encode_wc(src, wchar); + return 0; // TODO: _current_locale (locale.c) +} + +size_t mbstowcs(wchar_t* pDest, const char* pSrc, size_t num) { + int res; + char* src; + int count; + size_t src_len; + + src_len = strlen(pSrc); + + if (pDest != 0) { + src = (char*)pSrc; + + for (count = 0; count < num; count++) { + if (*src) { + res = mbtowc(pDest++, src, src_len); + + if (res > 0) { + src += res; + src_len -= res; + } else { + return -1; + } + } else { + *pDest = 0; + break; + } + } + } else { + count = 0; + } + + return count; +} + +size_t wcstombs(char* src, const wchar_t* pwcs, size_t n) { + int chars_written = 0; + int result; + char temp[3]; + wchar_t* source; + + if (!src || !pwcs) { + return 0; + } + + source = (wchar_t*)pwcs; + + while (chars_written <= n) { + if (!*source) { + *(src + chars_written) = '\0'; + break; + } else { + result = wctomb(temp, *source++); + + if ((chars_written + result) <= n) { + strncpy(src + chars_written, temp, result); + chars_written += result; + } else { + break; + } + } + } + + return chars_written; +} diff --git a/src/MSL/mem.c b/src/MSL/mem.c new file mode 100644 index 00000000..764161e1 --- /dev/null +++ b/src/MSL/mem.c @@ -0,0 +1,80 @@ +#include "mem_funcs.h" +#include "string.h" + +void* memmove(void* dst, const void* src, size_t len) { + const char* csrc; + char* cdst; + + int reverse = (u32)src < (u32)dst; + + if (len >= 32) { + if (((int)dst ^ (int)src) & 3) { + if (!reverse) { + __copy_longs_unaligned(dst, src, len); + } else { + __copy_longs_rev_unaligned(dst, src, len); + } + } else { + if (!reverse) { + __copy_longs_aligned(dst, src, len); + } else { + __copy_longs_rev_aligned(dst, src, len); + } + } + + return dst; + } else { + if (!reverse) { + for (csrc = (const char*)src - 1, cdst = (char*)dst - 1, len++; + --len;) { + *++cdst = *++csrc; + } + } else { + for (csrc = (const char*)src + len, cdst = (char*)dst + len, len++; + --len;) { + *--cdst = *--csrc; + } + } + } + + return dst; +} + +void* memchr(const void* src, int val, size_t n) { + const u8* p; + u32 v = val & 0xFF; + + for (p = (u8*)src - 1, n++; --n;) { + if ((*++p & 0xFF) == v) { + return (void*)p; + } + } + + return NULL; +} + +void* __memrchr(const void* src, int val, size_t n) { + const u8* p; + u32 v = val & 0xFF; + + for (p = (u8*)src + n, n++; --n;) { + if (*--p == v) { + return (void*)p; + } + } + + return NULL; +} + +int memcmp(const void* src1, const void* src2, size_t n) { + const u8* p1; + const u8* p2; + + for (p1 = (const u8*)src1 - 1, p2 = (const u8*)src2 - 1, n++; --n;) { + if (*++p1 != *++p2) { + return (*p1 < *p2) ? -1 : 1; + } + } + + return 0; +} diff --git a/src/MSL/mem_funcs.c b/src/MSL/mem_funcs.c new file mode 100644 index 00000000..20e92d75 --- /dev/null +++ b/src/MSL/mem_funcs.c @@ -0,0 +1,204 @@ +#include "mem_funcs.h" + +#define srcCharPtr ((unsigned char*)pSrc) +#define destCharPtr ((unsigned char*)pDest) +#define srcLongPtr ((unsigned long*)pSrc) +#define destLongPtr ((unsigned long*)pDest) + +void __copy_longs_aligned(void* pDest, const void* pSrc, unsigned long len) { + unsigned long i = (-(unsigned long)pDest) & 3; + srcCharPtr = ((unsigned char*)pSrc) - 1; + destCharPtr = ((unsigned char*)pDest) - 1; + + if (i != 0) { + len -= i; + + do { + *++(destCharPtr) = *++(srcCharPtr); + } while (--i); + } + + srcLongPtr = ((unsigned long*)(srcCharPtr + 1)) - 1; + destLongPtr = ((unsigned long*)(destCharPtr + 1)) - 1; + + i = len >> 5; + + if (i != 0) { + do { + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + } while (--i); + } + + i = (len & 31) >> 2; + + if (i != 0) { + do { + *++(destLongPtr) = *++(srcLongPtr); + } while (--i); + } + + srcCharPtr = ((unsigned char*)(srcLongPtr + 1)) - 1; + destCharPtr = ((unsigned char*)(destLongPtr + 1)) - 1; + + len &= 3; + + if (len != 0) { + do + *++(destCharPtr) = *++(srcCharPtr); + while (--len); + } +} + +void __copy_longs_rev_aligned(void* pDest, const void* pSrc, + unsigned long len) { + unsigned long i; + srcCharPtr = ((unsigned char*)pSrc) + len; + destCharPtr = ((unsigned char*)pDest) + len; + i = ((unsigned long)destCharPtr) & 3; + + if (i != 0) { + len -= i; + + do { + *--destCharPtr = *--srcCharPtr; + } while (--i); + } + + i = len >> 5; + + if (i != 0) { + do { + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + } while (--i); + } + + i = (len & 31) >> 2; + + if (i != 0) { + do { + *--destLongPtr = *--srcLongPtr; + } while (--i); + } + + len &= 3; + + if (len != 0) { + do { + *--destCharPtr = *--srcCharPtr; + } while (--len); + } +} + +void __copy_longs_unaligned(void* pDest, const void* pSrc, unsigned long len) { + unsigned long i, v1, v2; + unsigned int src, ls, rs; + + i = (-(unsigned long)pDest) & 3; + srcCharPtr = ((unsigned char*)pSrc) - 1; + destCharPtr = ((unsigned char*)pDest) - 1; + + if (i != 0) { + len -= i; + + do { + *++destCharPtr = *++srcCharPtr; + } while (--i); + } + + src = ((unsigned int)(srcCharPtr + 1)) & 3; + ls = src << 3; + rs = 32 - ls; + + srcCharPtr -= src; + + srcLongPtr = ((unsigned long*)(srcCharPtr + 1)) - 1; + destLongPtr = ((unsigned long*)(destCharPtr + 1)) - 1; + + i = len >> 3; + v1 = *++srcLongPtr; + + do { + v2 = *++srcLongPtr; + *++destLongPtr = (v1 << ls) | (v2 >> rs); + v1 = *++srcLongPtr; + *++destLongPtr = (v2 << ls) | (v1 >> rs); + } while (--i); + + if (len & 4) { + v2 = *++srcLongPtr; + *++destLongPtr = (v1 << ls) | (v2 >> rs); + } + + srcCharPtr = ((unsigned char*)(srcLongPtr + 1)) - 1; + destCharPtr = ((unsigned char*)(destLongPtr + 1)) - 1; + + len &= 3; + + if (len != 0) { + srcCharPtr -= 4 - src; + do { + *++destCharPtr = *++srcCharPtr; + } while (--len); + } +} + +void __copy_longs_rev_unaligned(void* pDest, const void* pSrc, + unsigned long len) { + unsigned long i, v1, v2; + unsigned int src, ls, rs; + + srcCharPtr = ((unsigned char*)pSrc) + len; + destCharPtr = ((unsigned char*)pDest) + len; + i = ((unsigned long)pDest) & 3; + + if (i != 0) { + len -= i; + + do { + *--destCharPtr = *--srcCharPtr; + } while (--i); + } + + src = ((unsigned int)(srcCharPtr)) & 3; + ls = src << 3; + rs = 32 - ls; + + srcCharPtr += 4 - src; + i = len >> 3; + v1 = *--srcLongPtr; + + do { + v2 = *--srcLongPtr; + *--destLongPtr = (v2 << ls) | (v1 >> rs); + v1 = *--srcLongPtr; + *--destLongPtr = (v1 << ls) | (v2 >> rs); + } while (--i); + + if (len & 4) { + v2 = *--srcLongPtr; + *--destLongPtr = (v2 << ls) | (v1 >> rs); + } + + len &= 3; + + if (len != 0) { + srcCharPtr += src; + do { + *--destCharPtr = *--srcCharPtr; + } while (--len); + } +} From cc5770f132987f2c57b47b0ad35a04410dce8e38 Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Mon, 22 Sep 2025 22:49:34 -0400 Subject: [PATCH 06/25] string and wstring stuff --- configure.py | 8 +- include/MSL/wctype.h | 10 ++ include/MSL/wmem.h | 9 ++ src/MSL/abort_exit_ppc_eabi.c | 1 + src/MSL/errno.c | 2 +- src/MSL/math_sun.c | 1 + src/MSL/string.c | 255 ++++++++++++++++++++++++++++++++++ src/MSL/wctype.c | 77 ++++++++++ src/MSL/wmem.c | 18 +++ 9 files changed, 376 insertions(+), 5 deletions(-) create mode 100644 include/MSL/wctype.h create mode 100644 include/MSL/wmem.h create mode 100644 src/MSL/abort_exit_ppc_eabi.c create mode 100644 src/MSL/string.c create mode 100644 src/MSL/wctype.c create mode 100644 src/MSL/wmem.c diff --git a/configure.py b/configure.py index 43e43912..06a1e471 100755 --- a/configure.py +++ b/configure.py @@ -744,16 +744,16 @@ def MatchingFor(*versions): Object(NonMatching, "MSL/printf.c"), Object(Matching, "MSL/rand.c"), Object(NonMatching, "MSL/scanf.c"), - Object(NonMatching, "MSL/string.c"), + Object(Matching, "MSL/string.c"), Object(NonMatching, "MSL/strtold.c"), Object(NonMatching, "MSL/strtoul.c"), - Object(NonMatching, "MSL/wctype.c"), - Object(NonMatching, "MSL/wmem.c"), + Object(Matching, "MSL/wctype.c"), + Object(Matching, "MSL/wmem.c"), Object(NonMatching, "MSL/wprintf.c"), Object(Matching, "MSL/wstring.c"), Object(NonMatching, "MSL/wchar_io.c"), Object(NonMatching, "MSL/uart_console_io_gcn.c"), - Object(NonMatching, "MSL/abort_exit_ppc_eabi.c"), + Object(Matching, "MSL/abort_exit_ppc_eabi.c"), Object(NonMatching, "MSL/math_sun.c"), Object(NonMatching, "MSL/math_float.c"), Object(NonMatching, "MSL/extras.c"), diff --git a/include/MSL/wctype.h b/include/MSL/wctype.h new file mode 100644 index 00000000..788ec040 --- /dev/null +++ b/include/MSL/wctype.h @@ -0,0 +1,10 @@ +#ifndef WCTYPE_H +#define WCTYPE_H + +#include "types.h" + +extern const unsigned short __wctype_mapC[0x100]; +extern const wchar_t __wlower_mapC[0x100]; +extern const wchar_t __wupper_mapC[0x100]; + +#endif // WCTYPE_H diff --git a/include/MSL/wmem.h b/include/MSL/wmem.h new file mode 100644 index 00000000..f581d950 --- /dev/null +++ b/include/MSL/wmem.h @@ -0,0 +1,9 @@ +#ifndef MSL_WMEM_H +#define MSL_WMEM_H + +#include "types.h" + +wchar_t* wmemcpy(wchar_t*, const wchar_t*, size_t); +wchar_t* wmemchr(wchar_t*, wchar_t, size_t); + +#endif diff --git a/src/MSL/abort_exit_ppc_eabi.c b/src/MSL/abort_exit_ppc_eabi.c new file mode 100644 index 00000000..81f51745 --- /dev/null +++ b/src/MSL/abort_exit_ppc_eabi.c @@ -0,0 +1 @@ +void (*__stdio_exit)(void); \ No newline at end of file diff --git a/src/MSL/errno.c b/src/MSL/errno.c index 507e9212..6e7bb62b 100644 --- a/src/MSL/errno.c +++ b/src/MSL/errno.c @@ -1 +1 @@ -int errno[] = {0x00000000, 0x00000000}; +int errno; diff --git a/src/MSL/math_sun.c b/src/MSL/math_sun.c index 889fde89..b7640f0b 100644 --- a/src/MSL/math_sun.c +++ b/src/MSL/math_sun.c @@ -1,3 +1,4 @@ +#include #include "math.h" double scalbn(double x, int n) { diff --git a/src/MSL/string.c b/src/MSL/string.c new file mode 100644 index 00000000..58e1337a --- /dev/null +++ b/src/MSL/string.c @@ -0,0 +1,255 @@ +#include "string.h" + +#define K1 0x80808080 +#define K2 0xFEFEFEFF + +#define set_unk(x, y) \ + x[(unsigned char)(y) >> 3] |= (unsigned char)(1 << ((y)&7)) +#define cond_unk(x, y) \ + (x[(unsigned char)(y) >> 3] & (unsigned char)(1 << ((y)&7))) +typedef unsigned char unk[32]; + +// thanks metrowerks very cool +char* strcpy(char* dst, const char* src) { + register u8 *destb, *fromb; + register u32 w, t, align; + + fromb = (u8*)src; + destb = (u8*)dst; + + if ((align = ((int)fromb & 3)) != ((int)destb & 3)) { + goto bytecopy; + } + + if (align) { + if ((*destb = *fromb) == 0) { + return (dst); + } + for (align = 3 - align; align; align--) { + if ((*(++destb) = *(++fromb)) == 0) { + return (dst); + } + } + ++destb; + ++fromb; + } + + w = *((int*)(fromb)); + + t = w + K2; + t &= ~w; + t &= K1; + if (t) { + goto bytecopy; + } + --((int*)(destb)); + + do { + *(++((int*)(destb))) = w; + w = *(++((int*)(fromb))); + + t = w + K2; + t &= ~w; + t &= K1; + if (t) { + goto adjust; + } + } while (1); + +adjust: + ++((int*)(destb)); +bytecopy: + if ((*destb = *fromb) == 0) { + return dst; + } + do { + if ((*(++destb) = *(++fromb)) == 0) { + return dst; + } + } while (1); + + return dst; +} + +char* strncpy(char* dst, const char* src, size_t n) { + const unsigned char* p = (const unsigned char*)src - 1; + unsigned char* q = (unsigned char*)dst - 1; + unsigned char zero = 0; + + n++; + + while (--n) { + if (!(*++q = *++p)) { + while (--n) { + *++q = 0; + } + break; + } + } + return (dst); +} + +char* strcat(char* dst, const char* src) { + const u8* p = (u8*)src - 1; + u8* q = (u8*)dst - 1; + + while (*++q) + ; + + q--; + + while (*++q = *++p) + ; + + return (dst); +} + +char* strncat(char* dst, const char* src, size_t n) { + const u8* p = (u8*)src - 1; + u8* q = (u8*)dst - 1; + + while (*++q) + ; + + q--; + n++; + + while (--n) { + if (!(*++q = *++p)) { + q--; + break; + } + } + + *++q = 0; + + return dst; +} + +int strcmp(const char* str1, const char* str2) { + // bless metrowerks for this implementation + register u8* left = (u8*)str1; + register u8* right = (u8*)str2; + u32 align, l1, r1, x; + + l1 = *left; + r1 = *right; + if (l1 - r1) { + return (l1 - r1); + } + + if ((align = ((int)left & 3)) != ((int)right & 3)) { + goto bytecopy; + } + if (align) { + if (l1 == 0) { + return 0; + } + for (align = 3 - align; align; align--) { + l1 = *(++left); + r1 = *(++right); + if (l1 - r1) { + return (l1 - r1); + } + if (l1 == 0) { + return 0; + } + } + left++; + right++; + } + + l1 = *(int*)left; + r1 = *(int*)right; + x = l1 + K2; + x &= ~l1; + if (x & K1) { + goto adjust; + } + while (l1 == r1) { + l1 = *(++((int*)(left))); + r1 = *(++((int*)(right))); + x = l1 + K2; + if (x & K1) { + goto adjust; + } + } + +adjust: + l1 = *left; + r1 = *right; + if (l1 - r1) { + return (l1 - r1); + } +bytecopy: + if (l1 == 0) { + return 0; + } + do { + l1 = *(++left); + r1 = *(++right); + if (l1 - r1) { + return (l1 - r1); + } + if (l1 == 0) { + return 0; + } + } while (1); +} + +int strncmp(const char* str1, const char* str2, size_t n) { + const u8* p1 = (u8*)str1 - 1; + const u8* p2 = (u8*)str2 - 1; + u32 c1, c2; + + n++; + + while (--n) { + if ((c1 = *++p1) != (c2 = *++p2)) { + return (c1 - c2); + } else if (!c1) { + break; + } + } + return 0; +} + +char* strchr(const char* str, int chr) { + const u8* p = (u8*)str - 1; + u32 c = (chr & 0xFF); + u32 ch; + + while (ch = *++p) { + if (ch == c) { + return ((char*)p); + } + } + + return (c ? 0 : (char*)p); +} + +char* strstr(const char* str, const char* pat) { + u8* s1 = (u8*)str - 1; + u8* p1 = (u8*)pat - 1; + u32 firstc, c1, c2; + + if (pat == NULL || !(firstc = *++p1)) { + return (char*)str; + } + + while ((c1 = *++s1)) { + if (c1 == firstc) { + const u8* s2 = s1 - 1; + const u8* p2 = p1 - 1; + + while ((c1 = *(++s2)) == (c2 = *(++p2)) && c1) + ; + + if (!c2) { + return (char*)s1; + } + } + } + + return NULL; +} diff --git a/src/MSL/wctype.c b/src/MSL/wctype.c new file mode 100644 index 00000000..60ac9ac3 --- /dev/null +++ b/src/MSL/wctype.c @@ -0,0 +1,77 @@ +#include "wctype.h" + +const unsigned short __wctype_mapC[0x100] = { + 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x106, 0x104, + 0x104, 0x104, 0x104, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x142, + 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + 0xD0, 0xD0, 0xD0, 0xD0, 0x458, 0x458, 0x458, 0x458, 0x458, 0x458, 0x458, + 0x458, 0x458, 0x458, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x651, + 0x651, 0x651, 0x651, 0x651, 0x651, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, + 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, + 0x251, 0x251, 0x251, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x471, 0x471, + 0x471, 0x471, 0x471, 0x471, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, + 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, + 0x71, 0x71, 0xD0, 0xD0, 0xD0, 0xD0, 0x4}; + +const wchar_t __wlower_mapC[0x100] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, + 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, + 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, + 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, L' ', L'!', L'"', L'#', + L'$', L'%', L'&', L'\'', L'(', L')', L'*', L'+', L',', + L'-', L'.', L'/', L'0', L'1', L'2', L'3', L'4', L'5', + L'6', L'7', L'8', L'9', L':', L';', L'<', L'=', L'>', + L'?', L'@', L'a', L'b', L'c', L'd', L'e', L'f', L'g', + L'h', L'i', L'j', L'k', L'l', L'm', L'n', L'o', L'p', + L'q', L'r', L's', L't', L'u', L'v', L'w', L'x', L'y', + L'z', L'[', L'\\', L']', L'^', L'_', L'`', L'a', L'b', + L'c', L'd', L'e', L'f', L'g', L'h', L'i', L'j', L'k', + L'l', L'm', L'n', L'o', L'p', L'q', L'r', L's', L't', + L'u', L'v', L'w', L'x', L'y', L'z', L'{', L'|', L'}', + L'~', 0x007F, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, + 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, + 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, + 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, + 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, + 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, + 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, + 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, + 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, + 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, + 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, + 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, + 0x00FC, 0x00FD, 0x00FE, 0x00FF}; + +const wchar_t __wupper_mapC[0x100] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, + 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, + 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, + 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, L' ', L'!', L'"', L'#', + L'$', L'%', L'&', L'\'', L'(', L')', L'*', L'+', L',', + L'-', L'.', L'/', L'0', L'1', L'2', L'3', L'4', L'5', + L'6', L'7', L'8', L'9', L':', L';', L'<', L'=', L'>', + L'?', L'@', L'A', L'B', L'C', L'D', L'E', L'F', L'G', + L'H', L'I', L'J', L'K', L'L', L'M', L'N', L'O', L'P', + L'Q', L'R', L'S', L'T', L'U', L'V', L'W', L'X', L'Y', + L'Z', L'[', L'\\', L']', L'^', L'_', L'`', L'A', L'B', + L'C', L'D', L'E', L'F', L'G', L'H', L'I', L'J', L'K', + L'L', L'M', L'N', L'O', L'P', L'Q', L'R', L'S', L'T', + L'U', L'V', L'W', L'X', L'Y', L'Z', L'{', L'|', L'}', + L'~', 0x007F, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, + 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, + 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, + 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, + 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, + 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, + 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, + 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, + 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, + 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, + 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, + 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, + 0x00FC, 0x00FD, 0x00FE, 0x00FF}; diff --git a/src/MSL/wmem.c b/src/MSL/wmem.c new file mode 100644 index 00000000..d434f7f3 --- /dev/null +++ b/src/MSL/wmem.c @@ -0,0 +1,18 @@ +#include + +wchar_t* wmemcpy(wchar_t* dest, const wchar_t* src, size_t n) { + return (wchar_t*)memcpy(dest, src, n * sizeof(wchar_t)); +} + +wchar_t* wmemchr(wchar_t* s, wchar_t c, size_t n) { + while (n) { + if (*s == c) { + return s; + } + + s++; + n--; + } + + return NULL; +} From 6a2fad7c857632e1539b19f7e0dcab3ffc70583b Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Mon, 22 Sep 2025 23:49:28 -0400 Subject: [PATCH 07/25] misc_io --- configure.py | 2 +- src/MSL/misc_io.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 src/MSL/misc_io.c diff --git a/configure.py b/configure.py index 06a1e471..48d8aa0a 100755 --- a/configure.py +++ b/configure.py @@ -740,7 +740,7 @@ def MatchingFor(*versions): Object(NonMatching, "MSL/mem.c"), Object(Matching, "MSL/mem_funcs.c"), Object(NonMatching, "MSL/math_api.c"), - Object(NonMatching, "MSL/misc_io.c"), + Object(Matching, "MSL/misc_io.c"), Object(NonMatching, "MSL/printf.c"), Object(Matching, "MSL/rand.c"), Object(NonMatching, "MSL/scanf.c"), diff --git a/src/MSL/misc_io.c b/src/MSL/misc_io.c new file mode 100644 index 00000000..b4d0329a --- /dev/null +++ b/src/MSL/misc_io.c @@ -0,0 +1,6 @@ +extern void (*__stdio_exit)(void); +void __close_all(void); + +void __stdio_atexit(void) { + __stdio_exit = __close_all; +} From e1635121bbb019a6ee84ae881f288acfb70980bb Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Tue, 23 Sep 2025 00:52:37 -0400 Subject: [PATCH 08/25] locale --- include/MSL/ansi_params.h | 14 ++++ include/MSL/ctype.h | 41 ++-------- include/MSL/limits.h | 4 + include/MSL/locale.h | 154 ++++++++++++++++++++++++++++---------- src/MSL/ctype.c | 73 ++++++++++++++++++ src/MSL/locale.c | 121 ++++++++++++++++++++++++++++++ 6 files changed, 335 insertions(+), 72 deletions(-) create mode 100644 include/MSL/ansi_params.h create mode 100644 src/MSL/ctype.c create mode 100644 src/MSL/locale.c diff --git a/include/MSL/ansi_params.h b/include/MSL/ansi_params.h new file mode 100644 index 00000000..969bf9f5 --- /dev/null +++ b/include/MSL/ansi_params.h @@ -0,0 +1,14 @@ +#ifndef ANSI_PARAMS_H +#define ANSI_PARAMS_H + +#define _MSL_CANT_THROW __attribute__((nothrow)) + +#define _MSL_THROW throw() + +#ifndef _MSL_LOCALDATA +#define _MSL_LOCALDATA(_a) _a +#endif + +#define __std(ref) ref + +#endif // ANSI_PARAMS_H diff --git a/include/MSL/ctype.h b/include/MSL/ctype.h index 1a3d9807..c44a3a8f 100644 --- a/include/MSL/ctype.h +++ b/include/MSL/ctype.h @@ -1,37 +1,10 @@ -#ifndef MSL_CTYPE_H -#define MSL_CTYPE_H -#include -#ifdef __cplusplus -extern "C" { -#endif +#ifndef CTYPE_H +#define CTYPE_H -typedef struct __CMap { - char UNK_0x0[0x10]; - const u8* to_lower_table; // at 0x10 - const u8* to_upper_table; // at 0x14 -} __CMap; +extern const unsigned char __lower_mapC[0x100]; +extern const unsigned char __upper_mapC[0x100]; +extern const unsigned short __ctype_mapC[0x100]; -typedef struct __Locale { - char UNK_0x0[0x38]; - struct __CMap* cmap; // at 0x38 - char UNK_0x3C[0x44 - 0x3C]; -} __Locale; +int tolower(int); -extern __Locale _current_locale; - -inline int tolower(int x) { - return (x < 0 || x >= 256) - ? x - : (int)(&_current_locale)->cmap->to_lower_table[x]; -} - -inline int toupper(int x) { - return (x < 0 || x >= 256) - ? x - : (int)(&_current_locale)->cmap->to_upper_table[x]; -} - -#ifdef __cplusplus -} -#endif -#endif +#endif // CTYPE_H diff --git a/include/MSL/limits.h b/include/MSL/limits.h index 3524bf95..86ec85f3 100644 --- a/include/MSL/limits.h +++ b/include/MSL/limits.h @@ -25,6 +25,10 @@ extern "C" { #define LONG_MAX INT_MAX #define ULONG_MAX 4294967295 +#define LLONG_MIN (-0x7FFFFFFFFFFFFFFFLL - 1) +#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL +#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL + #ifdef __cplusplus } #endif diff --git a/include/MSL/locale.h b/include/MSL/locale.h index b0fb693e..d4e4ab82 100644 --- a/include/MSL/locale.h +++ b/include/MSL/locale.h @@ -1,38 +1,116 @@ -#ifndef MSL_LOCALE_H -#define MSL_LOCALE_H -#include -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct lconv { - char* decimal_point; // at 0x0 - char* thousands_sep; // at 0x4 - char* grouping; // at 0x8 - char* currency_symbol; // at 0xC - char* mon_decimal_point; // at 0x10 - char* mon_thousands_sep; // at 0x14 - char* mon_grouping; // at 0x18 - char* positive_sign; // at 0x1C - char* negative_sign; // at 0x20 - char int_frac_digits; // at 0x24 - char frac_digits; // at 0x25 - char p_cs_precedes; // at 0x26 - char p_sep_by_space; // at 0x27 - char n_cs_precedes; // at 0x28 - char n_sep_by_space; // at 0x29 - char p_sign_posn; // at 0x2A - char n_sign_posn; // at 0x2B - char* int_curr_symbol; // at 0x2C - char int_p_cs_precedes; // at 0x30 - char int_n_cs_precedes; // at 0x31 - char int_p_sep_by_space; // at 0x32 - char int_n_sep_by_space; // at 0x33 - char int_p_sign_posn; // at 0x34 - char int_n_sign_posn; // at 0x35 -} lconv; - -#ifdef __cplusplus -} -#endif -#endif +#ifndef LOCALE_H +#define LOCALE_H + +#include "ansi_params.h" +//#include "size_t.h" +#include "wchar_io.h" + +typedef int (* __decode_mbyte) (wchar_t *, const char *, __std(size_t)); +typedef int (* __encode_mbyte) (char *, wchar_t); + +struct lconv { + char* decimal_point; + char* thousands_sep; + char* grouping; + char* mon_decimal_point; + char* mon_thousands_sep; + char* mon_grouping; + char* positive_sign; + char* negative_sign; + char* currency_symbol; + char frac_digits; + char p_cs_precedes; + char n_cs_precedes; + char p_sep_by_space; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + char* int_curr_symbol; + char int_frac_digits; + char int_p_cs_precedes; + char int_n_cs_precedes; + char int_p_sep_by_space; + char int_n_sep_by_space; + char int_p_sign_posn; + char int_n_sign_posn; +}; + +struct _loc_mon_cmpt { + char CmptName[8]; + char* mon_decimal_point; + char* mon_thousands_sep; + char* mon_grouping; + char* positive_sign; + char* negative_sign; + char* currency_symbol; + char frac_digits; + char p_cs_precedes; + char n_cs_precedes; + char p_sep_by_space; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + char* int_curr_symbol; + char int_frac_digits; + char int_p_cs_precedes; + char int_n_cs_precedes; + char int_p_sep_by_space; + char int_n_sep_by_space; + char int_p_sign_posn; + char int_n_sign_posn; +}; + +struct _loc_num_cmpt { + char CmptName[8]; + char* decimal_point; + char* thousands_sep; + char* grouping; +}; + +struct _loc_time_cmpt { + char CmptName[8]; + const char* am_pm; + const char* DateTime_Format; + const char* Twelve_hr_format; + const char* Date_Format; + const char* Time_Format; + const char* Day_Names; + const char* MonthNames; + char* TimeZone; +}; + +struct _loc_coll_cmpt { + char name[8]; + int char_start; + int char_coll_tab_size; + short char_spec; + unsigned short* char_coll_table_ptr; + unsigned short* wchar_coll_seq_ptr; +}; + +struct _loc_ctype_cmpt { + char name[8]; // 0x0 + const unsigned short* ctype_map_ptr; // 0x8 + const unsigned char* upper_map_ptr; // 0xC + const unsigned char* lower_map_ptr; // 0x10 + const unsigned short* wctype_map_ptr; // 0x14 + const wchar_t* wupper_map_ptr; // 0x18 + const wchar_t* wlower_map_ptr; // 0x1C + __decode_mbyte decode_mb; + __encode_mbyte encode_wc; +}; + +struct __locale { + struct __locale* next_locale; // 0x0 + char name[0x30]; // 0x4 + struct _loc_coll_cmpt* coll_cmpt_ptr; // 0x34 + struct _loc_ctype_cmpt* ctype_cmpt_ptr; // 0x38 + struct _loc_mon_cmpt* mon_cmpt_ptr; // 0x3C + struct _loc_num_cmpt* num_cmpt_ptr; // 0x40 + struct _loc_time_cmpt* time_cmpt_ptr; // 0x44 +}; + +extern struct __locale _current_locale; +extern struct lconv __lconv; + +#endif // LOCALE_H \ No newline at end of file diff --git a/src/MSL/ctype.c b/src/MSL/ctype.c new file mode 100644 index 00000000..8a295931 --- /dev/null +++ b/src/MSL/ctype.c @@ -0,0 +1,73 @@ +#include "ctype.h" + +#include "locale.h" + +const unsigned short __ctype_mapC[0x100] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 0x106, 0x104, + 0x104, 0x104, 0x104, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0x142, + 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + 0xD0, 0xD0, 0xD0, 0xD0, 0x458, 0x458, 0x458, 0x458, 0x458, 0x458, 0x458, + 0x458, 0x458, 0x458, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x651, + 0x651, 0x651, 0x651, 0x651, 0x651, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, + 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, + 0x251, 0x251, 0x251, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x471, 0x471, + 0x471, 0x471, 0x471, 0x471, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, + 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, + 4 + +}; + +const unsigned char __lower_mapC[0x100] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, ' ', '!', '"', '#', + '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', + '<', '=', '>', '?', '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', 0x7F, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, + 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, + 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, + 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, + 0xFC, 0xFD, 0xFE, 0xFF}; + +const unsigned char __upper_mapC[0x100] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, ' ', '!', '"', '#', + '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', + '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '{', '|', '}', '~', 0x7F, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, + 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, + 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, + 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, + 0xFC, 0xFD, 0xFE, 0xFF}; + +int tolower(int c) { + return ((c < 0) || (c >= 0x100)) + ? c + : (int)(_current_locale.ctype_cmpt_ptr->lower_map_ptr[c]); +} diff --git a/src/MSL/locale.c b/src/MSL/locale.c new file mode 100644 index 00000000..411257f7 --- /dev/null +++ b/src/MSL/locale.c @@ -0,0 +1,121 @@ +#include "locale.h" +#include "mbstring.h" +#include "ctype.h" +#include "wctype.h" + +#pragma options align=native +#pragma warn_padding off +struct lconv __lconv = { + ".", + "", + "", + "", + "", + "", + "", + "", + "", + 127, + 127, + 127, + 127, + 127, + 127, + 127, + "", + 127, + 127, + 127, + 127, + 127, + 127, + 127 +}; +#pragma warn_padding reset +#pragma options align=reset + +struct _loc_ctype_cmpt _loc_ctyp_C = { + "C", + &__ctype_mapC[0], + &__upper_mapC[0], + &__lower_mapC[0], + &__wctype_mapC[0], + &__wupper_mapC[0], + &__wlower_mapC[0], + __mbtowc_noconv, + __wctomb_noconv +}; + + +unsigned short char_coll_tableC[0x60] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x39, 0x3b, 0x3d, 0x3f, 0x41, 0x43, 0x45, 0x47, + 0x49, 0x4b, 0x4d, 0x4f, 0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x18, 0x19, 0x1a, 0x1b, 0x1c, + 0x00, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x46, 0x48, + 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x1d, 0x1e, 0x1f, 0x20 +}; + +struct _loc_coll_cmpt _loc_coll_C = { + "C", + 0x20, + 0x6E, + 0, + (unsigned short*)&char_coll_tableC[0], + 0 +}; + +struct _loc_mon_cmpt _loc_mon_C = { + "C", + "", + "", + "", + "", + "", + "", + 127, + 127, + 127, + 127, + 127, + 127, + 127, + "", + 127, + 127, + 127, + 127, + 127, + 127, + 127 +}; + +struct _loc_num_cmpt _loc_num_C = { + "C", + ".", + "", + "" +}; + +struct _loc_time_cmpt _loc_tim_C = { + "C", + "AM|PM", + "%a %b %e %T %Y", + "%I:%M:%S %p", + "%m/%d/%y", + "%T", + "Sun|Sunday|Mon|Monday|Tue|Tuesday|Wed|Wednesday|Thu|Thursday|Fri|Friday|Sat|Saturday", + "Jan|January|Feb|February|Mar|March|Apr|April|May|May|Jun|June|Jul|July|Aug|August|Sep|September|Oct|October|Nov|November|Dec|December", + "" +}; + + +struct __locale _current_locale = { + 0, + "C", + &_loc_coll_C, + &_loc_ctyp_C, + &_loc_mon_C, + &_loc_num_C, + &_loc_tim_C +}; From 756238bfb168848a864c855607bdcbfc3a6e5b44 Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Tue, 23 Sep 2025 02:12:02 -0400 Subject: [PATCH 09/25] file io stuff --- configure.py | 24 +++--- include/MSL/buffer_io.h | 9 +++ include/MSL/internal/file_io.h | 6 +- include/MSL/internal/file_struct.h | 85 +++++++++++++++++++++ include/MSL/math_api.h | 14 ++++ src/MSL/FILE_POS.c | 103 +++++++++++++++++++++++++ src/MSL/buffer_io.c | 37 +++++++++ src/MSL/direct_io.c | 116 +++++++++++++++++++++++++++++ src/MSL/extras.c | 28 +++++++ src/MSL/file_io.c | 72 ++++++++++++++++++ src/MSL/math_api.c | 32 ++++++++ src/MSL/math_sun.c | 3 +- src/MSL/mbstring.c | 2 + src/MSL/mem.c | 2 + 14 files changed, 516 insertions(+), 17 deletions(-) create mode 100644 include/MSL/buffer_io.h create mode 100644 include/MSL/internal/file_struct.h create mode 100644 include/MSL/math_api.h create mode 100644 src/MSL/FILE_POS.c create mode 100644 src/MSL/buffer_io.c create mode 100644 src/MSL/direct_io.c create mode 100644 src/MSL/extras.c create mode 100644 src/MSL/file_io.c create mode 100644 src/MSL/math_api.c diff --git a/configure.py b/configure.py index 48d8aa0a..28cfe19b 100755 --- a/configure.py +++ b/configure.py @@ -727,37 +727,37 @@ def MatchingFor(*versions): "progress_category": "sdk", "objects": [ Object(NonMatching, "MSL/alloc.c"), + Object(Matching, "MSL/errno.c"), Object(NonMatching, "MSL/ansi_files.c"), Object(NonMatching, "MSL/ansi_fp.c"), - Object(Matching, "MSL/arith.c"), - Object(NonMatching, "MSL/buffer_io.c"), - Object(NonMatching, "MSL/direct_io.c"), - Object(Matching, "MSL/errno.c"), - Object(NonMatching, "MSL/file_io.c"), - Object(NonMatching, "MSL/FILE_POS.c"), Object(NonMatching, "MSL/locale.c"), + Object(Matching, "MSL/arith.c"), + Object(Matching, "MSL/buffer_io.c"), + Object(Matching, "MSL/direct_io.c"), + Object(Matching, "MSL/file_io.c"), + Object(Matching, "MSL/FILE_POS.c"), Object(NonMatching, "MSL/mbstring.c"), - Object(NonMatching, "MSL/mem.c"), + Object(Matching, "MSL/mem.c"), Object(Matching, "MSL/mem_funcs.c"), - Object(NonMatching, "MSL/math_api.c"), + Object(Matching, "MSL/math_api.c"), Object(Matching, "MSL/misc_io.c"), Object(NonMatching, "MSL/printf.c"), Object(Matching, "MSL/rand.c"), + Object(Matching, "MSL/float.c"), Object(NonMatching, "MSL/scanf.c"), Object(Matching, "MSL/string.c"), Object(NonMatching, "MSL/strtold.c"), - Object(NonMatching, "MSL/strtoul.c"), Object(Matching, "MSL/wctype.c"), + Object(NonMatching, "MSL/strtoul.c"), Object(Matching, "MSL/wmem.c"), Object(NonMatching, "MSL/wprintf.c"), Object(Matching, "MSL/wstring.c"), Object(NonMatching, "MSL/wchar_io.c"), Object(NonMatching, "MSL/uart_console_io_gcn.c"), Object(Matching, "MSL/abort_exit_ppc_eabi.c"), - Object(NonMatching, "MSL/math_sun.c"), + Object(Matching, "MSL/math_sun.c"), Object(NonMatching, "MSL/math_float.c"), - Object(NonMatching, "MSL/extras.c"), - Object(Matching, "MSL/float.c"), + Object(Matching, "MSL/extras.c"), Object(Matching, "MSL/e_acos.c"), Object(Matching, "MSL/e_asin.c"), Object(Matching, "MSL/e_atan2.c"), diff --git a/include/MSL/buffer_io.h b/include/MSL/buffer_io.h new file mode 100644 index 00000000..dec792b1 --- /dev/null +++ b/include/MSL/buffer_io.h @@ -0,0 +1,9 @@ +#ifndef BUFFER_IO_H +#define BUFFER_IO_H + +#include "file_struct.h" + +void __prep_buffer(FILE*); +int __flush_buffer(FILE*, size_t*); + +#endif // BUFFER_IO_H diff --git a/include/MSL/internal/file_io.h b/include/MSL/internal/file_io.h index 40ec5785..6fd55fd7 100644 --- a/include/MSL/internal/file_io.h +++ b/include/MSL/internal/file_io.h @@ -1,13 +1,11 @@ #ifndef MSL_FILE_IO_H #define MSL_FILE_IO_H -#include +#include #ifdef __cplusplus extern "C" { #endif -typedef struct FILE { - u8 dummy; -} FILE; + int fclose(FILE*); int fflush(FILE*); diff --git a/include/MSL/internal/file_struct.h b/include/MSL/internal/file_struct.h new file mode 100644 index 00000000..3a551bf3 --- /dev/null +++ b/include/MSL/internal/file_struct.h @@ -0,0 +1,85 @@ +#ifndef FILE_STRUCT_H +#define FILE_STRUCT_H + +#include "ansi_params.h" +#include + +enum file_kinds { + file_closed, + file_disk, + file_console, + file_unavailable +}; + +enum open_modes { + must_exist, + create_if_needed, + create_or_truncate +}; + +enum file_orientation { + file_unoriented, + file_char_oriented, + file_wide_oriented +}; + +typedef struct { + unsigned int open : 2; + unsigned int io : 3; + unsigned int buffer : 2; + unsigned int file : 3; + unsigned int file_orientation : 2; + unsigned int binary : 1; +} file_modes; + +enum io_states { + neutral, + writing, + reading, + rereading +}; + +typedef struct +{ + unsigned int io_state : 3; + unsigned int free_buffer : 1; + unsigned char eof; + unsigned char error; +} file_state; + +typedef unsigned long file_handle; +typedef struct _FILE FILE; +typedef int (* __pos_proc)(unsigned long, long *, int, void *); +typedef int (* __io_proc)(unsigned long, unsigned char *, size_t *, void *); +typedef int (* __close_proc)(unsigned long); + +struct _FILE { + file_handle handle; + file_modes mode; + file_state state; + unsigned char is_dyn_alloc; + unsigned char char_buf; + unsigned char char_buf_of; + unsigned char unget_buffer[2]; + wchar_t ungetwc_buffer[2]; + unsigned long pos; + unsigned char* buffer; + unsigned long buffer_size; + unsigned char* buffer_ptr; + unsigned long buffer_len; + unsigned long buffer_alignment; + unsigned long unk; + unsigned long buffer_pos; + __pos_proc pos_proc; + __io_proc read_proc; + __io_proc write_proc; + __close_proc close_proc; + void* ref; + struct _FILE* next_file; +}; + +extern FILE __files[]; + +#define stdout (&__std(__files[1])) + +#endif // FILE_STRUCT_H \ No newline at end of file diff --git a/include/MSL/math_api.h b/include/MSL/math_api.h new file mode 100644 index 00000000..f55ccfad --- /dev/null +++ b/include/MSL/math_api.h @@ -0,0 +1,14 @@ +#ifndef MATH_API_H +#define MATH_API_H + +int __fpclassifyf(float); +int __signbitd(double); +int __fpclassifyd(double); + +double copysign(double, double); +double frexp(double, int *); +double ldexp(double, int); + +double nan(const char *); + +#endif // MATH_API_H \ No newline at end of file diff --git a/src/MSL/FILE_POS.c b/src/MSL/FILE_POS.c new file mode 100644 index 00000000..8619b385 --- /dev/null +++ b/src/MSL/FILE_POS.c @@ -0,0 +1,103 @@ +#include "buffer_io.h" +#include "file_struct.h" +#include "errno.h" + +#pragma exceptions on + +long _ftell(FILE* pFile) { + int buf = 0; + long pos; + + unsigned char file_kind = pFile->mode.file; + + if (!(file_kind == file_disk || file_kind == file_console) || + pFile->state.error) { + errno = 40; + return -1; + } + + if (pFile->state.io_state == neutral) { + return pFile->pos; + } + + pos = pFile->buffer_pos + (pFile->buffer_ptr - pFile->buffer); + + if (pFile->state.io_state >= rereading) { + buf = pFile->state.io_state - rereading + 1; + pos -= buf; + } + + if (!pFile->mode.binary) { + long dist = pFile->buffer_ptr - pFile->buffer - buf; + unsigned char* cur_buf = pFile->buffer; + + while (dist--) { + if (*cur_buf++ == '\n') { + pos++; + } + } + } + + return pos; +} + +long ftell(FILE* pFile) { + return _ftell(pFile); +} + +int _fseek(FILE* pFile, long offs, int file_mode) { + __pos_proc position_proc_func; + unsigned char file_kind = pFile->mode.file; + + if (!(file_kind == file_disk) || pFile->state.error) { + errno = 40; + return -1; + } + + if (pFile->state.io_state == writing) { + if (__flush_buffer(pFile, 0) != 0) { + pFile->state.error = 1; + pFile->buffer_len = 0; + errno = 40; + return -1; + } + } + + if (file_mode == 1) { + file_mode = 0; + offs += _ftell(pFile); + } + + if ((file_mode != 2) && (pFile->mode.io != 3) && + ((pFile->state.io_state == reading) || + (pFile->state.io_state == rereading))) { + if ((offs >= pFile->pos || offs < pFile->buffer_pos)) { + pFile->state.io_state = neutral; + } else { + pFile->buffer_ptr = pFile->buffer + (offs - pFile->buffer_pos); + pFile->buffer_len = pFile->pos - offs; + pFile->state.io_state = reading; + } + } else { + pFile->state.io_state = neutral; + } + + if (pFile->state.io_state == neutral) { + position_proc_func = pFile->pos_proc; + + if (position_proc_func != 0 && + (*position_proc_func)(pFile->handle, &offs, file_mode, + pFile->ref)) { + pFile->state.error = 1; + pFile->buffer_len = 0; + errno = 40; + return -1; + } + + pFile->state.eof = 0; + pFile->pos = offs; + pFile->buffer_len = 0; + } + + return 0; +} diff --git a/src/MSL/buffer_io.c b/src/MSL/buffer_io.c new file mode 100644 index 00000000..842d302d --- /dev/null +++ b/src/MSL/buffer_io.c @@ -0,0 +1,37 @@ +#include "buffer_io.h" + +#pragma exceptions on + +void __prep_buffer(FILE* pFile) { + pFile->buffer_ptr = pFile->buffer; + pFile->buffer_len = pFile->buffer_size; + pFile->buffer_len -= pFile->pos & pFile->buffer_alignment; + pFile->buffer_pos = pFile->pos; +} + +int __flush_buffer(FILE* pFile, size_t* pFlushed) { + size_t len; + int res; + + len = pFile->buffer_ptr - pFile->buffer; + + if (len != 0) { + pFile->buffer_len = len; + + res = (*pFile->write_proc)(pFile->handle, pFile->buffer, + (size_t*)&pFile->buffer_len, pFile->ref); + + if (pFlushed != 0) { + *pFlushed = pFile->buffer_len; + } + + if (res != 0) { + return res; + } + + pFile->pos += pFile->buffer_len; + } + + __prep_buffer(pFile); + return 0; +} diff --git a/src/MSL/direct_io.c b/src/MSL/direct_io.c new file mode 100644 index 00000000..fd31399b --- /dev/null +++ b/src/MSL/direct_io.c @@ -0,0 +1,116 @@ +#include "buffer_io.h" +#include "file_struct.h" +#include "wchar_io.h" + +#pragma exceptions on + +size_t __fwrite(const void *pPtr, size_t memb_size, size_t num_memb, FILE *pFile) { + unsigned char* cur_ptr; + size_t num_bytes, rem_bytes, bytes_written; + int res, buff; + + if (fwide(pFile, 0) == 0) { + fwide(pFile, -1); + } + + rem_bytes = memb_size * num_memb; + + if (rem_bytes == 0 || pFile->state.error || pFile->mode.file == 0) { + return 0; + } + + if (pFile->mode.file == 2) { + __stdio_atexit(); + } + + buff = (!pFile->mode.binary || pFile->mode.buffer == 2 || pFile->mode.buffer == 1); + + if (pFile->state.io_state == 0 && pFile->mode.io & 2) { + if (pFile->mode.io & 4) { + if (_fseek(pFile, 0, 2)) { + return 0; + } + } + + pFile->state.io_state = 1; + __prep_buffer(pFile); + } + + if (pFile->state.io_state != 1) { + pFile->state.error = 1; + pFile->buffer_len = 0; + return 0; + } + + cur_ptr = (unsigned char*)pPtr; + bytes_written = 0; + + if (rem_bytes && (pFile->buffer_ptr != pFile->buffer || buff)) { + pFile->buffer_len = pFile->buffer_size - (pFile->buffer_ptr - pFile->buffer); + + do { + unsigned char* nw = 0; + num_bytes = pFile->buffer_len; + + if (num_bytes > rem_bytes) { + num_bytes = rem_bytes; + } + + if (pFile->mode.buffer == 1 && num_bytes) { + if ((nw = (unsigned char*) __memrchr(cur_ptr, '\n', num_bytes)) != 0) { + num_bytes = nw + 1 - cur_ptr; + } + } + + if (num_bytes != 0) { + memcpy(pFile->buffer_ptr, cur_ptr, num_bytes); + cur_ptr += num_bytes; + rem_bytes -= num_bytes; + pFile->buffer_ptr += num_bytes; + pFile->buffer_len -= num_bytes; + } + + if (pFile->buffer_len == 0 || nw != 0 || (!pFile->mode.buffer)) { + res = __flush_buffer(pFile, 0); + + if (res != 0) { + pFile->state.error = 1; + pFile->buffer_len = 0; + rem_bytes = 0; + break; + } + } + + bytes_written += num_bytes; + + } while(rem_bytes && buff); + } + + if (rem_bytes && buff == 0) { + unsigned char* save_buf = pFile->buffer; + size_t save_size = pFile->buffer_size; + + pFile->buffer = cur_ptr; + pFile->buffer_size = rem_bytes; + pFile->buffer_ptr = cur_ptr + rem_bytes; + + if (__flush_buffer(pFile, &num_bytes) != 0) { + pFile->state.error = 1; + pFile->buffer_len = 0; + } + else { + bytes_written += num_bytes; + } + + pFile->buffer = save_buf; + pFile->buffer_size = save_size; + __prep_buffer(pFile); + pFile->buffer_len = 0; + } + + if (pFile->mode.buffer != 2) { + pFile->buffer_len = 0; + } + + return bytes_written / memb_size; +} \ No newline at end of file diff --git a/src/MSL/extras.c b/src/MSL/extras.c new file mode 100644 index 00000000..1d76087c --- /dev/null +++ b/src/MSL/extras.c @@ -0,0 +1,28 @@ +#include "locale.h" + +inline int tolower_inline(int c) { + return ((c < 0) || (c >= 0x100)) + ? c + : (int)(_current_locale.ctype_cmpt_ptr->lower_map_ptr[c]); +} + +int stricmp(const char* s1, const char* s2) { + char c1, c2; + + while (1) { + c1 = tolower_inline(*s1++); + c2 = tolower_inline(*s2++); + + if (c1 < c2) { + return -1; + } + + if (c1 > c2) { + return 1; + } + + if (c1 == 0) { + return 0; + } + } +} diff --git a/src/MSL/file_io.c b/src/MSL/file_io.c new file mode 100644 index 00000000..76e5a5cc --- /dev/null +++ b/src/MSL/file_io.c @@ -0,0 +1,72 @@ +#include "file_io.h" + +#pragma exceptions on + +int fclose(FILE* pFile) { + int flush_res, close_res; + + if (pFile == 0) { + return -1; + } + + if (pFile->mode.file == 0) { + return 0; + } + + flush_res = fflush(pFile); + close_res = (*pFile->close_proc)(pFile->handle); + pFile->mode.file = 0; + pFile->handle = 0; + + if (pFile->state.free_buffer) { + free(pFile->buffer); + } + + return ((flush_res || close_res) ? -1 : 0); +} + +int fflush(FILE* pFile) { + long pos; + + if (pFile == 0) { + return __flush_all(); + } + + if (pFile->state.error || pFile->mode.file == 0) { + return -1; + } + + if (pFile->mode.io == 1) { + return 0; + } + + if (pFile->state.io_state >= 3) { + pFile->state.io_state = 2; + } + + if (pFile->state.io_state == 2) { + pFile->buffer_len = 0; + } + + if (pFile->state.io_state != 1) { + pFile->state.io_state = 0; + return 0; + } + + if (pFile->mode.file != 1) { + pos = 0; + } else { + pos = ftell(pFile); + } + + if (__flush_buffer(pFile, 0)) { + pFile->state.error = 1; + pFile->buffer_len = 0; + return -1; + } + + pFile->state.io_state = 0; + pFile->pos = pos; + pFile->buffer_len = 0; + return 0; +} diff --git a/src/MSL/math_api.c b/src/MSL/math_api.c new file mode 100644 index 00000000..78319ecc --- /dev/null +++ b/src/MSL/math_api.c @@ -0,0 +1,32 @@ +#include "math_api.h" + +#pragma exceptions on + +int __signbitd(double dbl) { + return (*(int*)&dbl) & 0x80000000; +} + +int __fpclassifyd(double dbl) { + switch ((*(int*)&dbl) & 0x7FF00000) { + case 0x7FF00000: + if (((*(int*)&dbl) & 0xFFFFF) || (*(1 + (int*)&dbl)) & 0xFFFFFFFF) { + return 1; + } + else { + return 2; + } + + break; + case 0: + if (((*(int*)&dbl) & 0xFFFFF) || (*(1 + (int*)&dbl)) & 0xFFFFFFFF) { + return 5; + } + else { + return 3; + } + + break; + } + + return 4; +} diff --git a/src/MSL/math_sun.c b/src/MSL/math_sun.c index b7640f0b..e5be11e3 100644 --- a/src/MSL/math_sun.c +++ b/src/MSL/math_sun.c @@ -1,6 +1,7 @@ -#include #include "math.h" +#pragma exceptions on + double scalbn(double x, int n) { double value; int exp; diff --git a/src/MSL/mbstring.c b/src/MSL/mbstring.c index 2797f511..9dad8b04 100644 --- a/src/MSL/mbstring.c +++ b/src/MSL/mbstring.c @@ -3,6 +3,8 @@ #include "locale.h" #include "string.h" +#pragma exceptions on + int mbtowc(wchar_t* dest, const char* s, size_t num) { // return _current_locale.ctype_cmpt_ptr->decode_mb(dest, s, num); return 0; // TODO: _current_locale (locale.c) diff --git a/src/MSL/mem.c b/src/MSL/mem.c index 764161e1..f4d5ab2d 100644 --- a/src/MSL/mem.c +++ b/src/MSL/mem.c @@ -1,6 +1,8 @@ #include "mem_funcs.h" #include "string.h" +#pragma exceptions on + void* memmove(void* dst, const void* src, size_t len) { const char* csrc; char* cdst; From 5a51bc1ef11c02c44da62ac72e37867e675d42c9 Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Tue, 23 Sep 2025 03:15:35 -0400 Subject: [PATCH 10/25] uart and io stuff --- configure.py | 8 +++---- include/MSL/UART.h | 37 +++++++++++++++++++++++++++++++ include/MSL/wchar_io.h | 8 +++++++ src/MSL/math_float.c | 8 +++++++ src/MSL/mbstring.c | 6 ++--- src/MSL/uart_console_io_gcn.c | 41 +++++++++++++++++++++++++++++++++++ src/MSL/wchar_io.c | 35 ++++++++++++++++++++++++++++++ 7 files changed, 135 insertions(+), 8 deletions(-) create mode 100644 include/MSL/UART.h create mode 100644 include/MSL/wchar_io.h create mode 100644 src/MSL/math_float.c create mode 100644 src/MSL/uart_console_io_gcn.c create mode 100644 src/MSL/wchar_io.c diff --git a/configure.py b/configure.py index 28cfe19b..a872e890 100755 --- a/configure.py +++ b/configure.py @@ -736,7 +736,7 @@ def MatchingFor(*versions): Object(Matching, "MSL/direct_io.c"), Object(Matching, "MSL/file_io.c"), Object(Matching, "MSL/FILE_POS.c"), - Object(NonMatching, "MSL/mbstring.c"), + Object(Matching, "MSL/mbstring.c"), Object(Matching, "MSL/mem.c"), Object(Matching, "MSL/mem_funcs.c"), Object(Matching, "MSL/math_api.c"), @@ -752,11 +752,11 @@ def MatchingFor(*versions): Object(Matching, "MSL/wmem.c"), Object(NonMatching, "MSL/wprintf.c"), Object(Matching, "MSL/wstring.c"), - Object(NonMatching, "MSL/wchar_io.c"), - Object(NonMatching, "MSL/uart_console_io_gcn.c"), + Object(Matching, "MSL/wchar_io.c"), + Object(Matching, "MSL/uart_console_io_gcn.c"), Object(Matching, "MSL/abort_exit_ppc_eabi.c"), Object(Matching, "MSL/math_sun.c"), - Object(NonMatching, "MSL/math_float.c"), + Object(Matching, "MSL/math_float.c"), Object(Matching, "MSL/extras.c"), Object(Matching, "MSL/e_acos.c"), Object(Matching, "MSL/e_asin.c"), diff --git a/include/MSL/UART.h b/include/MSL/UART.h new file mode 100644 index 00000000..9d6abdf0 --- /dev/null +++ b/include/MSL/UART.h @@ -0,0 +1,37 @@ +#ifndef UART_H +#define UART_H + +typedef int UARTError; + +enum { + kUARTNoError = 0, + kUARTUnknownBaudRate, + kUARTConfigurationError, + kUARTBufferOverflow, + kUARTNoData +}; + +typedef enum { + kBaudHWSet = -1, + kBaud300 = 300, + kBaud600 = 600, + kBaud1200 = 1200, + kBaud1800 = 1800, + kBaud2000 = 2000, + kBaud2400 = 2400, + kBaud3600 = 3600, + kBaud4800 = 4800, + kBaud7200 = 7200, + kBaud9600 = 9600, + kBaud19200 = 19200, + kBaud38400 = 38400, + kBaud57600 = 57600, + kBaud115200 = 115200, + kBaud230400 = 230400 +} UARTBaudRate; + +UARTError InitializeUART(UARTBaudRate); + +UARTError WriteUARTN(const void *, unsigned long); + +#endif // UART_H \ No newline at end of file diff --git a/include/MSL/wchar_io.h b/include/MSL/wchar_io.h new file mode 100644 index 00000000..4cc827b7 --- /dev/null +++ b/include/MSL/wchar_io.h @@ -0,0 +1,8 @@ +#ifndef WCHAR_IO_H +#define WCHAR_IO_H + +#include "file_struct.h" + +int fwide(FILE *, int); + +#endif // WCHAR_IO_H \ No newline at end of file diff --git a/src/MSL/math_float.c b/src/MSL/math_float.c new file mode 100644 index 00000000..b71c85ac --- /dev/null +++ b/src/MSL/math_float.c @@ -0,0 +1,8 @@ +asm float fabsf(float x) { + nofralloc + + frsp f0, f1 + fabs f0, f0 + frsp f1, f0 + blr +} diff --git a/src/MSL/mbstring.c b/src/MSL/mbstring.c index 9dad8b04..68599878 100644 --- a/src/MSL/mbstring.c +++ b/src/MSL/mbstring.c @@ -6,8 +6,7 @@ #pragma exceptions on int mbtowc(wchar_t* dest, const char* s, size_t num) { - // return _current_locale.ctype_cmpt_ptr->decode_mb(dest, s, num); - return 0; // TODO: _current_locale (locale.c) + return _current_locale.ctype_cmpt_ptr->decode_mb(dest, s, num); } int __mbtowc_noconv(wchar_t* dest, const char* src, size_t n) { @@ -40,8 +39,7 @@ int __wctomb_noconv(char* src, wchar_t cr) { } static inline int wctomb(char* src, wchar_t wchar) { - // return _current_locale.ctype_cmpt_ptr->encode_wc(src, wchar); - return 0; // TODO: _current_locale (locale.c) + return _current_locale.ctype_cmpt_ptr->encode_wc(src, wchar); } size_t mbstowcs(wchar_t* pDest, const char* pSrc, size_t num) { diff --git a/src/MSL/uart_console_io_gcn.c b/src/MSL/uart_console_io_gcn.c new file mode 100644 index 00000000..13950070 --- /dev/null +++ b/src/MSL/uart_console_io_gcn.c @@ -0,0 +1,41 @@ +#include "UART.h" +#include "types.h" + +int __TRK_write_console(unsigned long, unsigned char *, size_t *, void *); + +UARTError __init_uart_console(void) { + UARTError err = kUARTNoError; + static int initialized = 0; + + if (initialized == 0) { + err = InitializeUART(kBaud57600); + + if (err == kUARTNoError) { + initialized = 1; + } + } + + return err; +} + +#pragma exceptions on + +int __write_console(unsigned long handle, unsigned char *buffer, size_t *count, void *ref) { + if (!(OSGetConsoleType() & 0x20000000)) { + if (__init_uart_console() != kUARTNoError) { + return 1; + } + + if (WriteUARTN(buffer, *count) != kUARTNoError) { + *count = 0; + return 1; + } + } + + __TRK_write_console(handle, buffer, count, ref); + return 0; +} + +int __close_console(unsigned long handle) { + return 0; +} diff --git a/src/MSL/wchar_io.c b/src/MSL/wchar_io.c new file mode 100644 index 00000000..64fd7c2e --- /dev/null +++ b/src/MSL/wchar_io.c @@ -0,0 +1,35 @@ +#include + +int fwide(FILE *pFile, int file_mode) { + int orientation; + int res; + + if ((pFile == NULL) || (pFile->mode.file == file_closed)) { + return 0; + } + + orientation = pFile->mode.file_orientation; + + switch (orientation) { + case file_unoriented: + if (file_mode > 0) { + pFile->mode.file_orientation = file_wide_oriented; + } + else if (file_mode < 0) { + pFile->mode.file_orientation = file_char_oriented; + } + + res = file_mode; + break; + + case file_wide_oriented: + res = 1; + break; + + case file_char_oriented: + res = -1; + break; + } + + return res; +} \ No newline at end of file From c885ceae5d0be308d61ab538c8a3553c0bbd5bec Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Tue, 23 Sep 2025 14:41:50 -0400 Subject: [PATCH 11/25] files --- include/MSL/ansi_files.h | 7 +++++ include/MSL/internal/file_struct.h | 17 +++++++---- include/MSL/locale.h | 1 - include/MSL/stdio_api.h | 26 +++++++++++++++++ src/MSL/ansi_files.c | 46 ++++++++++++++++++++++++++++++ src/MSL/file_io.c | 22 +++++++------- 6 files changed, 102 insertions(+), 17 deletions(-) create mode 100644 include/MSL/ansi_files.h create mode 100644 include/MSL/stdio_api.h create mode 100644 src/MSL/ansi_files.c diff --git a/include/MSL/ansi_files.h b/include/MSL/ansi_files.h new file mode 100644 index 00000000..a7e0dbcf --- /dev/null +++ b/include/MSL/ansi_files.h @@ -0,0 +1,7 @@ +typedef unsigned char console_buff[80]; + +static console_buff stdin_buff; +static console_buff stdout_buff; +static console_buff stderr_buff; + +void __close_all(void); \ No newline at end of file diff --git a/include/MSL/internal/file_struct.h b/include/MSL/internal/file_struct.h index 3a551bf3..b0519872 100644 --- a/include/MSL/internal/file_struct.h +++ b/include/MSL/internal/file_struct.h @@ -32,6 +32,13 @@ typedef struct { unsigned int binary : 1; } file_modes; +enum io_modes { + read = 1, + write = 2, + read_write = 3, + append = 4 +}; + enum io_states { neutral, writing, @@ -41,10 +48,10 @@ enum io_states { typedef struct { - unsigned int io_state : 3; - unsigned int free_buffer : 1; - unsigned char eof; - unsigned char error; + unsigned int io_state : 3; + unsigned int free_buffer : 1; + unsigned char eof; + unsigned char error; } file_state; typedef unsigned long file_handle; @@ -80,6 +87,6 @@ struct _FILE { extern FILE __files[]; -#define stdout (&__std(__files[1])) +#define stdout (&__std(__files[1])) #endif // FILE_STRUCT_H \ No newline at end of file diff --git a/include/MSL/locale.h b/include/MSL/locale.h index d4e4ab82..97a18d28 100644 --- a/include/MSL/locale.h +++ b/include/MSL/locale.h @@ -2,7 +2,6 @@ #define LOCALE_H #include "ansi_params.h" -//#include "size_t.h" #include "wchar_io.h" typedef int (* __decode_mbyte) (wchar_t *, const char *, __std(size_t)); diff --git a/include/MSL/stdio_api.h b/include/MSL/stdio_api.h new file mode 100644 index 00000000..ced5511d --- /dev/null +++ b/include/MSL/stdio_api.h @@ -0,0 +1,26 @@ +#ifndef STDIO_API_H +#define STDIO_API_H + +#include "types.h" + +enum __ReadProcActions { __GetAChar, __UngetAChar, __TestForError }; + +typedef struct { + char* NextChar; + int NullCharDetected; +} __InStrCtrl; + +typedef struct { + wchar_t* wCharStr; + size_t MaxCharCount; + size_t CharsWritten; +} __wOutStrCtrl; + +typedef struct { + wchar_t* wNextChar; + int wNullCharDetected; +} __wInStrCtrl; + +int __StringRead(void*, int, int); + +#endif // STDIO_API_H diff --git a/src/MSL/ansi_files.c b/src/MSL/ansi_files.c new file mode 100644 index 00000000..4542402a --- /dev/null +++ b/src/MSL/ansi_files.c @@ -0,0 +1,46 @@ +#include "file_struct.h" +#include "ansi_files.h" + +#pragma exceptions on + +void __close_all(void) { + FILE* file = &__files[0]; + FILE* lastFile; + + while (file != 0) { + if (file->mode.file != file_closed) { + fclose(file); + } + + lastFile = file; + file = file->next_file; + + if (lastFile->is_dyn_alloc) { + free(lastFile); + } + else { + lastFile->mode.file = file_unavailable; + + if ((file != 0) && (file->is_dyn_alloc)) { + lastFile->next_file = 0; + } + } + } +} + +int __flush_all(void) { + int res = 0; + FILE* file = &__files[0]; + + while (file != 0) { + if (file->mode.file != file_closed) { + if (fflush(file)) { + res = -1; + } + } + + file = file->next_file; + } + + return res; +} diff --git a/src/MSL/file_io.c b/src/MSL/file_io.c index 76e5a5cc..078aa397 100644 --- a/src/MSL/file_io.c +++ b/src/MSL/file_io.c @@ -9,13 +9,13 @@ int fclose(FILE* pFile) { return -1; } - if (pFile->mode.file == 0) { + if (pFile->mode.file == file_closed) { return 0; } flush_res = fflush(pFile); close_res = (*pFile->close_proc)(pFile->handle); - pFile->mode.file = 0; + pFile->mode.file = file_closed; pFile->handle = 0; if (pFile->state.free_buffer) { @@ -32,28 +32,28 @@ int fflush(FILE* pFile) { return __flush_all(); } - if (pFile->state.error || pFile->mode.file == 0) { + if (pFile->state.error || pFile->mode.file == file_closed) { return -1; } - if (pFile->mode.io == 1) { + if (pFile->mode.io == read) { return 0; } - if (pFile->state.io_state >= 3) { - pFile->state.io_state = 2; + if (pFile->state.io_state >= rereading) { + pFile->state.io_state = reading; } - if (pFile->state.io_state == 2) { + if (pFile->state.io_state == reading) { pFile->buffer_len = 0; } - if (pFile->state.io_state != 1) { - pFile->state.io_state = 0; + if (pFile->state.io_state != writing) { + pFile->state.io_state = neutral; return 0; } - if (pFile->mode.file != 1) { + if (pFile->mode.file != file_disk) { pos = 0; } else { pos = ftell(pFile); @@ -65,7 +65,7 @@ int fflush(FILE* pFile) { return -1; } - pFile->state.io_state = 0; + pFile->state.io_state = neutral; pFile->pos = pos; pFile->buffer_len = 0; return 0; From 04785d433db9a3ae6baf7dbff0d0f6ba8b4208de Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Tue, 23 Sep 2025 16:53:02 -0400 Subject: [PATCH 12/25] refactor ctype --- include/MSL/ansi_fp.h | 15 +++++++++ include/MSL/ctype.h | 28 ++++++++++++----- src/MSL/ansi_fp.c | 57 +++++++++++++++++++++++++++++++++ src/MSL/ctype.c | 73 ------------------------------------------- src/MSL/locale.c | 9 ++++-- 5 files changed, 100 insertions(+), 82 deletions(-) create mode 100644 include/MSL/ansi_fp.h create mode 100644 src/MSL/ansi_fp.c delete mode 100644 src/MSL/ctype.c diff --git a/include/MSL/ansi_fp.h b/include/MSL/ansi_fp.h new file mode 100644 index 00000000..75eb0ae6 --- /dev/null +++ b/include/MSL/ansi_fp.h @@ -0,0 +1,15 @@ +#ifndef ANSI_FP_H +#define ANSI_FP_H +#include +#ifdef __cplusplus +extern "C" { +#endif + +extern const unsigned short __ctype_mapC[0x100]; +extern const unsigned char __lower_mapC[0x100]; +extern const unsigned char __upper_mapC[0x100]; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/MSL/ctype.h b/include/MSL/ctype.h index c44a3a8f..aed25213 100644 --- a/include/MSL/ctype.h +++ b/include/MSL/ctype.h @@ -1,10 +1,24 @@ -#ifndef CTYPE_H -#define CTYPE_H +#ifndef MSL_CTYPE_H +#define MSL_CTYPE_H +#include +#include +#ifdef __cplusplus +extern "C" { +#endif -extern const unsigned char __lower_mapC[0x100]; -extern const unsigned char __upper_mapC[0x100]; -extern const unsigned short __ctype_mapC[0x100]; +inline int tolower(int x) { + return (x < 0 || x >= 256) + ? x + : (int)(&_current_locale)->ctype_cmpt_ptr->lower_map_ptr[x]; +} -int tolower(int); +inline int toupper(int x) { + return (x < 0 || x >= 256) + ? x + : (int)(&_current_locale)->ctype_cmpt_ptr->upper_map_ptr[x]; +} -#endif // CTYPE_H +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/MSL/ansi_fp.c b/src/MSL/ansi_fp.c new file mode 100644 index 00000000..e583aa10 --- /dev/null +++ b/src/MSL/ansi_fp.c @@ -0,0 +1,57 @@ +#include "ansi_fp.h" + +const unsigned short __ctype_mapC[0x100] = { + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 0x106, 0x104, 0x104, 0x104, 0x104, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 0x142, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + 0x458, 0x458, 0x458, 0x458, 0x458, 0x458, 0x458, 0x458, + 0x458, 0x458, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + 0xD0, 0x651, 0x651, 0x651, 0x651, 0x651, 0x651, 0x251, + 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, + 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, + 0x251, 0x251, 0x251, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + 0xD0, 0x471, 0x471, 0x471, 0x471, 0x471, 0x471, 0x71, + 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, + 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, + 0x71, 0x71, 0x71, 0xd0, 0xd0, 0xd0, 0xd0, 4 + +}; + +const unsigned char __lower_mapC[0x100] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0x7F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF}; + +const unsigned char __upper_mapC[0x100] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', 0x7F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF}; diff --git a/src/MSL/ctype.c b/src/MSL/ctype.c deleted file mode 100644 index 8a295931..00000000 --- a/src/MSL/ctype.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "ctype.h" - -#include "locale.h" - -const unsigned short __ctype_mapC[0x100] = { - 4, 4, 4, 4, 4, 4, 4, 4, 4, 0x106, 0x104, - 0x104, 0x104, 0x104, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0x142, - 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, - 0xD0, 0xD0, 0xD0, 0xD0, 0x458, 0x458, 0x458, 0x458, 0x458, 0x458, 0x458, - 0x458, 0x458, 0x458, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x651, - 0x651, 0x651, 0x651, 0x651, 0x651, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, - 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, 0x251, - 0x251, 0x251, 0x251, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x471, 0x471, - 0x471, 0x471, 0x471, 0x471, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, - 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, - 4 - -}; - -const unsigned char __lower_mapC[0x100] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, ' ', '!', '"', '#', - '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', - '<', '=', '>', '?', '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', - 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^', '_', - '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', - 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', - 'x', 'y', 'z', '{', '|', '}', '~', 0x7F, 0x80, 0x81, 0x82, 0x83, - 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, - 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, - 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, - 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, - 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, - 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, - 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, - 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, - 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, - 0xFC, 0xFD, 0xFE, 0xFF}; - -const unsigned char __upper_mapC[0x100] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, ' ', '!', '"', '#', - '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', - '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', - 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', - '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', - 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', '{', '|', '}', '~', 0x7F, 0x80, 0x81, 0x82, 0x83, - 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, - 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, - 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, - 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, - 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, - 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, - 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, - 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, - 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, - 0xFC, 0xFD, 0xFE, 0xFF}; - -int tolower(int c) { - return ((c < 0) || (c >= 0x100)) - ? c - : (int)(_current_locale.ctype_cmpt_ptr->lower_map_ptr[c]); -} diff --git a/src/MSL/locale.c b/src/MSL/locale.c index 411257f7..72b2a2c3 100644 --- a/src/MSL/locale.c +++ b/src/MSL/locale.c @@ -2,6 +2,7 @@ #include "mbstring.h" #include "ctype.h" #include "wctype.h" +#include "ansi_fp.h" #pragma options align=native #pragma warn_padding off @@ -34,6 +35,12 @@ struct lconv __lconv = { #pragma warn_padding reset #pragma options align=reset +typedef struct __CMap { + char UNK_0x0[0x10]; + const u8* to_lower_table; // at 0x10 + const u8* to_upper_table; // at 0x14 +} __CMap; + struct _loc_ctype_cmpt _loc_ctyp_C = { "C", &__ctype_mapC[0], @@ -46,7 +53,6 @@ struct _loc_ctype_cmpt _loc_ctyp_C = { __wctomb_noconv }; - unsigned short char_coll_tableC[0x60] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, @@ -109,7 +115,6 @@ struct _loc_time_cmpt _loc_tim_C = { "" }; - struct __locale _current_locale = { 0, "C", From 131fe13af461755526d5ab58afcf36c673798acf Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Tue, 23 Sep 2025 21:28:59 -0400 Subject: [PATCH 13/25] ansi_fp --- include/MSL/ansi_fp.h | 19 ++ src/MSL/ansi_fp.c | 714 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 733 insertions(+) diff --git a/include/MSL/ansi_fp.h b/include/MSL/ansi_fp.h index 75eb0ae6..9281836a 100644 --- a/include/MSL/ansi_fp.h +++ b/include/MSL/ansi_fp.h @@ -1,6 +1,25 @@ #ifndef ANSI_FP_H #define ANSI_FP_H #include + +typedef struct decimal { + char sign; + char _1; + short exponent; + + struct { + unsigned char length; + unsigned char text[36]; + unsigned char pad; + } sig; +} decimal; + +typedef struct decform { + char style; + char _1; + short digits; +} decform; + #ifdef __cplusplus extern "C" { #endif diff --git a/src/MSL/ansi_fp.c b/src/MSL/ansi_fp.c index e583aa10..0394f8bb 100644 --- a/src/MSL/ansi_fp.c +++ b/src/MSL/ansi_fp.c @@ -1,4 +1,24 @@ #include "ansi_fp.h" +#include "math_api.h" +#include "float.h" + +#pragma exceptions on + +//const unsigned char lbl_8037B2F8[0xE0] = { +// 0x35, 0x34, 0x32, 0x31, 0x30, 0x31, 0x30, 0x38, 0x36, 0x32, 0x34, 0x32, 0x37, 0x35, 0x32, 0x32, +// 0x31, 0x37, 0x30, 0x30, 0x33, 0x37, 0x32, 0x36, 0x34, 0x30, 0x30, 0x34, 0x33, 0x34, 0x39, 0x37, +// 0x30, 0x38, 0x35, 0x35, 0x37, 0x31, 0x32, 0x38, 0x39, 0x30, 0x36, 0x32, 0x35, 0x00, 0x31, 0x31, +// 0x31, 0x30, 0x32, 0x32, 0x33, 0x30, 0x32, 0x34, 0x36, 0x32, 0x35, 0x31, 0x35, 0x36, 0x35, 0x34, +// 0x30, 0x34, 0x32, 0x33, 0x36, 0x33, 0x31, 0x36, 0x36, 0x38, 0x30, 0x39, 0x30, 0x38, 0x32, 0x30, +// 0x33, 0x31, 0x32, 0x35, 0x00, 0x32, 0x33, 0x32, 0x38, 0x33, 0x30, 0x36, 0x34, 0x33, 0x36, 0x35, +// 0x33, 0x38, 0x36, 0x39, 0x36, 0x32, 0x38, 0x39, 0x30, 0x36, 0x32, 0x35, 0x00, 0x31, 0x35, 0x32, +// 0x35, 0x38, 0x37, 0x38, 0x39, 0x30, 0x36, 0x32, 0x35, 0x00, 0x33, 0x39, 0x30, 0x36, 0x32, 0x35, +// 0x00, 0x37, 0x38, 0x31, 0x32, 0x35, 0x00, 0x31, 0x35, 0x36, 0x32, 0x35, 0x00, 0x33, 0x31, 0x32, +// 0x35, 0x00, 0x36, 0x32, 0x35, 0x00, 0x31, 0x32, 0x35, 0x00, 0x32, 0x35, 0x00, 0x35, 0x00, 0x31, +// 0x00, 0x32, 0x00, 0x34, 0x00, 0x38, 0x00, 0x31, 0x36, 0x00, 0x33, 0x32, 0x00, 0x36, 0x34, 0x00, +// 0x31, 0x32, 0x38, 0x00, 0x32, 0x35, 0x36, 0x00, 0x31, 0x37, 0x39, 0x37, 0x36, 0x39, 0x33, 0x31, +// 0x33, 0x34, 0x38, 0x36, 0x32, 0x33, 0x31, 0x35, 0x38, 0x30, 0x37, 0x39, 0x33, 0x37, 0x32, 0x38, +// 0x37, 0x31, 0x34, 0x30, 0x35, 0x33, 0x30, 0x33, 0x34, 0x31, 0x35, 0x31, 0x00, 0x00, 0x00, 0x00}; const unsigned short __ctype_mapC[0x100] = { 4, 4, 4, 4, 4, 4, 4, 4, @@ -55,3 +75,697 @@ const unsigned char __upper_mapC[0x100] = { 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF}; + +#define INFINITY (*(float*)__float_huge) +#define SIGDIGLEN 36 +extern double pow(double, double); + + +inline int count_trailing(double x) { + return __builtin___count_trailing_zero64(*(unsigned long long*)&x | + 0x0010000000000000); +} + +static inline void __dorounddecup(decimal* d, int digits) { + u8* b = d->sig.text; + u8* i = b + digits - 1; + + while (1) { + if (*i < 9) { + *i += 1; + break; + } + if (i == b) { + *i = 1; + d->exponent++; + break; + } + *i-- = 0; + } +} + +static inline int __must_round(const decimal* d, int digits) { + // regswap fun here + u8 const* i = d->sig.text + digits; + + if (*i > 5) { + return 1; + } + + if (*i < 5) { + return -1; + } + + for (i++; i < d->sig.text + d->sig.length; i++) { + if (*i != 0) { + return 1; + } + } + + if (d->sig.text[digits - 1] & 1) { + return 1; + } + + return -1; +} + +static inline void __rounddec(decimal* d, int digits) { + if (digits > 0 && digits < d->sig.length) { + int unkBool = __must_round(d, digits); + d->sig.length = digits; + + if (unkBool >= 0) { + __dorounddecup(d, digits); + } + } +} + +void __ull2dec(decimal* pDecimal, unsigned long long input) { + pDecimal->sign = 0; + pDecimal->sig.length = 0; + + for (; input != 0; input /= 10) { + pDecimal->sig.text[pDecimal->sig.length++] = + (unsigned char)(input % 10); + } + + /* regswap if these were declared at the top...only logic I can think of is making them valid in this block */ + { + unsigned char* start = pDecimal->sig.text; + unsigned char* end = pDecimal->sig.text + pDecimal->sig.length; + + for (; start < --end; ++start) { + unsigned char t = *start; + *start = *end; + *end = t; + } + } + + pDecimal->exponent = (short)(pDecimal->sig.length - 1); +} + +void __timesdec(decimal* pResult, const decimal* x, const decimal* y) { + unsigned long accumulator = 0; + unsigned char mant[72]; + int i = x->sig.length + y->sig.length - 1; + unsigned char* ip = mant + i + 1; + unsigned char* ep = ip; + pResult->sign = 0; + + for (; i > 0; --i) { + int k = y->sig.length - 1; + int j = i - k - 1; + int l; + int t; + unsigned char const *jp, *kp; + + if (j < 0) { + j = 0; + k = i - 1; + } + + jp = x->sig.text + j; + kp = y->sig.text + k; + l = k + 1; + t = x->sig.length - j; + + if (l > t) { + l = t; + } + + for (; l > 0; --l, ++jp, --kp) { + accumulator += (unsigned long)(*jp) * *kp; + } + + *--ip = (unsigned char)(accumulator % 10); + accumulator /= 10; + } + + pResult->exponent = (short)(x->exponent + y->exponent); + + if (accumulator > 0) { + *--ip = (unsigned char)accumulator; + pResult->exponent++; + } + + for (i = 0; i < 36 && ip < ep; ++i, ++ip) { + pResult->sig.text[i] = *ip; + } + + pResult->sig.length = i; + + if (ip < ep && *ip >= 5) { + if (*ip == 5) { + unsigned char* jp = ip + 1; + for (; jp < ep; ++jp) { + if (*jp != 0) { + goto round; + } + } + + if ((*(ip - 1) & 1) == 0) { + return; + } + } + round: + __dorounddecup(pResult, pResult->sig.length); + } +} + +void __str2dec(decimal* pDecimal, const char* pStr, short exp) { + int i; + pDecimal->exponent = exp; + pDecimal->sign = 0; + + for (i = 0; i < 36 && *pStr != 0;) { + pDecimal->sig.text[i++] = (unsigned char)(*pStr++ - '0'); + } + + pDecimal->sig.length = i; + + if (*pStr != 0) { + if (*pStr < 5) { + return; + } + + if (*pStr > 5) { + goto round; + } + + { + const char* p = pStr + 1; + for (; *p != 0; ++p) { + if (*p != '0') { + goto round; + } + } + + if ((pDecimal->sig.text[i - 1] & 1) == 0) { + return; + } + } + + round: + __dorounddecup(pDecimal, pDecimal->sig.length); + } +} + + + +static void __two_exp(decimal* pDecimal, long exp) { + switch (exp) { + case -64: + __str2dec(pDecimal, "542101086242752217003726400434970855712890625", -20); + return; + case -53: + __str2dec(pDecimal, "11102230246251565404236316680908203125", -16); + return; + case -32: + __str2dec(pDecimal, "23283064365386962890625", -10); + return; + case -16: + __str2dec(pDecimal, "152587890625", -5); + return; + case -8: + __str2dec(pDecimal, "390625", -3); + return; + case -7: + __str2dec(pDecimal, "78125", -3); + return; + case -6: + __str2dec(pDecimal, "15625", -2); + return; + case -5: + __str2dec(pDecimal, "3125", -2); + return; + case -4: + __str2dec(pDecimal, "625", -2); + return; + case -3: + __str2dec(pDecimal, "125", -1); + return; + case -2: + __str2dec(pDecimal, "25", -1); + return; + case -1: + __str2dec(pDecimal, "5", -1); + return; + case 0: + __str2dec(pDecimal, "1", 0); + return; + case 1: + __str2dec(pDecimal, "2", 0); + return; + case 2: + __str2dec(pDecimal, "4", 0); + return; + case 3: + __str2dec(pDecimal, "8", 0); + return; + case 4: + __str2dec(pDecimal, "16", 1); + return; + case 5: + __str2dec(pDecimal, "32", 1); + return; + case 6: + __str2dec(pDecimal, "64", 1); + return; + case 7: + __str2dec(pDecimal, "128", 2); + return; + case 8: + __str2dec(pDecimal, "256", 2); + return; + } + + { + decimal x2, temp; + __two_exp(&x2, ((long)((0x80000000UL & exp) >> 31) + exp) >> 1); + __timesdec(pDecimal, &x2, &x2); + if (exp & 1) { + temp = *pDecimal; + if (exp > 0) + __str2dec(&x2, "2", 0); + else + __str2dec(&x2, "5", -1); + __timesdec(pDecimal, &temp, &x2); + } + } +} + +int __equals_dec(const decimal* x, const decimal* y) { + if (x->sig.text[0] == 0) { + if (y->sig.text[0] == 0) { + return 1; + } + + return 0; + } + + if (y->sig.text[0] == 0) { + if (x->sig.text[0] == 0) { + return 1; + } + + return 0; + } + + if (x->exponent == y->exponent) { + int i; + int l = x->sig.length; + + if (l > y->sig.length) { + l = y->sig.length; + } + + for (i = 0; i < l; ++i) { + if (x->sig.text[i] != y->sig.text[i]) { + return 0; + } + } + + if (l == x->sig.length) { + x = y; + } + + for (; i < x->sig.length; ++i) { + if (x->sig.text[i] != 0) { + return 0; + } + } + + return 1; + } + + return 0; +} + +static int __less_dec(const decimal* x, const decimal* y) { + if (x->sig.text[0] == 0) { + if (y->sig.text[0] != 0) { + return 1; + } + + return 0; + } + + if (y->sig.text[0] == 0) { + return 0; + } + + if (x->exponent == y->exponent) { + int i; + int l = x->sig.length; + + if (l > y->sig.length) { + l = y->sig.length; + } + + for (i = 0; i < l; ++i) { + if (x->sig.text[i] < y->sig.text[i]) { + return 1; + } + + if (y->sig.text[i] < x->sig.text[i]) { + return 0; + } + } + + if (l == x->sig.length) { + for (; i < y->sig.length; ++i) { + if (y->sig.text[i] != 0) { + return 1; + } + } + } + + return 0; + } + + return x->exponent < y->exponent; +} + +void __minus_dec(decimal* z, const decimal* x, const decimal* y) { + int zlen, dexp; + unsigned char *ib, *i, *ie; + unsigned char const *jb, *j, *jn; + *z = *x; + + if (y->sig.text[0] == 0) { + return; + } + + zlen = z->sig.length; + + if (zlen < y->sig.length) { + zlen = y->sig.length; + } + + dexp = z->exponent - y->exponent; + zlen += dexp; + + if (zlen > 36) { + zlen = 36; + } + + while (z->sig.length < zlen) { + z->sig.text[z->sig.length++] = 0; + } + + ib = z->sig.text; + i = ib + zlen; + + if (y->sig.length + dexp < zlen) { + i = ib + (y->sig.length + dexp); + } + + jb = y->sig.text; + j = jb + (i - ib - dexp); + jn = j; + + while (i > ib && j > jb) { + --i; + --j; + if (*i < *j) { + unsigned char* k = i - 1; + while (*k == 0) { + --k; + } + while (k != i) { + --*k; + *++k += 10; + } + } + + *i -= *j; + } + + if (jn - jb < y->sig.length) { + BOOL round_down = FALSE; + if (*jn < 5) { + round_down = TRUE; + } else if (*jn == 5) { + unsigned char const* je = y->sig.text + y->sig.length; + + for (j = jn + 1; j < je; ++j) { + if (*j != 0) { + goto done; + } + } + + i = ib + (jn - jb) + dexp - 1; + + if (*i & 1) { + round_down = 1; + } + } + if (round_down) { + if (*i < 1) { + unsigned char* k = i - 1; + + while (*k == 0) { + --k; + } + while (k != i) { + --*k; + *++k += 10; + } + } + + *i -= 1; + } + } + +done: + for (i = ib; *i == 0; ++i) + ; + + if (i > ib) { + unsigned char dl = (unsigned char)(i - ib); + z->exponent -= dl; + ie = ib + z->sig.length; + for (; i < ie; ++i, ++ib) + *ib = *i; + z->sig.length -= dl; + } + + ib = z->sig.text; + + for (i = ib + z->sig.length; i > ib;) { + --i; + if (*i != 0) { + break; + } + } + + z->sig.length = (unsigned char)(i - ib + 1); +} + +void __num2dec_internal(decimal* pDecimal, double x) { + char sign = (char)(__signbitd(x) != 0); + if (x == 0.0) { + pDecimal->sign = sign; + pDecimal->exponent = 0; + pDecimal->sig.length = 1; + pDecimal->sig.text[0] = 0; + return; + } + + if (!(__fpclassifyd(x) > 2)) { + pDecimal->sign = sign; + pDecimal->exponent = 0; + pDecimal->sig.length = 1; + pDecimal->sig.text[0] = + (unsigned char)(__fpclassifyd(x) == 1 ? 'N' : 'I'); + return; + } + + if (sign) { + x = -x; + } + + { + int exp; + double frac = frexp(x, &exp); + long num_bits_extract = 53 - count_trailing(frac); + decimal int_d, pow2_d; + __two_exp(&pow2_d, exp - num_bits_extract); + __ull2dec(&int_d, + (unsigned long long)ldexp(frac, (int)num_bits_extract)); + __timesdec(pDecimal, &int_d, &pow2_d); + pDecimal->sign = sign; + } +} + +void __num2dec(const decform* form, double val, decimal* d) { + short digits = form->digits; + int i; + __num2dec_internal(d, val); + + if (d->sig.text[0] > 9) { + return; + } + + if (digits > SIGDIGLEN) { + digits = SIGDIGLEN; + } + + __rounddec(d, digits); + + while (d->sig.length < digits) { + d->sig.text[d->sig.length++] = 0; + } + + d->exponent -= d->sig.length - 1; + + for (i = 0; i < d->sig.length; i++) { + d->sig.text[i] += '0'; + } +} + +double __dec2num(const decimal* d) { + if (d->sig.length <= 0) { + return copysign(0.0, d->sign == 0 ? 1.0 : -1.0); + } + + switch (d->sig.text[0]) { + case '0': + return copysign(0.0, d->sign == 0 ? 1.0 : -1.0); + case 'I': + return copysign((double)INFINITY, d->sign == 0 ? 1.0 : -1.0); + case 'N': { + double result; + long long* ll = (long long*)&result; + *ll = 0x7FF0000000000000ULL; + if (d->sign) + *ll |= 0x8000000000000000ULL; + *ll |= 0x0008000000000000ULL; + + return result; + } + } + { + static double pow_10[8] = {1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8}; + decimal dec = *d; + unsigned char* i = dec.sig.text; + unsigned char* e = i + dec.sig.length; + double first_guess; + int exponent; + + for (; i < e; ++i) { + *i -= '0'; + } + + dec.exponent += dec.sig.length - 1; + exponent = dec.exponent; + { + decimal max; + __str2dec(&max, "179769313486231580793728714053034151", 308); + if (__less_dec(&max, &dec)) { + return copysign((double)INFINITY, d->sign == 0 ? 1.0 : -1.0); + } + } + + i = dec.sig.text; + first_guess = *i++; + + while (i < e) { + unsigned long ival = 0; + int j; + double temp1, temp2; + int ndig = (int)(e - i) % 8; + + if (ndig == 0) { + ndig = 8; + } + + for (j = 0; j < ndig; ++j, ++i) { + ival = ival * 10 + *i; + } + + temp1 = first_guess * pow_10[ndig - 1]; + temp2 = temp1 + ival; + + if (ival != 0 && temp1 == temp2) { + break; + } + + first_guess = temp2; + exponent -= ndig; + } + if (exponent < 0) { + first_guess /= pow(5.0, -exponent); + } else { + first_guess *= pow(5.0, exponent); + } + + first_guess = ldexp(first_guess, exponent); + + if (__fpclassifyd(first_guess) == 2) { + first_guess = (double)0x7FEFFFFFFFFFFFFF; + } + + { + decimal feedback1, feedback2, difflow, diffhigh; + double next_guess; + long long* ull = (long long*)&next_guess; + int guessed_low = 0; + __num2dec_internal(&feedback1, first_guess); + + if (__equals_dec(&feedback1, &dec)) { + goto done; + } + + if (__less_dec(&feedback1, &dec)) { + guessed_low = 1; + } + + next_guess = first_guess; + while (1) { + if (guessed_low) { + ++*ull; + if (__fpclassifyd(next_guess) != 2) { + ; // this makes it match somehow + } else { + goto done; + } + } else { + --*ull; + } + + __num2dec_internal(&feedback2, next_guess); + if (guessed_low && !__less_dec(&feedback2, &dec)) { + break; + } else if (!guessed_low && !__less_dec(&dec, &feedback2)) { + difflow = feedback1; + feedback1 = feedback2; + feedback2 = difflow; + { + double temp = first_guess; + first_guess = next_guess; + next_guess = temp; + } + break; + } + feedback1 = feedback2; + first_guess = next_guess; + } + + __minus_dec(&difflow, &dec, &feedback1); + __minus_dec(&diffhigh, &feedback2, &dec); + if (__equals_dec(&difflow, &diffhigh)) { + if (*(long long*)&first_guess & 1) { + first_guess = next_guess; + } + } else if (!__less_dec(&difflow, &diffhigh)) { + first_guess = next_guess; + } + } + done: + if (dec.sign) { + first_guess = -first_guess; + } + return first_guess; + } +} From 2325a6672d91c17a6d0cd37b71a39cf8808798e6 Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Wed, 24 Sep 2025 13:36:54 -0400 Subject: [PATCH 14/25] fix ansi_fp strings --- src/MSL/ansi_fp.c | 88 ++++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/src/MSL/ansi_fp.c b/src/MSL/ansi_fp.c index 0394f8bb..ec6e4be7 100644 --- a/src/MSL/ansi_fp.c +++ b/src/MSL/ansi_fp.c @@ -4,21 +4,29 @@ #pragma exceptions on -//const unsigned char lbl_8037B2F8[0xE0] = { -// 0x35, 0x34, 0x32, 0x31, 0x30, 0x31, 0x30, 0x38, 0x36, 0x32, 0x34, 0x32, 0x37, 0x35, 0x32, 0x32, -// 0x31, 0x37, 0x30, 0x30, 0x33, 0x37, 0x32, 0x36, 0x34, 0x30, 0x30, 0x34, 0x33, 0x34, 0x39, 0x37, -// 0x30, 0x38, 0x35, 0x35, 0x37, 0x31, 0x32, 0x38, 0x39, 0x30, 0x36, 0x32, 0x35, 0x00, 0x31, 0x31, -// 0x31, 0x30, 0x32, 0x32, 0x33, 0x30, 0x32, 0x34, 0x36, 0x32, 0x35, 0x31, 0x35, 0x36, 0x35, 0x34, -// 0x30, 0x34, 0x32, 0x33, 0x36, 0x33, 0x31, 0x36, 0x36, 0x38, 0x30, 0x39, 0x30, 0x38, 0x32, 0x30, -// 0x33, 0x31, 0x32, 0x35, 0x00, 0x32, 0x33, 0x32, 0x38, 0x33, 0x30, 0x36, 0x34, 0x33, 0x36, 0x35, -// 0x33, 0x38, 0x36, 0x39, 0x36, 0x32, 0x38, 0x39, 0x30, 0x36, 0x32, 0x35, 0x00, 0x31, 0x35, 0x32, -// 0x35, 0x38, 0x37, 0x38, 0x39, 0x30, 0x36, 0x32, 0x35, 0x00, 0x33, 0x39, 0x30, 0x36, 0x32, 0x35, -// 0x00, 0x37, 0x38, 0x31, 0x32, 0x35, 0x00, 0x31, 0x35, 0x36, 0x32, 0x35, 0x00, 0x33, 0x31, 0x32, -// 0x35, 0x00, 0x36, 0x32, 0x35, 0x00, 0x31, 0x32, 0x35, 0x00, 0x32, 0x35, 0x00, 0x35, 0x00, 0x31, -// 0x00, 0x32, 0x00, 0x34, 0x00, 0x38, 0x00, 0x31, 0x36, 0x00, 0x33, 0x32, 0x00, 0x36, 0x34, 0x00, -// 0x31, 0x32, 0x38, 0x00, 0x32, 0x35, 0x36, 0x00, 0x31, 0x37, 0x39, 0x37, 0x36, 0x39, 0x33, 0x31, -// 0x33, 0x34, 0x38, 0x36, 0x32, 0x33, 0x31, 0x35, 0x38, 0x30, 0x37, 0x39, 0x33, 0x37, 0x32, 0x38, -// 0x37, 0x31, 0x34, 0x30, 0x35, 0x33, 0x30, 0x33, 0x34, 0x31, 0x35, 0x31, 0x00, 0x00, 0x00, 0x00}; +const signed char lbl_8037B2F8[] = + "542101086242752217003726400434970855712890625\000" + "11102230246251565404236316680908203125\000" + "23283064365386962890625\000" + "152587890625\000" + "390625\000" + "78125\000" + "15625\000" + "3125\000" + "625\000" + "125\000" + "25\000" + "5\000" + "1\000" + "2\000" + "4\000" + "8\000" + "16\000" + "32\000" + "64\000" + "128\000" + "256\000" + "179769313486231580793728714053034151\000\000\000"; const unsigned short __ctype_mapC[0x100] = { 4, 4, 4, 4, 4, 4, 4, 4, @@ -275,67 +283,67 @@ void __str2dec(decimal* pDecimal, const char* pStr, short exp) { static void __two_exp(decimal* pDecimal, long exp) { switch (exp) { case -64: - __str2dec(pDecimal, "542101086242752217003726400434970855712890625", -20); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0], -20); return; case -53: - __str2dec(pDecimal, "11102230246251565404236316680908203125", -16); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x2E], -16); return; case -32: - __str2dec(pDecimal, "23283064365386962890625", -10); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x55], -10); return; case -16: - __str2dec(pDecimal, "152587890625", -5); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x6D], -5); return; case -8: - __str2dec(pDecimal, "390625", -3); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x7A], -3); return; case -7: - __str2dec(pDecimal, "78125", -3); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x81], -3); return; case -6: - __str2dec(pDecimal, "15625", -2); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x87], -2); return; case -5: - __str2dec(pDecimal, "3125", -2); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x8D], -2); return; case -4: - __str2dec(pDecimal, "625", -2); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x92], -2); return; case -3: - __str2dec(pDecimal, "125", -1); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x96], -1); return; case -2: - __str2dec(pDecimal, "25", -1); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x9A], -1); return; case -1: - __str2dec(pDecimal, "5", -1); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x9D], -1); return; case 0: - __str2dec(pDecimal, "1", 0); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x9F], 0); return; case 1: - __str2dec(pDecimal, "2", 0); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xA1], 0); return; case 2: - __str2dec(pDecimal, "4", 0); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xA3], 0); return; case 3: - __str2dec(pDecimal, "8", 0); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xA5], 0); return; case 4: - __str2dec(pDecimal, "16", 1); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xA7], 1); return; case 5: - __str2dec(pDecimal, "32", 1); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xAA], 1); return; case 6: - __str2dec(pDecimal, "64", 1); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xAD], 1); return; case 7: - __str2dec(pDecimal, "128", 2); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xB0], 2); return; case 8: - __str2dec(pDecimal, "256", 2); + __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xB4], 2); return; } @@ -346,9 +354,9 @@ static void __two_exp(decimal* pDecimal, long exp) { if (exp & 1) { temp = *pDecimal; if (exp > 0) - __str2dec(&x2, "2", 0); + __str2dec(&x2, (const char*)&lbl_8037B2F8[0xA1], 0); else - __str2dec(&x2, "5", -1); + __str2dec(&x2, (const char*)&lbl_8037B2F8[0x9D], -1); __timesdec(pDecimal, &temp, &x2); } } @@ -661,7 +669,7 @@ double __dec2num(const decimal* d) { exponent = dec.exponent; { decimal max; - __str2dec(&max, "179769313486231580793728714053034151", 308); + __str2dec(&max, (const char*)&lbl_8037B2F8[0xB8], 308); if (__less_dec(&max, &dec)) { return copysign((double)INFINITY, d->sign == 0 ? 1.0 : -1.0); } @@ -768,4 +776,4 @@ double __dec2num(const decimal* d) { } return first_guess; } -} +} \ No newline at end of file From 53efcb6af0285d7561201cb693b59002cc85f2eb Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Thu, 25 Sep 2025 02:13:19 -0400 Subject: [PATCH 15/25] finish ansi_fp.c --- config/RSPE01_01/symbols.txt | 34 ++++++++-------- include/MSL/ansi_fp.h | 8 ++++ src/MSL/ansi_fp.c | 76 +++++++++++++++++++----------------- src/MSL/locale.c | 22 +++++------ 4 files changed, 74 insertions(+), 66 deletions(-) diff --git a/config/RSPE01_01/symbols.txt b/config/RSPE01_01/symbols.txt index 2ee24722..92dc1f22 100644 --- a/config/RSPE01_01/symbols.txt +++ b/config/RSPE01_01/symbols.txt @@ -14852,15 +14852,15 @@ lbl_8037B248 = .rodata:0x8037B248; // type:object size:0x10 data:4byte __constants = .rodata:0x8037B258; // type:object size:0x18 scope:global data:double @stringBase0 = .rodata:0x8037B270; // type:object size:0x6F scope:local data:string_table fix_pool_sizes = .rodata:0x8037B2E0; // type:object size:0x18 scope:global data:4byte -lbl_8037B2F8 = .rodata:0x8037B2F8; // type:object size:0xE0 +__fp_string_pool = .rodata:0x8037B2F8; // type:object size:0xE0 __ctype_mapC = .rodata:0x8037B3D8; // type:object size:0x200 scope:global __lower_mapC = .rodata:0x8037B5D8; // type:object size:0x100 scope:global __upper_mapC = .rodata:0x8037B6D8; // type:object size:0x100 scope:global -lbl_8037B7D8 = .rodata:0x8037B7D8; // type:object size:0x10 -lbl_8037B7E8 = .rodata:0x8037B7E8; // type:object size:0xC data:string -lbl_8037B7F4 = .rodata:0x8037B7F4; // type:object size:0xC -lbl_8037B800 = .rodata:0x8037B800; // type:object size:0x58 -lbl_8037B858 = .rodata:0x8037B858; // type:object size:0x88 +_DateTime_Format_C = .rodata:0x8037B7D8; // type:object size:0x10 +_Time_Format_12_C = .rodata:0x8037B7E8; // type:object size:0xC data:string +_Date_Format_C = .rodata:0x8037B7F4; // type:object size:0xC +_Day_Names_C = .rodata:0x8037B800; // type:object size:0x58 +_Month_Names_C = .rodata:0x8037B858; // type:object size:0x88 @stringBase0 = .rodata:0x8037B8E0; // type:object size:0x2B scope:local data:string_table gap_07_8037B90B_rodata = .rodata:0x8037B90B; // type:object size:0x5 scope:global lbl_8037B910 = .rodata:0x8037B910; // type:object size:0x28 data:4byte @@ -22950,17 +22950,17 @@ gap_12_804C0A64_sdata2 = .sdata2:0x804C0A64; // type:object size:0x4 scope:globa @8659 = .sdata2:0x804C0AC0; // type:object size:0x4 scope:local align:4 data:float @8675 = .sdata2:0x804C0AC4; // type:object size:0x4 scope:local align:4 data:float @8678 = .sdata2:0x804C0AC8; // type:object size:0x8 scope:local align:8 data:double -lbl_804C0AD0 = .sdata2:0x804C0AD0; // type:object size:0x8 data:double -lbl_804C0AD8 = .sdata2:0x804C0AD8; // type:object size:0x8 data:double -lbl_804C0AE0 = .sdata2:0x804C0AE0; // type:object size:0x8 data:double -lbl_804C0AE8 = .sdata2:0x804C0AE8; // type:object size:0x8 data:double -lbl_804C0AF0 = .sdata2:0x804C0AF0; // type:object size:0x8 data:double -lbl_804C0AF8 = .sdata2:0x804C0AF8; // type:object size:0x8 data:double -lbl_804C0B00 = .sdata2:0x804C0B00; // type:object size:0x8 data:double -lbl_804C0B08 = .sdata2:0x804C0B08; // type:object size:0x4 -lbl_804C0B0C = .sdata2:0x804C0B0C; // type:object size:0x4 -lbl_804C0B10 = .sdata2:0x804C0B10; // type:object size:0x8 -lbl_804C0B18 = .sdata2:0x804C0B18; // type:object size:0x8 +@499 = .sdata2:0x804C0AD0; // type:object size:0x8 data:double +@724 = .sdata2:0x804C0AD8; // type:object size:0x8 data:double +@725 = .sdata2:0x804C0AE0; // type:object size:0x8 data:double +@726 = .sdata2:0x804C0AE8; // type:object size:0x8 data:double +@727 = .sdata2:0x804C0AF0; // type:object size:0x8 data:double +@731 = .sdata2:0x804C0AF8; // type:object size:0x8 data:double +@732 = .sdata2:0x804C0B00; // type:object size:0x8 data:double +_Decimal_Point_C = .sdata2:0x804C0B08; // type:object size:0x4 +_const_int_0 = .sdata2:0x804C0B0C; // type:object size:0x4 +_AmPm_Format_C = .sdata2:0x804C0B10; // type:object size:0x8 +_Time_Format_C = .sdata2:0x804C0B18; // type:object size:0x8 lbl_804C0B20 = .sdata2:0x804C0B20; // type:object size:0x8 data:double lbl_804C0B28 = .sdata2:0x804C0B28; // type:object size:0x1 data:byte lbl_804C0B29 = .sdata2:0x804C0B29; // type:object size:0x1 data:byte diff --git a/include/MSL/ansi_fp.h b/include/MSL/ansi_fp.h index 9281836a..3a7c8581 100644 --- a/include/MSL/ansi_fp.h +++ b/include/MSL/ansi_fp.h @@ -24,6 +24,14 @@ typedef struct decform { extern "C" { #endif +extern const char _AmPm_Format_C[]; +extern const char _DateTime_Format_C[]; +extern const char _Time_Format_12_C[]; +extern const char _Date_Format_C[]; +extern const char _Time_Format_C[]; +extern const char _Day_Names_C[]; +extern const char _Month_Names_C[]; + extern const unsigned short __ctype_mapC[0x100]; extern const unsigned char __lower_mapC[0x100]; extern const unsigned char __upper_mapC[0x100]; diff --git a/src/MSL/ansi_fp.c b/src/MSL/ansi_fp.c index ec6e4be7..87109475 100644 --- a/src/MSL/ansi_fp.c +++ b/src/MSL/ansi_fp.c @@ -4,7 +4,7 @@ #pragma exceptions on -const signed char lbl_8037B2F8[] = +const signed char __fp_string_pool[] = "542101086242752217003726400434970855712890625\000" "11102230246251565404236316680908203125\000" "23283064365386962890625\000" @@ -44,9 +44,7 @@ const unsigned short __ctype_mapC[0x100] = { 0xD0, 0x471, 0x471, 0x471, 0x471, 0x471, 0x471, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, - 0x71, 0x71, 0x71, 0xd0, 0xd0, 0xd0, 0xd0, 4 - -}; + 0x71, 0x71, 0x71, 0xd0, 0xd0, 0xd0, 0xd0, 4}; const unsigned char __lower_mapC[0x100] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, @@ -84,14 +82,18 @@ const unsigned char __upper_mapC[0x100] = { 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF}; +const char _DateTime_Format_C[] = "%a %b %e %T %Y\0"; +const char _Time_Format_12_C[] = "%I:%M:%S %p"; +const char _Date_Format_C[] = "%m/%d/%y\0\0\0"; +const char _Day_Names_C[] = "Sun|Sunday|Mon|Monday|Tue|Tuesday|Wed|Wednesday|Thu|Thursday|Fri|Friday|Sat|Saturday\0\0\0"; +const char _Month_Names_C[] = "Jan|January|Feb|February|Mar|March|Apr|April|May|May|Jun|June|Jul|July|Aug|August|Sep|September|Oct|October|Nov|November|Dec|December\0\0"; + #define INFINITY (*(float*)__float_huge) #define SIGDIGLEN 36 extern double pow(double, double); - inline int count_trailing(double x) { - return __builtin___count_trailing_zero64(*(unsigned long long*)&x | - 0x0010000000000000); + return __builtin___count_trailing_zero64(*(unsigned long long*)&x | 0x0010000000000000); } static inline void __dorounddecup(decimal* d, int digits) { @@ -278,72 +280,70 @@ void __str2dec(decimal* pDecimal, const char* pStr, short exp) { } } - - static void __two_exp(decimal* pDecimal, long exp) { switch (exp) { case -64: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0], -20); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0], -20); return; case -53: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x2E], -16); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0x2E], -16); return; case -32: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x55], -10); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0x55], -10); return; case -16: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x6D], -5); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0x6D], -5); return; case -8: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x7A], -3); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0x7A], -3); return; case -7: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x81], -3); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0x81], -3); return; case -6: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x87], -2); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0x87], -2); return; case -5: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x8D], -2); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0x8D], -2); return; case -4: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x92], -2); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0x92], -2); return; case -3: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x96], -1); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0x96], -1); return; case -2: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x9A], -1); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0x9A], -1); return; case -1: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x9D], -1); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0x9D], -1); return; case 0: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0x9F], 0); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0x9F], 0); return; case 1: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xA1], 0); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0xA1], 0); return; case 2: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xA3], 0); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0xA3], 0); return; case 3: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xA5], 0); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0xA5], 0); return; case 4: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xA7], 1); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0xA7], 1); return; case 5: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xAA], 1); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0xAA], 1); return; case 6: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xAD], 1); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0xAD], 1); return; case 7: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xB0], 2); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0xB0], 2); return; case 8: - __str2dec(pDecimal, (const char*)&lbl_8037B2F8[0xB4], 2); + __str2dec(pDecimal, (const char*)&__fp_string_pool[0xB4], 2); return; } @@ -354,9 +354,9 @@ static void __two_exp(decimal* pDecimal, long exp) { if (exp & 1) { temp = *pDecimal; if (exp > 0) - __str2dec(&x2, (const char*)&lbl_8037B2F8[0xA1], 0); + __str2dec(&x2, (const char*)&__fp_string_pool[0xA1], 0); else - __str2dec(&x2, (const char*)&lbl_8037B2F8[0x9D], -1); + __str2dec(&x2, (const char*)&__fp_string_pool[0x9D], -1); __timesdec(pDecimal, &temp, &x2); } } @@ -669,7 +669,7 @@ double __dec2num(const decimal* d) { exponent = dec.exponent; { decimal max; - __str2dec(&max, (const char*)&lbl_8037B2F8[0xB8], 308); + __str2dec(&max, (const char*)&__fp_string_pool[0xB8], 308); if (__less_dec(&max, &dec)) { return copysign((double)INFINITY, d->sign == 0 ? 1.0 : -1.0); } @@ -711,9 +711,8 @@ double __dec2num(const decimal* d) { first_guess = ldexp(first_guess, exponent); if (__fpclassifyd(first_guess) == 2) { - first_guess = (double)0x7FEFFFFFFFFFFFFF; + first_guess = 1.7976931348623157E+308L; } - { decimal feedback1, feedback2, difflow, diffhigh; double next_guess; @@ -776,4 +775,9 @@ double __dec2num(const decimal* d) { } return first_guess; } -} \ No newline at end of file +} + +const char _Decimal_Point_C[] = ".\0\0"; +const int _const_int_0 = 0; +const char _AmPm_Format_C[] = "AM|PM\0\0"; +const char _Time_Format_C[] = "%T\0\0\0\0\0"; diff --git a/src/MSL/locale.c b/src/MSL/locale.c index 72b2a2c3..c03a0186 100644 --- a/src/MSL/locale.c +++ b/src/MSL/locale.c @@ -4,10 +4,8 @@ #include "wctype.h" #include "ansi_fp.h" -#pragma options align=native -#pragma warn_padding off struct lconv __lconv = { - ".", + "", "", "", "", @@ -32,8 +30,6 @@ struct lconv __lconv = { 127, 127 }; -#pragma warn_padding reset -#pragma options align=reset typedef struct __CMap { char UNK_0x0[0x10]; @@ -98,20 +94,20 @@ struct _loc_mon_cmpt _loc_mon_C = { struct _loc_num_cmpt _loc_num_C = { "C", - ".", + "", "", "" }; struct _loc_time_cmpt _loc_tim_C = { "C", - "AM|PM", - "%a %b %e %T %Y", - "%I:%M:%S %p", - "%m/%d/%y", - "%T", - "Sun|Sunday|Mon|Monday|Tue|Tuesday|Wed|Wednesday|Thu|Thursday|Fri|Friday|Sat|Saturday", - "Jan|January|Feb|February|Mar|March|Apr|April|May|May|Jun|June|Jul|July|Aug|August|Sep|September|Oct|October|Nov|November|Dec|December", + _AmPm_Format_C, + _DateTime_Format_C, + _Time_Format_12_C, + _Date_Format_C, + _Time_Format_C, + _Day_Names_C, + _Month_Names_C, "" }; From eb5ea1630f00ae2ec8d237e67f69a09ea578782a Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Thu, 25 Sep 2025 15:05:52 -0400 Subject: [PATCH 16/25] file io related issues --- include/MSL/ansi_files.h | 26 ++++- include/MSL/ansi_fp.h | 2 + include/MSL/internal/file_struct.h | 6 + include/MSL/uart_console_io_gcn.h | 21 ++++ include/types.h | 2 + src/MSL/ansi_files.c | 169 +++++++++++++++++++++++------ src/MSL/uart_console_io_gcn.c | 3 +- 7 files changed, 191 insertions(+), 38 deletions(-) create mode 100644 include/MSL/uart_console_io_gcn.h diff --git a/include/MSL/ansi_files.h b/include/MSL/ansi_files.h index a7e0dbcf..5513beb3 100644 --- a/include/MSL/ansi_files.h +++ b/include/MSL/ansi_files.h @@ -1,7 +1,23 @@ -typedef unsigned char console_buff[80]; +#ifndef _ANSI_FILES_H +#define _ANSI_FILES_H -static console_buff stdin_buff; -static console_buff stdout_buff; -static console_buff stderr_buff; +#include "types.h" +#include "stdio.h" -void __close_all(void); \ No newline at end of file +#ifdef __cplusplus +extern "C" { +#endif + +#define console_buff_mode _IOLBF +#define console_buff_size 256 + +typedef unsigned char console_buff[console_buff_size]; + +void __close_all(); +u32 __flush_all(); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/include/MSL/ansi_fp.h b/include/MSL/ansi_fp.h index 3a7c8581..57d87b00 100644 --- a/include/MSL/ansi_fp.h +++ b/include/MSL/ansi_fp.h @@ -32,6 +32,8 @@ extern const char _Time_Format_C[]; extern const char _Day_Names_C[]; extern const char _Month_Names_C[]; +extern const int _const_int_0; + extern const unsigned short __ctype_mapC[0x100]; extern const unsigned char __lower_mapC[0x100]; extern const unsigned char __upper_mapC[0x100]; diff --git a/include/MSL/internal/file_struct.h b/include/MSL/internal/file_struct.h index b0519872..e0f5b149 100644 --- a/include/MSL/internal/file_struct.h +++ b/include/MSL/internal/file_struct.h @@ -85,6 +85,12 @@ struct _FILE { struct _FILE* next_file; }; +#define _IONBF 0 +#define _IOLBF 1 +#define _IOFBF 2 + +#define _STATIC_FILES 4 + extern FILE __files[]; #define stdout (&__std(__files[1])) diff --git a/include/MSL/uart_console_io_gcn.h b/include/MSL/uart_console_io_gcn.h new file mode 100644 index 00000000..3bc9093e --- /dev/null +++ b/include/MSL/uart_console_io_gcn.h @@ -0,0 +1,21 @@ +#ifndef _UART_CONSOLE_IO_GCN_H +#define _UART_CONSOLE_IO_GCN_H + +#include "file_struct.h" +#include "types.h" +#include "stdio.h" +#include "UART.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int __read_console(unsigned long, unsigned char* buffer, size_t* count, void* ref); +int __write_console(unsigned long, unsigned char* buffer, size_t* count, void* ref); +int __close_console(unsigned long); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/include/types.h b/include/types.h index 4fd2c040..9cd4fb1a 100644 --- a/include/types.h +++ b/include/types.h @@ -35,6 +35,8 @@ typedef void UNKTYPE; enum { FALSE, TRUE }; typedef int BOOL; +#define nullptr 0 + typedef void (*funcptr_t)(void); #endif diff --git a/src/MSL/ansi_files.c b/src/MSL/ansi_files.c index 4542402a..c93b1488 100644 --- a/src/MSL/ansi_files.c +++ b/src/MSL/ansi_files.c @@ -1,46 +1,153 @@ -#include "file_struct.h" #include "ansi_files.h" -#pragma exceptions on +#include "uart_console_io_gcn.h" +#include "stdio.h" +#include "stdlib.h" +#include "file_struct.h" -void __close_all(void) { - FILE* file = &__files[0]; - FILE* lastFile; +static console_buff stdin_buff; +static console_buff stdout_buff; +static console_buff stderr_buff; - while (file != 0) { - if (file->mode.file != file_closed) { - fclose(file); - } +FILE __files[_STATIC_FILES] = { + { + 0, // _00 + { + must_exist, // _04, open_mode + read, // _04, io_mode + console_buff_mode, // _04, buffer_mode + file_console, // _04, file_kind + 0 // _04, binary_io + }, + { + neutral, // _08, io_state + 0, // _08, free_buffer + 0, // _08, eof + 0 // _08, error + }, + 0, // _0C + 0, // _0D + 0, // _0E + {0, 0}, // _0F + {0, 0}, // _12 + 0, // _18 + stdin_buff, // _1C + console_buff_size, // _20 + stdin_buff, // _24 + 0, // _28 + 0, // _2C + 0, // _30 + 0, // _34 + 0, // _38 + __read_console, // _3C + __write_console, // _40 + __close_console, // _44 + 0, // _48 + &__files[1] // _4C + }, + { + 1, // _00 + { + must_exist, // _04, open_mode + write, // _04, io_mode + console_buff_mode, // _04, buffer_mode + file_console, // _04, file_kind + 0 // _04, binary_io + }, + { + neutral, // _08, io_state + 0, // _08, free_buffer + 0, // _08, eof + 0 // _08, error + }, + 0, // _0C + 0, // _0D + 0, // _0E + {0, 0}, // _0F + {0, 0}, // _12 + 0, // _18 + stdout_buff, // _1C + console_buff_size, // _20 + stdout_buff, // _24 + 0, // _28 + 0, // _2C + 0, // _30 + 0, // _34 + 0, // _38 + __read_console, // _3C + __write_console, // _40 + __close_console, // _44 + 0, // _48 + &__files[2] // _4C + }, + { + 2, // _00 + { + must_exist, // _04, open_mode + write, // _04, io_mode + _IONBF, // _04, buffer_mode + file_console, // _04, file_kind + 0, // _04, binary_io + }, + { + neutral, // _08, io_state + 0, // _08, free_buffer + 0, // _08, eof + 0, // _08, error + }, + 0, // _0C + 0, // _0D + 0, // _0E + {0, 0}, // _0F + {0, 0}, // _12 + 0, // _18 + stderr_buff, // _1C + console_buff_size, // _20 + stderr_buff, // _24 + 0, // _28 + 0, // _2C + 0, // _30 + 0, // _34 + 0, // _38 + __read_console, // _3C + __write_console, // _40 + __close_console, // _44 + 0, // _48 + &__files[3] // _4C + }, +}; - lastFile = file; - file = file->next_file; +void __close_all() { + FILE* p = &__files[0]; + FILE* plast; - if (lastFile->is_dyn_alloc) { - free(lastFile); + while (p) { + if (p->mode.file != file_closed) { + fclose(p); } - else { - lastFile->mode.file = file_unavailable; - if ((file != 0) && (file->is_dyn_alloc)) { - lastFile->next_file = 0; + plast = p; + p = p->next_file; + if (plast->is_dyn_alloc) { + free(plast); + } else { + plast->mode.file = file_unavailable; + if ((p != NULL) && p->is_dyn_alloc) { + plast->next_file = NULL; } } } } -int __flush_all(void) { - int res = 0; - FILE* file = &__files[0]; - - while (file != 0) { - if (file->mode.file != file_closed) { - if (fflush(file)) { - res = -1; - } +u32 __flush_all() { + u32 retval = 0; + FILE* __stream; + __stream = &__files[0]; + while (__stream) { + if ((__stream->mode.file) && (fflush(__stream))) { + retval = -1; } - - file = file->next_file; - } - - return res; + __stream = __stream->next_file; + }; + return retval; } diff --git a/src/MSL/uart_console_io_gcn.c b/src/MSL/uart_console_io_gcn.c index 13950070..bcfe7be6 100644 --- a/src/MSL/uart_console_io_gcn.c +++ b/src/MSL/uart_console_io_gcn.c @@ -1,5 +1,4 @@ -#include "UART.h" -#include "types.h" +#include "UART_console_io_gcn.h" int __TRK_write_console(unsigned long, unsigned char *, size_t *, void *); From aed742a83da0c37b4f3692464525843da361805d Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Thu, 25 Sep 2025 16:37:22 -0400 Subject: [PATCH 17/25] rework ansi_files --- config/RSPE01_01/symbols.txt | 6 +- include/MSL/ansi_files.h | 4 + src/MSL/ansi_files.c | 193 +++++++++++++++-------------------- 3 files changed, 91 insertions(+), 112 deletions(-) diff --git a/config/RSPE01_01/symbols.txt b/config/RSPE01_01/symbols.txt index 92dc1f22..ba0eb258 100644 --- a/config/RSPE01_01/symbols.txt +++ b/config/RSPE01_01/symbols.txt @@ -17307,9 +17307,9 @@ __vt__Q23EGG6MsgRes = .data:0x80398760; // type:object size:0xC scope:global @STRING@getDataBlkSize__Q23EGG6MsgResFPCv@0 = .data:0x80398778; // type:object size:0xE scope:weak data:string @STRING@getDataBlkSize__Q23EGG6MsgResFPCv = .data:0x80398788; // type:object size:0xC scope:weak data:string __files = .data:0x80398798; // type:object size:0x50 scope:global -lbl_803987E8 = .data:0x803987E8; // type:object size:0x50 -lbl_80398838 = .data:0x80398838; // type:object size:0x50 -lbl_80398888 = .data:0x80398888; // type:object size:0x50 +__stdout_FILE = .data:0x803987E8; // type:object size:0x50 +__stderr_FILE = .data:0x80398838; // type:object size:0x50 +__file_terminator = .data:0x80398888; // type:object size:0x50 jumptable_803988D8 = .data:0x803988D8; // type:object size:0x124 scope:local gap_08_803989FC_data = .data:0x803989FC; // type:object size:0x4 scope:global pow_10$933 = .data:0x80398A00; // type:object size:0x40 scope:global diff --git a/include/MSL/ansi_files.h b/include/MSL/ansi_files.h index 5513beb3..cf0fdfc6 100644 --- a/include/MSL/ansi_files.h +++ b/include/MSL/ansi_files.h @@ -13,6 +13,10 @@ extern "C" { typedef unsigned char console_buff[console_buff_size]; +extern console_buff stdin_buff; +extern console_buff stdout_buff; +extern console_buff stderr_buff; + void __close_all(); u32 __flush_all(); diff --git a/src/MSL/ansi_files.c b/src/MSL/ansi_files.c index c93b1488..80991aa7 100644 --- a/src/MSL/ansi_files.c +++ b/src/MSL/ansi_files.c @@ -5,116 +5,91 @@ #include "stdlib.h" #include "file_struct.h" -static console_buff stdin_buff; -static console_buff stdout_buff; -static console_buff stderr_buff; +FILE __stdout_FILE; +FILE __stderr_FILE; -FILE __files[_STATIC_FILES] = { - { - 0, // _00 - { - must_exist, // _04, open_mode - read, // _04, io_mode - console_buff_mode, // _04, buffer_mode - file_console, // _04, file_kind - 0 // _04, binary_io - }, - { - neutral, // _08, io_state - 0, // _08, free_buffer - 0, // _08, eof - 0 // _08, error - }, - 0, // _0C - 0, // _0D - 0, // _0E - {0, 0}, // _0F - {0, 0}, // _12 - 0, // _18 - stdin_buff, // _1C - console_buff_size, // _20 - stdin_buff, // _24 - 0, // _28 - 0, // _2C - 0, // _30 - 0, // _34 - 0, // _38 - __read_console, // _3C - __write_console, // _40 - __close_console, // _44 - 0, // _48 - &__files[1] // _4C - }, - { - 1, // _00 - { - must_exist, // _04, open_mode - write, // _04, io_mode - console_buff_mode, // _04, buffer_mode - file_console, // _04, file_kind - 0 // _04, binary_io - }, - { - neutral, // _08, io_state - 0, // _08, free_buffer - 0, // _08, eof - 0 // _08, error - }, - 0, // _0C - 0, // _0D - 0, // _0E - {0, 0}, // _0F - {0, 0}, // _12 - 0, // _18 - stdout_buff, // _1C - console_buff_size, // _20 - stdout_buff, // _24 - 0, // _28 - 0, // _2C - 0, // _30 - 0, // _34 - 0, // _38 - __read_console, // _3C - __write_console, // _40 - __close_console, // _44 - 0, // _48 - &__files[2] // _4C - }, - { - 2, // _00 - { - must_exist, // _04, open_mode - write, // _04, io_mode - _IONBF, // _04, buffer_mode - file_console, // _04, file_kind - 0, // _04, binary_io - }, - { - neutral, // _08, io_state - 0, // _08, free_buffer - 0, // _08, eof - 0, // _08, error - }, - 0, // _0C - 0, // _0D - 0, // _0E - {0, 0}, // _0F - {0, 0}, // _12 - 0, // _18 - stderr_buff, // _1C - console_buff_size, // _20 - stderr_buff, // _24 - 0, // _28 - 0, // _2C - 0, // _30 - 0, // _34 - 0, // _38 - __read_console, // _3C - __write_console, // _40 - __close_console, // _44 - 0, // _48 - &__files[3] // _4C - }, +// Force __file_terminator to the .data section instead .bss +#pragma push +#pragma explicit_zero_data on +#pragma section data_type ".data" +FILE __file_terminator = {0}; // lbl_80398888 +#pragma pop + +#pragma exceptions on + +FILE __files[1] = {{ + 0, + { must_exist, read, _IOLBF, file_console, file_unoriented, 0 }, + { neutral, 0, 0, 0 }, + 0, + 0, + 0, + {0}, + {0}, + 0, + stdin_buff, + console_buff_size, + stdin_buff, + 0, + 0, + 0, + 0, + NULL, + __read_console, + __write_console, + __close_console, + NULL, + &__stdout_FILE + }}; + +FILE __stdout_FILE = { + 1, + { must_exist, write, _IOLBF, file_console, file_unoriented, 0 }, + { neutral, 0, 0, 0 }, + 0, + 0, + 0, + {0}, + {0}, + 0, + stdout_buff, + console_buff_size, + stdout_buff, + 0, + 0, + 0, + 0, + NULL, + __read_console, + __write_console, + __close_console, + NULL, + &__stderr_FILE +}; + +FILE __stderr_FILE = { + 2, + { must_exist, write, _IONBF, file_console, file_unoriented, 0 }, + { neutral, 0, 0, 0 }, + 0, + 0, + 0, + {0}, + {0}, + 0, + stderr_buff, + console_buff_size, + stderr_buff, + 0, + 0, + 0, + 0, + NULL, + __read_console, + __write_console, + __close_console, + NULL, + &__file_terminator }; void __close_all() { From 25694fc3de62127504df79f10d20f7f5a6f8648c Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Thu, 25 Sep 2025 19:26:45 -0400 Subject: [PATCH 18/25] alloc and wprintf --- include/MSL/ctype.h | 115 +++- include/MSL/errno.h | 5 + include/MSL/stdio.h | 1 + include/MSL/strtoul.h | 18 + include/MSL/va_list.h | 22 + include/MSL/wchar.h | 3 + src/MSL/alloc.c | 331 ++++++++++ src/MSL/strtoul.c | 287 +++++++++ src/MSL/wprintf.c | 1379 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 2153 insertions(+), 8 deletions(-) create mode 100644 include/MSL/strtoul.h create mode 100644 include/MSL/va_list.h create mode 100644 src/MSL/alloc.c create mode 100644 src/MSL/strtoul.c create mode 100644 src/MSL/wprintf.c diff --git a/include/MSL/ctype.h b/include/MSL/ctype.h index aed25213..6490acd5 100644 --- a/include/MSL/ctype.h +++ b/include/MSL/ctype.h @@ -6,16 +6,115 @@ extern "C" { #endif -inline int tolower(int x) { - return (x < 0 || x >= 256) - ? x - : (int)(&_current_locale)->ctype_cmpt_ptr->lower_map_ptr[x]; + +#define ctype_alpha 0x0001 +#define ctype_blank 0x0002 +#define ctype_cntrl 0x0004 +#define ctype_digit 0x0008 +#define ctype_graph 0x0010 +#define ctype_lower 0x0020 +#define ctype_print 0x0040 +#define ctype_punct 0x0080 +#define ctype_space 0x0100 +#define ctype_upper 0x0200 +#define ctype_xdigit 0x0400 + +#define ctype_alnum (ctype_alpha | ctype_digit) + +static inline int isalnum(int c) { + return (c < 0 || c >= 256) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & + ctype_alnum); +} + +static inline int isalpha(int c) { + return (c < 0 || c >= 256) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & + ctype_alpha); +} + +static inline int isblank(int c) { + return (c < 0 || c >= 256) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & + ctype_blank); +} + +static inline int iscntrl(int c) { + return (c < 0 || c >= 256) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & + ctype_cntrl); +} + +static inline int isdigit(int c) { + return (c < 0 || c >= 256) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & + ctype_digit); +} + +static inline int isgraph(int c) { + return (c < 0 || c >= 256) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & + ctype_graph); +} + +static inline int islower(int c) { + return (c < 0 || c >= 256) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & + ctype_lower); +} + +static inline int isprint(int c) { + return (c < 0 || c >= 256) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & + ctype_print); +} + +static inline int ispunct(int c) { + return (c < 0 || c >= 256) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & + ctype_punct); +} + +static inline int isspace(int c) { + return (c < 0 || c >= 256) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & + ctype_space); +} + +static inline int isupper(int c) { + return (c < 0 || c >= 256) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & + ctype_upper); +} + +static inline int isxdigit(int c) { + return (c < 0 || c >= 256) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & + ctype_xdigit); +} + +static inline int tolower(int c) { + return (c < 0 || c >= 256) + ? c + : (int)(&_current_locale)->ctype_cmpt_ptr->lower_map_ptr[c]; } -inline int toupper(int x) { - return (x < 0 || x >= 256) - ? x - : (int)(&_current_locale)->ctype_cmpt_ptr->upper_map_ptr[x]; +static inline int toupper(int c) { + return (c < 0 || c >= 256) + ? c + : (int)(&_current_locale)->ctype_cmpt_ptr->upper_map_ptr[c]; } #ifdef __cplusplus diff --git a/include/MSL/errno.h b/include/MSL/errno.h index c901fcca..02bbad19 100644 --- a/include/MSL/errno.h +++ b/include/MSL/errno.h @@ -7,7 +7,12 @@ extern "C" { extern int errno; +#define ENOERR 0 #define EDOM 33 +#define ERANGE 34 +#define ESIGPARM 36 +#define EFPOS 40 +#define EILSEQ 84 #ifdef __cplusplus } diff --git a/include/MSL/stdio.h b/include/MSL/stdio.h index 538fb215..44b8c44d 100644 --- a/include/MSL/stdio.h +++ b/include/MSL/stdio.h @@ -5,4 +5,5 @@ #include #include #include +#include "stdio_api.h" #endif diff --git a/include/MSL/strtoul.h b/include/MSL/strtoul.h new file mode 100644 index 00000000..c57dfb9f --- /dev/null +++ b/include/MSL/strtoul.h @@ -0,0 +1,18 @@ +#ifndef _STRTOUL_H +#define _STRTOUL_H + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned long __strtoul(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, + int* chars_scanned, int* negative, int* overflow); +unsigned long long __strtoull(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, + int* chars_scanned, int* negative, int* overflow); +int atoi(const char* str); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/MSL/va_list.h b/include/MSL/va_list.h new file mode 100644 index 00000000..16506e0d --- /dev/null +++ b/include/MSL/va_list.h @@ -0,0 +1,22 @@ +#ifndef VA_LIST_H +#define VA_LIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct __va_list_struct { + char gpr; + char fpr; + char reserved[2]; + char* input_arg_area; + char* reg_save_area; +} __va_list[1]; + +typedef __va_list va_list; + +#ifdef __cplusplus +} +#endif + +#endif // VA_LIST_H \ No newline at end of file diff --git a/include/MSL/wchar.h b/include/MSL/wchar.h index 5bfd82ee..7d2c53e1 100644 --- a/include/MSL/wchar.h +++ b/include/MSL/wchar.h @@ -12,6 +12,9 @@ extern "C" { #define WCHAR_MIN SHRT_MIN #define WCHAR_MAX USHRT_MAX +typedef unsigned short wchar_t; +typedef wchar_t wint_t; + #ifdef __cplusplus } #endif diff --git a/src/MSL/alloc.c b/src/MSL/alloc.c new file mode 100644 index 00000000..ff9dae28 --- /dev/null +++ b/src/MSL/alloc.c @@ -0,0 +1,331 @@ +void __sys_free(void* ptr); +void* memset(void*, int, int); + +typedef struct Block { + struct Block* prev; + struct Block* next; + unsigned long max_size; + unsigned long size; +} Block; + +typedef struct SubBlock { + unsigned long size; + Block* block; + struct SubBlock* prev; + struct SubBlock* next; +} SubBlock; + +struct FixSubBlock; + +typedef struct FixBlock { + struct FixBlock* prev_; + struct FixBlock* next_; + unsigned long client_size_; + struct FixSubBlock* start_; + unsigned long n_allocated_; +} FixBlock; + +typedef struct FixSubBlock { + FixBlock* block_; + struct FixSubBlock* next_; +} FixSubBlock; + +typedef struct FixStart { + FixBlock* tail_; + FixBlock* head_; +} FixStart; + +typedef struct __mem_pool_obj { + Block* start_; + FixStart fix_start[6]; +} __mem_pool_obj; + +typedef struct __mem_pool { + void* reserved[14]; +} __mem_pool; + +typedef signed long tag_word; + +typedef struct block_header { + tag_word tag; + struct block_header* prev; + struct block_header* next; +} block_header; + +typedef struct list_header { + block_header* rover; + block_header header; +} list_header; + +typedef struct heap_header { + struct heap_header* prev; + struct heap_header* next; +} heap_header; + +struct mem_pool_obj; +typedef void* (*sys_alloc_ptr)(unsigned long, struct mem_pool_obj*); +typedef void (*sys_free_ptr)(void*, struct mem_pool_obj*); + +typedef struct pool_options { + sys_alloc_ptr sys_alloc_func; + sys_free_ptr sys_free_func; + unsigned long min_heap_size; + int always_search_first; +} pool_options; + +typedef struct mem_pool_obj { + list_header free_list; + pool_options options; + heap_header* heap_list; + void* userData; + +} mem_pool_obj; + +mem_pool_obj __malloc_pool; +static int initialized = 0; + +static void SubBlock_merge_next(SubBlock*, SubBlock**); + +static const unsigned long fix_pool_sizes[] = {4, 12, 20, 36, 52, 68}; + +#define SubBlock_size(ths) ((ths)->size & 0xFFFFFFF8) +#define SubBlock_block(ths) ((Block*)((unsigned long)((ths)->block) & ~0x1)) +#define Block_size(ths) ((ths)->size & 0xFFFFFFF8) +#define Block_start(ths) \ + (*(SubBlock**)((char*)(ths) + Block_size((ths)) - sizeof(unsigned long))) + +#define SubBlock_set_free(ths) \ + unsigned long this_size = SubBlock_size((ths)); \ + (ths)->size &= ~0x2; \ + *(unsigned long*)((char*)(ths) + this_size) &= ~0x4; \ + *(unsigned long*)((char*)(ths) + this_size - sizeof(unsigned long)) = \ + this_size + +#define SubBlock_is_free(ths) !((ths)->size & 2) +#define SubBlock_set_size(ths, sz) \ + (ths)->size &= ~0xFFFFFFF8; \ + (ths)->size |= (sz)&0xFFFFFFF8; \ + if (SubBlock_is_free((ths))) \ + *(unsigned long*)((char*)(ths) + (sz) - sizeof(unsigned long)) = (sz) + +#define SubBlock_from_pointer(ptr) ((SubBlock*)((char*)(ptr)-8)) +#define FixSubBlock_from_pointer(ptr) ((FixSubBlock*)((char*)(ptr)-4)) + +#define FixBlock_client_size(ths) ((ths)->client_size_) +#define FixSubBlock_size(ths) (FixBlock_client_size((ths)->block_)) + +#define classify(ptr) \ + (*(unsigned long*)((char*)(ptr) - sizeof(unsigned long)) & 1) +#define __msize_inline(ptr) \ + (!classify(ptr) ? FixSubBlock_size(FixSubBlock_from_pointer(ptr)) \ + : SubBlock_size(SubBlock_from_pointer(ptr)) - 8) + +#define Block_empty(ths) \ + (_sb = (SubBlock*)((char*)(ths) + 16)), \ + SubBlock_is_free(_sb) && SubBlock_size(_sb) == Block_size((ths)) - 24 + +inline static SubBlock* SubBlock_merge_prev(SubBlock* ths, SubBlock** start) { + unsigned long prevsz; + SubBlock* p; + + if (!(ths->size & 0x04)) { + prevsz = *(unsigned long*)((char*)ths - sizeof(unsigned long)); + if (prevsz & 0x2) + return ths; + p = (SubBlock*)((char*)ths - prevsz); + SubBlock_set_size(p, prevsz + SubBlock_size(ths)); + + if (*start == ths) + *start = (*start)->next; + ths->next->prev = ths->prev; + ths->next->prev->next = ths->next; + return p; + } + return ths; +} + +void Block_link(Block* ths, SubBlock* sb) { + SubBlock** st; + SubBlock_set_free(sb); + st = &Block_start(ths); + + if (*st != 0) { + sb->prev = (*st)->prev; + sb->prev->next = sb; + sb->next = *st; + (*st)->prev = sb; + *st = sb; + *st = SubBlock_merge_prev(*st, st); + SubBlock_merge_next(*st, st); + } else { + *st = sb; + sb->prev = sb; + sb->next = sb; + } + if (ths->max_size < SubBlock_size(*st)) + ths->max_size = SubBlock_size(*st); +} + +static void SubBlock_merge_next(SubBlock* pBlock, SubBlock** pStart) { + SubBlock* next_sub_block; + unsigned long this_cur_size; + + next_sub_block = (SubBlock*)((char*)pBlock + (pBlock->size & 0xFFFFFFF8)); + + if (!(next_sub_block->size & 2)) { + this_cur_size = + (pBlock->size & 0xFFFFFFF8) + (next_sub_block->size & 0xFFFFFFF8); + + pBlock->size &= ~0xFFFFFFF8; + pBlock->size |= this_cur_size & 0xFFFFFFF8; + + if (!(pBlock->size & 2)) { + *(unsigned long*)((char*)(pBlock) + (this_cur_size)-4) = + (this_cur_size); + } + + if (!(pBlock->size & 2)) { + *(unsigned long*)((char*)pBlock + this_cur_size) &= ~4; + } else { + *(unsigned long*)((char*)pBlock + this_cur_size) |= 4; + } + + if (*pStart == next_sub_block) { + *pStart = (*pStart)->next; + } + + if (*pStart == next_sub_block) { + *pStart = 0; + } + + next_sub_block->next->prev = next_sub_block->prev; + next_sub_block->prev->next = next_sub_block->next; + } +} + +inline static Block* __unlink(__mem_pool_obj* pool_obj, Block* bp) { + Block* result = bp->next; + if (result == bp) { + result = 0; + } + + if (pool_obj->start_ == bp) { + pool_obj->start_ = result; + } + + if (result != 0) { + result->prev = bp->prev; + result->prev->next = result; + } + + bp->next = 0; + bp->prev = 0; + return result; +} + +inline static void deallocate_from_var_pools(__mem_pool_obj* pool_obj, void* ptr) { + SubBlock* sb = SubBlock_from_pointer(ptr); + SubBlock* _sb; + + Block* bp = SubBlock_block(sb); + Block_link(bp, sb); + + if (Block_empty(bp)) { + __unlink(pool_obj, bp); + __sys_free(bp); + } +} + +void deallocate_from_fixed_pools(__mem_pool_obj* pool_obj, void* ptr, + unsigned long size) { + unsigned long i = 0; + FixSubBlock* p; + FixBlock* b; + FixStart* fs; + + while (size > fix_pool_sizes[i]) { + ++i; + } + + fs = &pool_obj->fix_start[i]; + p = FixSubBlock_from_pointer(ptr); + b = p->block_; + + if (b->start_ == 0 && fs->head_ != b) { + if (fs->tail_ == b) { + fs->head_ = fs->head_->prev_; + fs->tail_ = fs->tail_->prev_; + } else { + b->prev_->next_ = b->next_; + b->next_->prev_ = b->prev_; + b->next_ = fs->head_; + b->prev_ = b->next_->prev_; + b->prev_->next_ = b; + b->next_->prev_ = b; + fs->head_ = b; + } + } + + p->next_ = b->start_; + b->start_ = p; + + if (--b->n_allocated_ == 0) { + if (fs->head_ == b) { + fs->head_ = b->next_; + } + + if (fs->tail_ == b) { + fs->tail_ = b->prev_; + } + + b->prev_->next_ = b->next_; + b->next_->prev_ = b->prev_; + + if (fs->head_ == b) { + fs->head_ = 0; + } + + if (fs->tail_ == b) { + fs->tail_ = 0; + } + + deallocate_from_var_pools(pool_obj, b); + } +} + +inline void __pool_free(__mem_pool* pool, void* ptr) { + __mem_pool_obj* pool_obj; + unsigned long size; + + if (ptr == 0) { + return; + } + + pool_obj = (__mem_pool_obj*)pool; + size = __msize_inline(ptr); + + if (size <= 68) { + deallocate_from_fixed_pools(pool_obj, ptr, size); + } else { + deallocate_from_var_pools(pool_obj, ptr); + } +} + +inline void __init_pool_obj(__mem_pool* pool_obj) { + memset(pool_obj, 0, sizeof(__mem_pool_obj)); +} + +inline static __mem_pool* get_malloc_pool(void) { + static __mem_pool protopool; + static unsigned char init = 0; + if (!init) { + __init_pool_obj(&protopool); + init = 1; + } + + return &protopool; +} + +void free(void* ptr) { + __pool_free(get_malloc_pool(), ptr); +} diff --git a/src/MSL/strtoul.c b/src/MSL/strtoul.c new file mode 100644 index 00000000..7b634729 --- /dev/null +++ b/src/MSL/strtoul.c @@ -0,0 +1,287 @@ +#include "strtoul.h" +#include "ctype.h" +#include "errno.h" +#include "limits.h" +#include "stdio.h" + +enum scan_states { + start = 0x01, + check_for_zero = 0x02, + leading_zero = 0x04, + need_digit = 0x08, + digit_loop = 0x10, + finished = 0x20, + failure = 0x40 +}; + +#define final_state(scan_state) (scan_state & (finished | failure)) +#define success(scan_state) (scan_state & (leading_zero | digit_loop | finished)) +#define fetch() (count++, (*ReadProc)(ReadProcArg, 0, __GetAChar)) +#define unfetch(c) (*ReadProc)(ReadProcArg, c, __UngetAChar) + +#pragma exceptions on + +// jumptable_80398FEC located in scanf + +unsigned long __strtoul(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, + int* chars_scanned, int* negative, int* overflow) { + int scan_state = start; + int count = 0; + int spaces = 0; + unsigned long value = 0; + unsigned long value_max = 0; + int c; + + *negative = *overflow = 0; + + if (base < 0 || base == 1 || base > 36 || max_width < 1) { + scan_state = failure; + } else { + c = fetch(); + } + + if (base != 0) { + value_max = ULONG_MAX / base; + } + + while (count <= max_width && c != -1 && !final_state(scan_state)) { + switch (scan_state) { + case start: + if (isspace(c)) { + c = fetch(); + count--; + spaces++; + break; + } + + if (c == '+') { + c = fetch(); + } else if (c == '-') { + c = fetch(); + *negative = 1; + } + + scan_state = check_for_zero; + break; + + case check_for_zero: + if (base == 0 || base == 16) { + if (c == '0') { + scan_state = leading_zero; + c = fetch(); + break; + } + } + + scan_state = need_digit; + break; + + case 4: + if (c == 'X' || c == 'x') { + base = 16; + scan_state = need_digit; + c = fetch(); + break; + } + + if (base == 0) { + base = 8; + } + + scan_state = digit_loop; + break; + + case need_digit: + case digit_loop: + if (base == 0) { + base = 10; + } + + if (!value_max) { + value_max = ULONG_MAX / base; + } + + if (isdigit(c)) { + if ((c -= '0') >= base) { + if (scan_state == digit_loop) { + scan_state = finished; + } else { + scan_state = failure; + } + + c += '0'; + break; + } + } else if (!isalpha(c) || (toupper(c) - 'A' + 10) >= base) { + if (scan_state == digit_loop) { + scan_state = finished; + } else { + scan_state = failure; + } + + break; + } else { + c = toupper(c) - 'A' + 10; + } + + if (value > value_max) { + *overflow = 1; + } + + value *= base; + + if (c > (ULONG_MAX - value)) { + *overflow = 1; + } + + value += c; + scan_state = digit_loop; + c = fetch(); + break; + } + } + + if (!success(scan_state)) { + count = 0; + value = 0; + *chars_scanned = 0; + } else { + count--; + *chars_scanned = count + spaces; + } + + unfetch(c); + return value; +} + +unsigned long long __strtoull(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, + int* chars_scanned, int* negative, int* overflow) { + int scan_state = start; + int count = 0; + int spaces = 0; + unsigned long long value = 0; + unsigned long long value_max = 0; + unsigned long long ullmax = ULLONG_MAX; + int c; + + *negative = *overflow = 0; + + if (base < 0 || base == 1 || base > 36 || max_width < 1) { + scan_state = failure; + } else { + c = fetch(); + } + + if (base != 0) { + value_max = ullmax / base; + } + + while (count <= max_width && c != -1 && !final_state(scan_state)) { + switch (scan_state) { + case start: + if (isspace(c)) { + c = fetch(); + count--; + spaces++; + break; + } + + if (c == '+') { + c = fetch(); + } else if (c == '-') { + c = fetch(); + *negative = 1; + } + + scan_state = check_for_zero; + break; + + case check_for_zero: + if (base == 0 || base == 16) { + if (c == '0') { + scan_state = leading_zero; + c = fetch(); + break; + } + } + + scan_state = need_digit; + break; + + case leading_zero: + if (c == 'X' || c == 'x') { + base = 16; + scan_state = need_digit; + c = fetch(); + break; + } + + if (base == 0) { + base = 8; + } + + scan_state = digit_loop; + break; + + case need_digit: + case digit_loop: + if (base == 0) { + base = 10; + } + + if (!value_max) { + value_max = ullmax / base; + } + + if (isdigit(c)) { + if ((c -= '0') >= base) { + if (scan_state == digit_loop) { + scan_state = finished; + } else { + scan_state = failure; + } + + c += '0'; + break; + } + } else if (!isalpha(c) || (toupper(c) - 'A' + 10) >= base) { + if (scan_state == digit_loop) { + scan_state = finished; + } else { + scan_state = failure; + } + + break; + } else { + c = toupper(c) - 'A' + 10; + } + + if (value > value_max) { + *overflow = 1; + } + + value *= base; + + if (c > (ullmax - value)) { + *overflow = 1; + } + + value += c; + scan_state = digit_loop; + c = fetch(); + break; + } + } + + if (!success(scan_state)) { + count = 0; + value = 0; + *chars_scanned = 0; + } else { + count--; + *chars_scanned = count + spaces; + } + + unfetch(c); + return value; +} diff --git a/src/MSL/wprintf.c b/src/MSL/wprintf.c new file mode 100644 index 00000000..5538c7ef --- /dev/null +++ b/src/MSL/wprintf.c @@ -0,0 +1,1379 @@ +#include "ansi_fp.h" +#include "stdio_api.h" +#include "wstring.h" +#include "stdarg.h" +#include "wchar.h" +#include "locale.h" + +#pragma exceptions on + +#define LDBL_MANT_DIG 24 +#define LDBL_MAX_EXP 128 +#define TARGET_FLOAT_BITS 32 +#define TARGET_FLOAT_BYTES (TARGET_FLOAT_BITS/8) +#define TARGET_FLOAT_MAX_EXP LDBL_MAX_EXP +#define TARGET_FLOAT_MANT_DIG LDBL_MANT_DIG +#define TARGET_FLOAT_IMPLICIT_J_BIT 1 +#define TARGET_FLOAT_MANT_BITS (TARGET_FLOAT_MANT_DIG - TARGET_FLOAT_IMPLICIT_J_BIT) +#define TARGET_FLOAT_EXP_BITS (TARGET_FLOAT_BITS - TARGET_FLOAT_MANT_BITS - 1) + +typedef long long intmax_t; + +#define PTRDIFF __typeof__((char*)0-(char*)0) +typedef PTRDIFF ptrdiff_t; + +wchar_t* wcscpy(wchar_t *pDest, const wchar_t *pSrc); +size_t strlen(const char *pStr); +void* memchr(const void *, int, size_t); +int mbtowc(wchar_t *pDest, const char *s, size_t num); + +enum justification_options { + left_justification, + right_justification, + zero_fill +}; + +enum sign_options { + only_minus, + sign_always, + space_holder +}; + +enum argument_options { + normal_argument, + char_argument, + short_argument, + long_argument, + long_long_argument, + wchar_argument, + intmax_argument, + size_t_argument, + ptrdiff_argument, + long_double_argument +}; + +typedef struct { + unsigned char justification_options; // 0x0 + unsigned char sign_options; // 0x1 + unsigned char precision_specified; // 0x2 + unsigned char alternate_form; // 0x3 + unsigned char argument_options; // 0x4 + wchar_t conversion_char; // 0x5 + int field_width; // 0x8 + int precision; // 0xC +} print_format; + +typedef struct { + char* CharStr; + size_t MaxCharCount; + size_t CharsWritten; +} __OutStrCtrl; + +inline int iswdigit(wint_t c) { + return ((c < 0) || (c >= 0x100)) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & + 0x8); +} + +inline int iswupper(wint_t c) { + return ((c < 0) || (c >= 0x100)) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & + 0x200); +} + +const wchar_t* parse_format(const wchar_t *format_string, va_list *arg, print_format *format) { + print_format f; + const wchar_t* s = format_string; + wchar_t c; + int flag_found; + f.justification_options = right_justification; + f.sign_options = only_minus; + f.precision_specified = 0; + f.alternate_form = 0; + f.argument_options = normal_argument; + f.field_width = 0; + f.precision = 0; + + if ((c = *++s) == L'%') { + f.conversion_char = c; + *format = f; + return ((const wchar_t*)s + 1); + } + + for (;;) { + flag_found = 1; + + switch (c) { + case L'-': + f.justification_options = left_justification; + break; + case L'+': + f.sign_options = sign_always; + break; + case L' ': + if (f.sign_options != sign_always) { + f.sign_options = space_holder; + } + break; + case L'#': + f.alternate_form = 1; + break; + case L'0': + if (f.justification_options != left_justification) { + f.justification_options = zero_fill; + } + break; + default: + flag_found = 0; + break; + } + + if (flag_found) { + c = *++s; + } + else { + break; + } + } + + if (c == L'*') { + if ((f.field_width = va_arg(*arg, int)) < 0) { + f.justification_options = left_justification; + f.field_width = -f.field_width; + } + + c = *++s; + } + else { + while (iswdigit(c)) { + f.field_width = (f.field_width * 10) + (c - L'0'); + c = *++s; + } + } + + if (f.field_width > 509) { + f.conversion_char = 0xFFFF; + *format = f; + return ((const wchar_t*)s + 1); + } + + if (c == L'.') { + f.precision_specified = 1; + + if ((c = *++s) == L'*') { + if ((f.precision = va_arg(*arg, int)) < 0) { + f.precision_specified = 0; + } + + c = *++s; + } + else { + while (iswdigit(c)) { + f.precision = (f.precision * 10) + (c - L'0'); + c = *++s; + } + } + } + + flag_found = 1; + + switch (c) { + case L'h': + f.argument_options = short_argument; + + if (s[1] == L'h') { + f.argument_options = char_argument; + c = *++s; + } + + break; + + case L'l': + f.argument_options = long_argument; + + if (s[1] == L'l') { + f.argument_options = long_long_argument; + c = *++s; + } + + break; + + case L'L': + f.argument_options = long_double_argument; + break; + case L'j': + f.argument_options = intmax_argument; + break; + case L't': + f.argument_options = ptrdiff_argument; + break; + case L'z': + f.argument_options = size_t_argument; + break; + default: + flag_found = 0; + break; + } + + if (flag_found) { + c = *++s; + } + + f.conversion_char = c; + + switch (c) { + case L'd': + case L'i': + case L'u': + case L'o': + case L'x': + case L'X': + if (f.argument_options == long_double_argument) { + f.conversion_char = long_long_argument; + } + + if (!f.precision_specified) { + f.precision = 1; + } + else if (f.justification_options == zero_fill) { + f.justification_options = right_justification; + } + break; + + case L'f': + case L'F': + if (f.argument_options == short_argument || f.argument_options == intmax_argument || f.argument_options == size_t_argument || f.argument_options == ptrdiff_argument || f.argument_options == long_long_argument) { + f.conversion_char = 0xFFFF; + break; + } + + if (!f.precision_specified) { + f.precision = 6; + } + break; + + case L'a': + case L'A': + if (!f.precision_specified) { + f.precision = 0xD; + } + + if (f.argument_options == short_argument || f.argument_options == intmax_argument || + f.argument_options == size_t_argument || f.argument_options == ptrdiff_argument || + f.argument_options == long_long_argument || f.argument_options == char_argument) { + f.conversion_char = 0xFFFF; + } + + break; + + case L'g': + case L'G': + if (!f.precision) { + f.precision = 1; + } + + case L'e': + case L'E': + if (f.argument_options == short_argument || f.argument_options == intmax_argument || f.argument_options == size_t_argument || f.argument_options == ptrdiff_argument || f.argument_options == long_long_argument || f.argument_options == char_argument) { + f.conversion_char = 0xFFFF; + break; + } + + if (!f.precision_specified) { + f.precision = 6; + } + break; + + case L'p': + f.argument_options = long_argument; + f.alternate_form = 1; + f.conversion_char = L'x'; + f.precision = 8; + break; + + case L'c': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } + else { + if (f.precision_specified || f.argument_options != normal_argument) { + f.conversion_char = 0xFFFF; + } + } + + break; + + case L's': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } + else { + if (f.argument_options != normal_argument) { + f.conversion_char = 0xFFFF; + } + } + + break; + + case L'n': + if (f.argument_options == long_double_argument) { + f.conversion_char = long_long_argument; + } + + break; + + default: + f.conversion_char = 0xFFFF; + break; + } + + *format = f; + return ((const wchar_t*)s + 1); +} + +wchar_t * long2str(long num, wchar_t * buff, print_format format) { + unsigned long unsigned_num, base; + wchar_t* p; + int n, digits; + int minus = 0; + unsigned_num = num; + minus = 0; + + p = buff; + *--p = 0; + digits = 0; + + if (!num && !format.precision && !(format.alternate_form && format.conversion_char == L'o')) { + return p; + } + + switch (format.conversion_char) { + case L'd': + case L'i': + base = 10; + + if (num < 0) { + if (num != 0x80000000) { + unsigned_num = -num; + } + + minus = 1; + } + break; + + case L'o': + base = 8; + format.sign_options = only_minus; + break; + + case L'u': + base = 10; + format.sign_options = only_minus; + break; + + case L'x': + case L'X': + base = 16; + format.sign_options = only_minus; + break; + } + + do { + n = unsigned_num % base; + unsigned_num /= base; + + if (n < 10) { + n += L'0'; + } + else { + n -= 10; + + if (format.conversion_char == L'x') { + n += L'a'; + } + else { + n += L'A'; + } + } + + *--p = n; + ++digits; + } + while (unsigned_num != 0); + + if (base == 8 && format.alternate_form && *p != L'0') { + *--p = L'0'; + ++digits; + } + + if (format.justification_options == zero_fill) { + format.precision = format.field_width; + + if (minus || format.sign_options != only_minus) + --format.precision; + + if (base == 16 && format.alternate_form) + format.precision -= 2; + } + + if (buff - p + format.precision > 509) + return 0; + + while (digits < format.precision) { + *--p = L'0'; + ++digits; + } + + if (base == 16 && format.alternate_form) { + *--p = format.conversion_char; + *--p = L'0'; + } + + if (minus) { + *--p = L'-'; + } + else if (format.sign_options == sign_always) { + *--p = L'+'; + } + else if (format.sign_options == space_holder) { + *--p = L' '; + } + + return p; +} + +wchar_t* longlong2str(long long num, wchar_t *pBuf, print_format fmt) { + unsigned long long unsigned_num, base; + wchar_t* p; + int n, digits; + int minus = 0; + unsigned_num = num; + minus = 0; + p = pBuf; + *--p = 0; + digits = 0; + + if (!num && !fmt.precision && !(fmt.alternate_form && fmt.conversion_char == L'o')) { + return p; + } + + switch (fmt.conversion_char) { + case L'd': + case L'i': + base = 10; + + if (num < 0) { + if (num != 0x8000000000000000) { + unsigned_num = -num; + } + + minus = 1; + } + break; + case L'o': + base = 8; + fmt.sign_options = only_minus; + break; + case L'u': + base = 10; + fmt.sign_options = only_minus; + break; + case L'x': + case L'X': + base = 16; + fmt.sign_options = only_minus; + break; + } + + do { + n = unsigned_num % base; + unsigned_num /= base; + + if (n < 10) { + n += L'0'; + } + else { + n -= 10; + if (fmt.conversion_char == L'x') { + n += L'a'; + } + else { + n += L'A'; + } + } + + *--p = n; + ++digits; + } while (unsigned_num != 0); + + if (base == 8 && fmt.alternate_form && *p != L'0') { + *--p = L'0'; + ++digits; + } + + if (fmt.justification_options == zero_fill) { + fmt.precision = fmt.field_width; + + if (minus || fmt.sign_options != only_minus) { + --fmt.precision; + } + + if (base == 16 && fmt.alternate_form) { + fmt.precision -= 2; + } + } + + if (pBuf - p + fmt.precision > 509) { + return 0; + } + + while (digits < fmt.precision) { + *--p = L'0'; + ++digits; + } + + if (base == 16 && fmt.alternate_form) { + *--p = fmt.conversion_char; + *--p = L'0'; + } + + if (minus) { + *--p = L'-'; + } + else if (fmt.sign_options == sign_always) { + *--p = L'+'; + } + else if (fmt.sign_options == space_holder) { + *--p = L' '; + } + + return p; +} + +wchar_t * double2hex(long double num, wchar_t * buff, print_format format) { + wchar_t *p; + unsigned char *q; + unsigned char working_byte; + long double ld; + int expbits, expmask; + unsigned snum; + long exp; + print_format exp_format; + int hex_precision; + int mantissa_bit; + decform form; + decimal dec; + int radix_marker; + + radix_marker = * (unsigned char *)(__lconv).decimal_point; + p = buff; + ld = num; + + if (format.precision > 509) { + return 0; + } + + form.style = (char)0; + form.digits = 0x20; + __num2dec(&form, num, &dec); + + if (fabsl(num) == 0.0) { + p = buff - 6; + wcscpy(p, L"0x0p0"); + return p; + } + + if (*dec.sig.text == 'I') { + if (dec.sign) { + p = buff - 5; + if (format.conversion_char == L'A') + wcscpy(p, L"-INF"); + else + wcscpy(p, L"-inf"); + } + else { + p = buff - 4; + if (format.conversion_char == L'A') + wcscpy(p, L"INF"); + else + wcscpy(p, L"inf"); + } + + return p; + } + else if (*dec.sig.text == 'N') { + if (dec.sign) { + p = buff - 5; + if (format.conversion_char == L'A') + wcscpy(p, L"-NAN"); + else + wcscpy(p, L"-nan"); + } + else { + p = buff - 4; + if (format.conversion_char == L'A') + wcscpy(p, L"NAN"); + else + wcscpy(p, L"nan"); + } + return p; + } + + exp_format.justification_options = 1; + exp_format.sign_options = 1; + exp_format.precision_specified = 0; + exp_format.alternate_form = 0; + exp_format.argument_options = 0; + exp_format.field_width = 0; + exp_format.precision = 1; + exp_format.conversion_char = 'd'; + + expbits = 11; + expmask = 0x7FF; + + snum = ((unsigned char *)&num)[0] << 25; + if (TARGET_FLOAT_EXP_BITS > 7) + snum |= ((unsigned char *)&num)[1] << 17; + if (TARGET_FLOAT_EXP_BITS > 15) + snum |= ((unsigned char *)&num)[2] << 9; + if (TARGET_FLOAT_EXP_BITS > 23) + snum |= ((unsigned char *)&num)[3] << 1; + + snum = (snum >> (32 - expbits)) & expmask; + exp = snum - 0x3FF; + + p = long2str(exp, buff, exp_format); + if (format.conversion_char == L'a') + *--p = L'p'; + else + *--p = L'P'; + q = (unsigned char *)# + + if (TARGET_FLOAT_IMPLICIT_J_BIT) { + mantissa_bit = (1 + expbits + format.precision * 4) - 1; + } + else { + mantissa_bit = (1 + expbits + format.precision * 4) - 4; + } + + for (hex_precision = format.precision; hex_precision >= 1; hex_precision--) { + if (mantissa_bit < 64) { + int mantissa_byte; + + mantissa_byte = mantissa_bit >> 3; + working_byte = (*(q + mantissa_byte)) >> (7 - (mantissa_bit & 7)); + + if ((mantissa_bit & ~7) != ((mantissa_bit - 4) & ~7)) { + working_byte |= ((*(q + (mantissa_byte - 1))) << 8) >> (7 - ((mantissa_bit) & 7)); + } + + if (!TARGET_FLOAT_IMPLICIT_J_BIT) { + if (mantissa_bit == 1 + expbits) { + *--p = radix_marker; + working_byte &= 0x1; + } + } + + if ((working_byte &= 0xF) < 10) { + working_byte += L'0'; + } + else + if (format.conversion_char == L'a') { + working_byte += L'a' - 10; + } + else { + working_byte += L'A' - 10; + } + } + else { + working_byte = L'0'; + } + + *--p = working_byte; + mantissa_bit -= 4; + } + + if (TARGET_FLOAT_IMPLICIT_J_BIT){ + if (format.precision || format.alternate_form) { + *--p = radix_marker; + } + + *--p = L'1'; + } + + if (format.conversion_char == L'a') { + *--p = L'x'; + } + else { + *--p = L'X'; + } + + *--p = L'0'; + + if (dec.sign) { + *--p = L'-'; + } + else if (format.sign_options == 1) { + *--p = L'+'; + } + else if (format.sign_options == 2) { + *--p = L' '; + } + + return p; +} + +void round_decimal(decimal *dec, int new_length) { + char c; + char* p; + int carry; + + if (new_length < 0) { +return_zero: + dec->exponent = 0; + dec->sig.length = 1; + *dec->sig.text = '0'; + return; + } + + if (new_length >= dec->sig.length) { + return; + } + + p = (char*)dec->sig.text + new_length + 1; + c = *--p - L'0'; + + if (c == 5) { + char* q = &((char*)dec->sig.text)[dec->sig.length]; + + while (--q > p && *q == '0'); + carry = (q == p) ? p[-1] & 1 : 1; + } + else { + carry = (c > 5); + } + + while (new_length != 0) { + c = *--p - L'0' + carry; + + if ((carry = (c > 9)) != 0 || c == 0) { + --new_length; + } + else { + *p = c + L'0'; + break; + } + } + + if (carry != 0) { + dec->exponent += 1; + dec->sig.length = 1; + *dec->sig.text = '1'; + return; + } + else if (new_length == 0) { + goto return_zero; + } + + dec->sig.length = new_length; +} + +wchar_t* float2str(long double num, wchar_t *wbuff, print_format format) { + decimal dec; + decform form; + wchar_t* pw; + char* p; + char buff[512]; + char* q; + int n, digits, sign; + int int_digits, frac_digits; + int radix_marker; + + radix_marker = *(unsigned char*)__lconv.decimal_point; + + if (format.precision > 509) { + return 0; + } + + form.style = 0; + form.digits = 0x20; + __num2dec(&form, num, &dec); + p = (char*)dec.sig.text + dec.sig.length; + + while (dec.sig.length > 1 && *--p == '0') { + --dec.sig.length; + ++dec.exponent; + } + + switch (*dec.sig.text) { + case '0': + dec.exponent = 0; + break; + case 'I': + if (num < 0) { + pw = wbuff - 5; + + if (iswupper(format.conversion_char)) { + wcscpy(pw, L"-INF"); + } + else { + wcscpy(pw, L"-inf"); + } + } + else { + pw = wbuff - 4; + if (iswupper(format.conversion_char)) { + wcscpy(pw, L"INF"); + } + else { + wcscpy(pw, L"inf"); + } + } + + return pw; + + case 'N': + if (dec.sign) { + pw = wbuff - 5; + + if (iswupper(format.conversion_char)) { + wcscpy(pw, L"-NAN"); + } + else { + wcscpy(pw, L"-nan"); + } + } + else { + pw = wbuff - 4; + if (iswupper(format.conversion_char)) { + wcscpy(pw, L"NAN"); + } + else { + wcscpy(pw, L"nan"); + } + } + + return pw; + } + + dec.exponent += dec.sig.length - 1; + p = buff + 512; + *--p = 0; + + switch (format.conversion_char) + { + case L'g': + case L'G': + + if (dec.sig.length > format.precision) { + round_decimal(&dec, format.precision); + } + + if (dec.exponent < -4 || dec.exponent >= format.precision) + { + if (format.alternate_form) { + --format.precision; + } + else { + format.precision = dec.sig.length - 1; + } + + if (format.conversion_char == L'g') { + format.conversion_char = L'e'; + } + else { + format.conversion_char = L'E'; + } + + goto e_format; + } + + if (format.alternate_form) { + format.precision -= dec.exponent + 1; + } + else { + if ((format.precision = dec.sig.length - (dec.exponent + 1)) < 0) { + format.precision = 0; + } + } + + goto f_format; + + case L'e': + case L'E': + e_format: + + if (dec.sig.length > format.precision + 1) { + round_decimal(&dec, format.precision + 1); + } + + n = dec.exponent; + sign = '+'; + + if (n < 0) { + n = -n; + sign = '-'; + } + + for (digits = 0; n || digits < 2; ++digits) { + *--p = n % 10 + '0'; + n /= 10; + } + + *--p = sign; + *--p = format.conversion_char; + + if (buff - p + format.precision > 509) { + return 0; + } + + if (dec.sig.length < format.precision + 1) { + for (n = format.precision + 1 - dec.sig.length + 1; --n;) { + *--p = '0'; + } + } + + for (n = dec.sig.length, q = (char*)dec.sig.text + dec.sig.length; --n;) { + *--p = *--q; + } + + if (format.precision || format.alternate_form) { + *--p = radix_marker; + } + + *--p = *dec.sig.text; + + if (dec.sign) + *--p = '-'; + else if (format.sign_options == sign_always) + *--p = '+'; + else if (format.sign_options == space_holder) + *--p = ' '; + + break; + + case L'f': + case L'F': + f_format: + + if ((frac_digits = -dec.exponent + dec.sig.length - 1) < 0) + frac_digits = 0; + + if (frac_digits > format.precision) { + round_decimal(&dec, dec.sig.length - (frac_digits - format.precision)); + + if ((frac_digits = -dec.exponent + dec.sig.length - 1) < 0) + frac_digits = 0; + } + + if ((int_digits = dec.exponent + 1) < 0) + int_digits = 0; + + if (int_digits + frac_digits > 509) + return 0; + + q = (char *) dec.sig.text + dec.sig.length; + + for (digits = 0; digits < (format.precision - frac_digits); ++digits) + *--p = '0'; + + for (digits = 0; digits < frac_digits && digits < dec.sig.length; ++digits) + *--p = *--q; + + for (; digits < frac_digits; ++digits) + *--p = '0'; + + if (format.precision || format.alternate_form) + *--p = radix_marker; + + if (int_digits) { + for (digits = 0; digits < int_digits - dec.sig.length; ++digits) { + *--p = '0'; + } + + for (; digits < int_digits; ++digits) { + *--p = *--q; + } + } + else { + *--p = '0'; + } + + if (dec.sign) { + *--p = '-'; + } + else if (format.sign_options == sign_always) { + *--p = '+'; + } + else if (format.sign_options == space_holder) { + *--p = ' '; + } + + break; + } + + pw = wbuff - strlen(p) - 1; + mbstowcs(pw, p, strlen(p)); + return pw; +} + +int __wpformatter(void *(*WriteProc)(void *, const wchar_t *, size_t), void *WriteProcArg, const wchar_t * format_str, va_list arg) { + int num_chars, chars_written, field_width; + const wchar_t* format_ptr; + const wchar_t* curr_format; + print_format format; + long long_num; + long long long_long_num; + long double long_double_num; + wchar_t buff[512]; + wchar_t* buff_ptr; + wchar_t* string_end; + char* cstring_end; + wchar_t fill_char = L' '; + char* strptr; + + format_ptr = format_str; + chars_written = 0; + + while (*format_ptr) { + if (!(curr_format = wcschr(format_ptr, L'%'))) { + num_chars = wcslen(format_ptr); + chars_written += num_chars; + + if (num_chars && !(*WriteProc)(WriteProcArg, format_ptr, num_chars)) { + return -1; + } + + break; + } + + num_chars = curr_format - format_ptr; + chars_written += num_chars; + + if (num_chars && !(*WriteProc)(WriteProcArg, format_ptr, num_chars)) { + return -1; + } + + format_ptr = curr_format; + format_ptr = parse_format(format_ptr, (va_list*)arg, &format); + + switch (format.conversion_char) { + case L'd': + case L'i': + if (format.argument_options == long_argument) { + long_num = va_arg(arg, long); + } + else if (format.argument_options == long_long_argument) { + long_long_num = va_arg(arg, long long); + } + else if (format.argument_options == intmax_argument) { + long_long_num = va_arg(arg, intmax_t); + } + else if (format.argument_options == size_t_argument) { + long_num = va_arg(arg, size_t); + } + else if (format.argument_options == ptrdiff_argument) { + long_num = va_arg(arg, ptrdiff_t); + } + else { + long_num = va_arg(arg, int); + } + + if (format.argument_options == short_argument) { + long_num = (short)long_num; + } + + if ((format.argument_options == long_long_argument) || (format.argument_options == intmax_argument)) { + if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) { + goto conversion_error; + } + } + else { + if (!(buff_ptr = long2str(long_num, buff + 512, format))) { + goto conversion_error; + } + } + + num_chars = buff + 512 - 1 - buff_ptr; + break; + + case L'o': + case L'u': + case L'x': + case L'X': + if (format.argument_options == long_argument) { + long_num = va_arg(arg, unsigned long); + } + else if (format.argument_options == long_long_argument) { + long_long_num = va_arg(arg, long long); + } + else if (format.argument_options == intmax_argument) { + long_long_num = va_arg(arg, intmax_t); + } + else if (format.argument_options == size_t_argument) { + long_num = va_arg(arg, size_t); + } + else if (format.argument_options == ptrdiff_argument) { + long_num = va_arg(arg, ptrdiff_t); + } + else { + long_num = va_arg(arg, unsigned int); + } + + if (format.argument_options == short_argument) { + long_num = (unsigned short)long_num; + } + + if ((format.argument_options == long_long_argument) || (format.argument_options == intmax_argument)) { + if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) { + goto conversion_error; + } + } + else { + if (!(buff_ptr = long2str(long_num, buff + 512, format))) { + goto conversion_error; + } + } + + num_chars = buff + 512 - 1 - buff_ptr; + break; + + case L'f': + case L'F': + case L'e': + case L'E': + case L'g': + case L'G': + if (format.argument_options == long_double_argument) { + long_double_num = va_arg(arg, long double); + } + else { + long_double_num = va_arg(arg, double); + } + + if (!(buff_ptr = float2str(long_double_num, buff + 512, format))) { + goto conversion_error; + } + + num_chars = buff + 512 - 1 - buff_ptr; + break; + + case 'a': + case 'A': + if (format.argument_options == long_double_argument) { + long_double_num = va_arg(arg, long double); + } + else { + long_double_num = va_arg(arg, double); + } + + if (!(buff_ptr = double2hex(long_double_num, buff + 512, format))) { + goto conversion_error; + } + + num_chars = buff + 512 - 1 - buff_ptr; + break; + + case L's': + if (format.argument_options == wchar_argument) { + buff_ptr = va_arg(arg, wchar_t *); + + if (buff_ptr == 0) { + buff_ptr = L""; + } + + if (format.alternate_form) + { + num_chars = (unsigned char) *buff_ptr++; + + if (format.precision_specified && num_chars > format.precision) + num_chars = format.precision; + } + else if (format.precision_specified) + { + num_chars = format.precision; + + if ((string_end = (wchar_t *)wmemchr(buff_ptr, 0, num_chars)) != 0) { + num_chars = string_end - buff_ptr; + } + } + else + num_chars = wcslen(buff_ptr); + } + else { + strptr = va_arg(arg, char *); + if (strptr == 0) { + strptr = ""; + } + + if (format.alternate_form) { + num_chars = (unsigned char) *buff_ptr++; + + if (format.precision_specified && num_chars > format.precision) { + num_chars = format.precision; + } + } + else if (format.precision_specified) { + num_chars = format.precision; + + if ((cstring_end = (char *) memchr(strptr, 0, num_chars)) != 0) { + num_chars = cstring_end - strptr; + } + } + else + num_chars = strlen(strptr); + if ((num_chars = mbstowcs(buff, strptr, num_chars)) < 0) + goto conversion_error; + + buff_ptr = &buff[0]; + } + + break; + + case 'n': + buff_ptr = va_arg(arg, wchar_t *); + + switch (format.argument_options) { + case normal_argument: + *(int*)buff_ptr = chars_written; + break; + case short_argument: + *(short*)buff_ptr = chars_written; + break; + case long_argument: + *(long*)buff_ptr = chars_written; + break; + case intmax_argument: + *(intmax_t*)buff_ptr = chars_written; + break; + case size_t_argument: + *(size_t*)buff_ptr = chars_written; + break; + case ptrdiff_argument: + *(ptrdiff_t*)buff_ptr = chars_written; + break; + case long_long_argument: + *(long long*)buff_ptr = chars_written; + break; + } + + continue; + + case L'c': + buff_ptr = buff; + if (format.argument_options == wchar_argument) { + *buff_ptr = va_arg(arg, int); + num_chars = 1; + } + else { + char chint = va_arg(arg, int); + num_chars = mbtowc(buff, &chint, 1); + } + + break; + + case L'%': + buff_ptr = buff; + *buff_ptr = '%'; + num_chars = 1; + break; + + case 0xFFFF: + default: + conversion_error: + num_chars = wcslen(curr_format); + chars_written += num_chars; + + if (num_chars && !(*WriteProc)(WriteProcArg, curr_format, num_chars)) { + return -1; + } + + return chars_written; + break; + } + + field_width = num_chars; + + if (format.justification_options != left_justification) { + fill_char = (format.justification_options == zero_fill) ? L'0' : L' '; + + if (((*buff_ptr == L'+') || (*buff_ptr == L'-') || (*buff_ptr == L' ')) && (fill_char == L'0')) { + if ((*WriteProc)(WriteProcArg, buff_ptr, 1) == 0) { + return -1; + } + + ++buff_ptr; + num_chars--; + } + + while (field_width < format.field_width) { + if ((*WriteProc)(WriteProcArg, &fill_char, 1) == 0) { + return -1; + } + + ++field_width; + } + } + + if (num_chars && !(*WriteProc)(WriteProcArg, buff_ptr, num_chars)) { + return -1; + } + + if (format.justification_options == left_justification) { + while (field_width < format.field_width) { + wchar_t blank = L' '; + + if ((*WriteProc)(WriteProcArg, &blank, 1) == 0) { + return -1; + } + + ++field_width; + } + } + + chars_written += field_width; + } + + return chars_written; +} + +void* __wStringWrite(void *wosc, const wchar_t * buffer, size_t numchars) { + size_t tobewritten; + void* res; + __wOutStrCtrl * wOscp = (__wOutStrCtrl*)wosc; + tobewritten = ((wOscp->CharsWritten + numchars) <= wOscp->MaxCharCount) ? numchars : wOscp->MaxCharCount - wOscp->CharsWritten; + res = (void*)wmemcpy(wOscp->wCharStr + wOscp->CharsWritten, buffer, tobewritten); + wOscp->CharsWritten += tobewritten; + return res; +} + +inline int vswprintf(wchar_t *s, size_t n, const wchar_t *format, va_list arg) { + int count; + __wOutStrCtrl wosc; + wosc.wCharStr = s; + wosc.MaxCharCount = n; + wosc.CharsWritten = 0; + + count = __wpformatter(&__wStringWrite, &wosc, format, arg); + + if (count >= 0) { + if (count < n) { + s[count] = 0; + } + else { + s[n - 1] = 0; + count = -1; + } + } + + return count; +} + + +int swprintf(wchar_t *s, size_t n, const wchar_t *format, ...) { + va_list args; + va_start(args, format); + return vswprintf(s, n, format, args); +} From 599c950d8a8ca4fa1843deb0553b0331a1236904 Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Thu, 25 Sep 2025 21:04:29 -0400 Subject: [PATCH 19/25] wprintf --- src/MSL/wprintf.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/MSL/wprintf.c b/src/MSL/wprintf.c index 5538c7ef..6cf78dad 100644 --- a/src/MSL/wprintf.c +++ b/src/MSL/wprintf.c @@ -22,6 +22,11 @@ typedef long long intmax_t; #define PTRDIFF __typeof__((char*)0-(char*)0) typedef PTRDIFF ptrdiff_t; +inline long double fabsl(long double x) { + return __fabs((double)x); +} + + wchar_t* wcscpy(wchar_t *pDest, const wchar_t *pSrc); size_t strlen(const char *pStr); void* memchr(const void *, int, size_t); @@ -231,7 +236,7 @@ const wchar_t* parse_format(const wchar_t *format_string, va_list *arg, print_fo case L'x': case L'X': if (f.argument_options == long_double_argument) { - f.conversion_char = long_long_argument; + f.argument_options = long_long_argument; } if (!f.precision_specified) { @@ -319,7 +324,7 @@ const wchar_t* parse_format(const wchar_t *format_string, va_list *arg, print_fo case L'n': if (f.argument_options == long_double_argument) { - f.conversion_char = long_long_argument; + f.argument_options = long_long_argument; } break; From 4dfca9fb3f21eee1feab0e74823f15ecfba47f05 Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Fri, 26 Sep 2025 01:56:42 -0400 Subject: [PATCH 20/25] clean up various files --- config/RSPE01_01/symbols.txt | 26 +- include/MSL/limits.h | 3 + include/MSL/scanf.h | 6 + include/MSL/wchar.h | 1 - src/MSL/alloc.c | 38 +- src/MSL/ansi_fp.c | 3 +- src/MSL/printf.c | 1382 ++++++++++++++++++++++++++++++++++ src/MSL/scanf.c | 862 +++++++++++++++++++++ src/MSL/strtold.c | 635 ++++++++++++++++ 9 files changed, 2922 insertions(+), 34 deletions(-) create mode 100644 include/MSL/scanf.h create mode 100644 src/MSL/printf.c create mode 100644 src/MSL/scanf.c create mode 100644 src/MSL/strtold.c diff --git a/config/RSPE01_01/symbols.txt b/config/RSPE01_01/symbols.txt index ba0eb258..b6055209 100644 --- a/config/RSPE01_01/symbols.txt +++ b/config/RSPE01_01/symbols.txt @@ -14868,7 +14868,7 @@ lbl_8037B938 = .rodata:0x8037B938; // type:object size:0x10 data:byte __wctype_mapC = .rodata:0x8037B948; // type:object size:0x200 scope:global __wlower_mapC = .rodata:0x8037BB48; // type:object size:0x200 scope:global __wupper_mapC = .rodata:0x8037BD48; // type:object size:0x200 scope:global -lbl_8037BF48 = .rodata:0x8037BF48; // type:object size:0x8 +@stringBase0 = .rodata:0x8037BF48; // type:object size:0x8 data:string_table Zero = .rodata:0x8037BF50; // type:object size:0x10 scope:local bp = .rodata:0x8037BF60; // type:object size:0x10 scope:local ...rodata.0 = .rodata:0x8037BF60; // type:label scope:local @@ -17310,7 +17310,7 @@ __files = .data:0x80398798; // type:object size:0x50 scope:global __stdout_FILE = .data:0x803987E8; // type:object size:0x50 __stderr_FILE = .data:0x80398838; // type:object size:0x50 __file_terminator = .data:0x80398888; // type:object size:0x50 -jumptable_803988D8 = .data:0x803988D8; // type:object size:0x124 scope:local +@233 = .data:0x803988D8; // type:object size:0x124 scope:local gap_08_803989FC_data = .data:0x803989FC; // type:object size:0x4 scope:global pow_10$933 = .data:0x80398A00; // type:object size:0x40 scope:global __lconv = .data:0x80398A40; // type:object size:0x38 scope:global data:4byte @@ -17321,22 +17321,22 @@ _loc_mon_C = .data:0x80398B7C; // type:object size:0x34 scope:global _loc_num_C = .data:0x80398BB0; // type:object size:0x18 scope:global _loc_tim_C = .data:0x80398BC8; // type:object size:0x28 scope:global _current_locale = .data:0x80398BF0; // type:object size:0x48 scope:global -jumptable_80398C38 = .data:0x80398C38; // type:object size:0xE0 scope:local -jumptable_80398D18 = .data:0x80398D18; // type:object size:0x44 scope:local -jumptable_80398D5C = .data:0x80398D5C; // type:object size:0x84 scope:local -@2337 = .data:0x80398DE0; // type:object size:0x84 scope:local -@2720 = .data:0x80398E64; // type:object size:0x24 scope:local +@245 = .data:0x80398C38; // type:object size:0xE0 scope:local +@244 = .data:0x80398D18; // type:object size:0x44 scope:local +@323 = .data:0x80398D5C; // type:object size:0x84 scope:local +@399 = .data:0x80398DE0; // type:object size:0x84 scope:local +@1071 = .data:0x80398E64; // type:object size:0x24 scope:local jumptable_80398E88 = .data:0x80398E88; // type:object size:0xE0 scope:local jumptable_80398F68 = .data:0x80398F68; // type:object size:0x20 scope:local jumptable_80398F88 = .data:0x80398F88; // type:object size:0x20 scope:local jumptable_80398FA8 = .data:0x80398FA8; // type:object size:0x44 scope:local jumptable_80398FEC = .data:0x80398FEC; // type:object size:0x44 scope:local -jumptable_80399030 = .data:0x80399030; // type:object size:0xE0 scope:local -jumptable_80399110 = .data:0x80399110; // type:object size:0x44 scope:local -jumptable_80399154 = .data:0x80399154; // type:object size:0x84 scope:local -jumptable_803991D8 = .data:0x803991D8; // type:object size:0x84 scope:local -jumptable_8039925C = .data:0x8039925C; // type:object size:0x24 scope:local -lbl_80399280 = .data:0x80399280; // type:object size:0x58 +@197 = .data:0x80399030; // type:object size:0xE0 scope:local +@196 = .data:0x80399110; // type:object size:0x44 scope:local +@275 = .data:0x80399154; // type:object size:0x84 scope:local +@351 = .data:0x803991D8; // type:object size:0x84 scope:local +@1029 = .data:0x8039925C; // type:object size:0x24 scope:local +@wstringBase0 = .data:0x80399280; // type:object size:0x58 @43 = .data:0x803992D8; // type:object size:0x6C scope:local jumptable_80399348 = .data:0x80399348; // type:object size:0x1C scope:local jumptable_80399364 = .data:0x80399364; // type:object size:0x1C scope:local diff --git a/include/MSL/limits.h b/include/MSL/limits.h index 86ec85f3..f301a0fc 100644 --- a/include/MSL/limits.h +++ b/include/MSL/limits.h @@ -29,6 +29,9 @@ extern "C" { #define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL #define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL +#define DBL_MIN 2.2250738585072014E-308L +#define DBL_MAX 1.7976931348623157E+308L + #ifdef __cplusplus } #endif diff --git a/include/MSL/scanf.h b/include/MSL/scanf.h new file mode 100644 index 00000000..a4068394 --- /dev/null +++ b/include/MSL/scanf.h @@ -0,0 +1,6 @@ +#ifndef SCANF_H +#define SCANF_H + + + +#endif // SCANF_H \ No newline at end of file diff --git a/include/MSL/wchar.h b/include/MSL/wchar.h index 7d2c53e1..693adb95 100644 --- a/include/MSL/wchar.h +++ b/include/MSL/wchar.h @@ -12,7 +12,6 @@ extern "C" { #define WCHAR_MIN SHRT_MIN #define WCHAR_MAX USHRT_MAX -typedef unsigned short wchar_t; typedef wchar_t wint_t; #ifdef __cplusplus diff --git a/src/MSL/alloc.c b/src/MSL/alloc.c index ff9dae28..d15aaa2e 100644 --- a/src/MSL/alloc.c +++ b/src/MSL/alloc.c @@ -1,3 +1,5 @@ +#pragma exceptions on + void __sys_free(void* ptr); void* memset(void*, int, int); @@ -81,9 +83,6 @@ typedef struct mem_pool_obj { } mem_pool_obj; -mem_pool_obj __malloc_pool; -static int initialized = 0; - static void SubBlock_merge_next(SubBlock*, SubBlock**); static const unsigned long fix_pool_sizes[] = {4, 12, 20, 36, 52, 68}; @@ -223,7 +222,8 @@ inline static Block* __unlink(__mem_pool_obj* pool_obj, Block* bp) { return result; } -inline static void deallocate_from_var_pools(__mem_pool_obj* pool_obj, void* ptr) { +inline static void deallocate_from_var_pools(__mem_pool_obj* pool_obj, + void* ptr) { SubBlock* sb = SubBlock_from_pointer(ptr); SubBlock* _sb; @@ -293,6 +293,21 @@ void deallocate_from_fixed_pools(__mem_pool_obj* pool_obj, void* ptr, } } +inline void __init_pool_obj(__mem_pool* pool_obj) { + memset(pool_obj, 0, sizeof(__mem_pool_obj)); +} + +inline static __mem_pool* get_malloc_pool(void) { + static __mem_pool protopool; + static unsigned char init = 0; + if (!init) { + __init_pool_obj(&protopool); + init = 1; + } + + return &protopool; +} + inline void __pool_free(__mem_pool* pool, void* ptr) { __mem_pool_obj* pool_obj; unsigned long size; @@ -311,21 +326,6 @@ inline void __pool_free(__mem_pool* pool, void* ptr) { } } -inline void __init_pool_obj(__mem_pool* pool_obj) { - memset(pool_obj, 0, sizeof(__mem_pool_obj)); -} - -inline static __mem_pool* get_malloc_pool(void) { - static __mem_pool protopool; - static unsigned char init = 0; - if (!init) { - __init_pool_obj(&protopool); - init = 1; - } - - return &protopool; -} - void free(void* ptr) { __pool_free(get_malloc_pool(), ptr); } diff --git a/src/MSL/ansi_fp.c b/src/MSL/ansi_fp.c index 87109475..718b527c 100644 --- a/src/MSL/ansi_fp.c +++ b/src/MSL/ansi_fp.c @@ -1,6 +1,7 @@ #include "ansi_fp.h" #include "math_api.h" #include "float.h" +#include "limits.h" #pragma exceptions on @@ -711,7 +712,7 @@ double __dec2num(const decimal* d) { first_guess = ldexp(first_guess, exponent); if (__fpclassifyd(first_guess) == 2) { - first_guess = 1.7976931348623157E+308L; + first_guess = DBL_MAX; } { decimal feedback1, feedback2, difflow, diffhigh; diff --git a/src/MSL/printf.c b/src/MSL/printf.c new file mode 100644 index 00000000..f8d072b3 --- /dev/null +++ b/src/MSL/printf.c @@ -0,0 +1,1382 @@ +#include +#include "ansi_fp.h" +#include "string.h" + +#pragma exceptions on + +#define LDBL_MANT_DIG 24 +#define LDBL_MAX_EXP 128 +#define TARGET_FLOAT_BITS 32 +#define TARGET_FLOAT_BYTES (TARGET_FLOAT_BITS/8) +#define TARGET_FLOAT_MAX_EXP LDBL_MAX_EXP +#define TARGET_FLOAT_MANT_DIG LDBL_MANT_DIG +#define TARGET_FLOAT_IMPLICIT_J_BIT 1 +#define TARGET_FLOAT_MANT_BITS (TARGET_FLOAT_MANT_DIG - TARGET_FLOAT_IMPLICIT_J_BIT) +#define TARGET_FLOAT_EXP_BITS (TARGET_FLOAT_BITS - TARGET_FLOAT_MANT_BITS - 1) + +typedef long long intmax_t; + +#define PTRDIFF __typeof__((char*)0-(char*)0) +typedef PTRDIFF ptrdiff_t; + +size_t __fwrite(const void *pPtr, size_t memb_size, size_t num_memb, FILE *pFile); + +enum justification_options { + left_justification, + right_justification, + zero_fill +}; + +enum sign_options { + only_minus, + sign_always, + space_holder +}; + +enum argument_options { + normal_argument, + char_argument, + short_argument, + long_argument, + long_long_argument, + wchar_argument, + intmax_argument, + size_t_argument, + ptrdiff_argument, + long_double_argument +}; + +typedef struct { + unsigned char justification_options; // 0x0 + unsigned char sign_options; // 0x1 + unsigned char precision_specified; // 0x2 + unsigned char alternate_form; // 0x3 + unsigned char argument_options; // 0x4 + unsigned char conversion_char; // 0x5 + int field_width; // 0x8 + int precision; // 0xC +} print_format; + +typedef struct { + char* CharStr; + size_t MaxCharCount; + size_t CharsWritten; +} __OutStrCtrl; + +/*static*/ const char* parse_format(const char *format_string, va_list *arg, print_format *format) { + print_format f; + const char* s = format_string; + int c; + int flag_found; + f.justification_options = right_justification; + f.sign_options = only_minus; + f.precision_specified = 0; + f.alternate_form = 0; + f.argument_options = normal_argument; + f.field_width = 0; + f.precision = 0; + + if ((c = *++s) == '%') { + f.conversion_char = c; + *format = f; + return ((const char*)s + 1); + } + + for (;;) { + flag_found = 1; + + switch (c) { + case '-': + f.justification_options = left_justification; + break; + case '+': + f.sign_options = sign_always; + break; + case ' ': + if (f.sign_options != sign_always) { + f.sign_options = space_holder; + } + break; + case '#': + f.alternate_form = 1; + break; + case '0': + if (f.justification_options != left_justification) { + f.justification_options = zero_fill; + } + break; + default: + flag_found = 0; + break; + } + + if (flag_found) { + c = *++s; + } + else { + break; + } + } + + if (c == '*') { + if ((f.field_width = va_arg(*arg, int)) < 0) { + f.justification_options = left_justification; + f.field_width = -f.field_width; + } + + c = *++s; + } + else { + while (isdigit(c)) { + f.field_width = (f.field_width * 10) + (c - '0'); + c = *++s; + } + } + + if (f.field_width > 509) { + f.conversion_char = 0xFF; + *format = f; + return ((const char*)s + 1); + } + + if (c == '.') { + f.precision_specified = 1; + + if ((c = *++s) == '*') { + if ((f.precision = va_arg(*arg, int)) < 0) { + f.precision_specified = 0; + } + + c = *++s; + } + else { + while (isdigit(c)) { + f.precision = (f.precision * 10) + (c - '0'); + c = *++s; + } + } + } + + flag_found = 1; + + switch (c) { + case 'h': + f.argument_options = short_argument; + + if (s[1] == 'h') { + f.argument_options = char_argument; + c = *++s; + } + + break; + + case 'l': + f.argument_options = long_argument; + + if (s[1] == 'l') { + f.argument_options = long_long_argument; + c = *++s; + } + + break; + + case 'L': + f.argument_options = long_double_argument; + break; + case 'j': + f.argument_options = intmax_argument; + break; + case 't': + f.argument_options = ptrdiff_argument; + break; + case 'z': + f.argument_options = size_t_argument; + break; + default: + flag_found = 0; + break; + } + + if (flag_found) { + c = *++s; + } + + f.conversion_char = c; + + switch (c) { + case 'd': + case 'i': + case 'u': + case 'o': + case 'x': + case 'X': + if (f.argument_options == long_double_argument) { + f.conversion_char = 0xFF; + break; + } + + if (!f.precision_specified) { + f.precision = 1; + } + else if (f.justification_options == zero_fill) { + f.justification_options = right_justification; + } + break; + + case 'f': + case 'F': + if (f.argument_options == short_argument || f.argument_options == intmax_argument || f.argument_options == size_t_argument || f.argument_options == ptrdiff_argument || f.argument_options == long_long_argument) { + f.conversion_char = 0xFF; + break; + } + + if (!f.precision_specified) { + f.precision = 1; + } + break; + + case 'a': + case 'A': + if (!f.precision_specified) { + f.precision = 0xD; + } + + if (f.argument_options == short_argument || f.argument_options == intmax_argument || + f.argument_options == size_t_argument || f.argument_options == ptrdiff_argument || + f.argument_options == long_long_argument || f.argument_options == char_argument) { + f.conversion_char = 0xFF; + } + + break; + + case 'g': + case 'G': + if (!f.precision) { + f.precision = 1; + } + + case 'e': + case 'E': + if (f.argument_options == short_argument || f.argument_options == intmax_argument || f.argument_options == size_t_argument || f.argument_options == ptrdiff_argument || f.argument_options == long_long_argument || f.argument_options == char_argument) { + f.conversion_char = 0xFF; + break; + } + + if (!f.precision_specified) { + f.precision = 6; + } + break; + + case 'p': + f.conversion_char = 'x'; + f.alternate_form = 1; + f.argument_options = long_argument; + f.precision = 8; + break; + + case 'c': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } + else { + if (f.precision_specified || f.argument_options != normal_argument) { + f.conversion_char = 0xFF; + } + } + + break; + + case 's': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } + else { + if (f.argument_options != normal_argument) { + f.conversion_char = 0xFF; + } + } + + break; + + case 'n': + if (f.argument_options == long_double_argument) { + f.conversion_char = 0xFF; + } + + break; + + default: + f.conversion_char = 0xFF; + break; + } + + *format = f; + return ((const char*)s + 1); +} + +static char * long2str(long num, char * buff, print_format format) { + unsigned long unsigned_num, base; + char* p; + int n, digits; + int minus = 0; + unsigned_num = num; + minus = 0; + + p = buff; + *--p = 0; + digits = 0; + + if (!num && !format.precision && !(format.alternate_form && format.conversion_char == 'o')) { + return p; + } + + switch (format.conversion_char) { + case 'd': + case 'i': + base = 10; + + if (num < 0) { + if (num != 0x80000000) { + unsigned_num = -num; + } + + minus = 1; + } + break; + + case 'o': + base = 8; + format.sign_options = only_minus; + break; + + case 'u': + base = 10; + format.sign_options = only_minus; + break; + + case 'x': + case 'X': + base = 16; + format.sign_options = only_minus; + break; + } + + do { + n = unsigned_num % base; + unsigned_num /= base; + + if (n < 10) { + n += '0'; + } + else { + n -= 10; + + if (format.conversion_char == 'x') { + n += 'a'; + } + else { + n += 'A'; + } + } + + *--p = n; + ++digits; + } + while (unsigned_num != 0); + + if (base == 8 && format.alternate_form && *p != '0') { + *--p = '0'; + ++digits; + } + + if (format.justification_options == zero_fill) { + format.precision = format.field_width; + + if (minus || format.sign_options != only_minus) + --format.precision; + + if (base == 16 && format.alternate_form) + format.precision -= 2; + } + + if (buff - p + format.precision > 509) + return (0); + + while (digits < format.precision) { + *--p = '0'; + ++digits; + } + + if (base == 16 && format.alternate_form) { + *--p = format.conversion_char; + *--p = '0'; + } + + if (minus) { + *--p = '-'; + } + else if (format.sign_options == sign_always) { + *--p = '+'; + } + else if (format.sign_options == space_holder) { + *--p = ' '; + } + + return p; +} + +char* longlong2str(long long num, char *pBuf, print_format fmt) { + unsigned long long unsigned_num, base; + char* p; + int n, digits; + int minus = 0; + unsigned_num = num; + minus = 0; + p = pBuf; + *--p = 0; + digits = 0; + + if (!num && !fmt.precision && !(fmt.alternate_form && fmt.conversion_char == 'o')) { + return p; + } + + switch (fmt.conversion_char) { + case 'd': + case 'i': + base = 10; + + if (num < 0) { + if (num != 0x8000000000000000) { + unsigned_num = -num; + } + + minus = 1; + } + break; + case 'o': + base = 8; + fmt.sign_options = only_minus; + break; + case 'u': + base = 10; + fmt.sign_options = only_minus; + break; + case 'x': + case 'X': + base = 16; + fmt.sign_options = only_minus; + break; + } + + do { + n = unsigned_num % base; + unsigned_num /= base; + + if (n < 10) { + n += '0'; + } + else { + n -= 10; + if (fmt.conversion_char == 'x') { + n += 'a'; + } + else { + n += 'A'; + } + } + + *--p = n; + ++digits; + } while (unsigned_num != 0); + + if (base == 8 && fmt.alternate_form && *p != '0') { + *--p = '0'; + ++digits; + } + + if (fmt.justification_options == zero_fill) { + fmt.precision = fmt.field_width; + + if (minus || fmt.sign_options != only_minus) { + --fmt.precision; + } + + if (base == 16 && fmt.alternate_form) { + fmt.precision -= 2; + } + } + + if (pBuf - p + fmt.precision > 509) { + return 0; + } + + while (digits < fmt.precision) { + *--p = '0'; + ++digits; + } + + if (base == 16 && fmt.alternate_form) { + *--p = fmt.conversion_char; + *--p = '0'; + } + + if (minus) { + *--p = '-'; + } + else if (fmt.sign_options == sign_always) { + *--p = '+'; + } + else if (fmt.sign_options == space_holder) { + *--p = ' '; + } + + return p; +} + +char * double2hex(long double num, char * buff, print_format format) { + char *p; + unsigned char *q; + unsigned char working_byte; + long double ld; + int expbits, expmask; + unsigned snum; + long exp; + print_format exp_format; + int hex_precision; + int mantissa_bit; + decform form; + decimal dec; + int radix_marker; + + radix_marker = * (unsigned char *)(__lconv).decimal_point; + p = buff; + ld = num; + + if (format.precision > 509) { + return 0; + } + + form.style = (char)0; + form.digits = 0x20; + __num2dec(&form, num, &dec); + + if (fabsl(num) == 0.0) { + p = buff - 6; + strcpy(p, "0x0p0"); + return p; + } + + if (*dec.sig.text == 'I') { + if (dec.sign) { + p = buff - 5; + if (format.conversion_char == 'A') + strcpy(p, "-INF"); + else + strcpy(p, "-inf"); + } + else { + p = buff - 4; + if (format.conversion_char == 'A') + strcpy(p, "INF"); + else + strcpy(p, "inf"); + } + + return p; + } + else if (*dec.sig.text == 'N') { + if (dec.sign) { + p = buff - 5; + if (format.conversion_char == 'A') + strcpy(p, "-NAN"); + else + strcpy(p, "-nan"); + } + else { + p = buff - 4; + if (format.conversion_char == 'A') + strcpy(p, "NAN"); + else + strcpy(p, "nan"); + } + return p; + } + + exp_format.justification_options = 1; + exp_format.sign_options = 1; + exp_format.precision_specified = 0; + exp_format.alternate_form = 0; + exp_format.argument_options = 0; + exp_format.field_width = 0; + exp_format.precision = 1; + exp_format.conversion_char = 'd'; + + expbits = 11; + expmask = 0x7FF; + + snum = ((unsigned char *)&num)[0] << 25; + if (TARGET_FLOAT_EXP_BITS > 7) + snum |= ((unsigned char *)&num)[1] << 17; + if (TARGET_FLOAT_EXP_BITS > 15) + snum |= ((unsigned char *)&num)[2] << 9; + if (TARGET_FLOAT_EXP_BITS > 23) + snum |= ((unsigned char *)&num)[3] << 1; + + snum = (snum >> (32 - expbits)) & expmask; + exp = snum - 0x3FF; + + p = long2str(exp, buff, exp_format); + if (format.conversion_char == 'a') + *--p = 'p'; + else + *--p = 'P'; + q = (unsigned char *)# + + if (TARGET_FLOAT_IMPLICIT_J_BIT) { + mantissa_bit = (1 + expbits + format.precision * 4) - 1; + } + else { + mantissa_bit = (1 + expbits + format.precision * 4) - 4; + } + + for (hex_precision = format.precision; hex_precision >= 1; hex_precision--) { + if (mantissa_bit < 64) { + int mantissa_byte; + + mantissa_byte = mantissa_bit >> 3; + working_byte = (*(q + mantissa_byte)) >> (7 - (mantissa_bit & 7)); + + if ((mantissa_bit & ~7) != ((mantissa_bit - 4) & ~7)) { + working_byte |= ((*(q + (mantissa_byte - 1))) << 8) >> (7 - ((mantissa_bit) & 7)); + } + + if (!TARGET_FLOAT_IMPLICIT_J_BIT) { + if (mantissa_bit == 1 + expbits) { + *--p = radix_marker; + working_byte &= 0x1; + } + } + + if ((working_byte &= 0xF) < 10) { + working_byte += '0'; + } + else + if (format.conversion_char == 'a') { + working_byte += 'a' - 10; + } + else { + working_byte += 'A' - 10; + } + } + else { + working_byte = '0'; + } + + *--p = working_byte; + mantissa_bit -= 4; + } + + if (TARGET_FLOAT_IMPLICIT_J_BIT){ + if (format.precision || format.alternate_form) { + *--p = radix_marker; + } + + *--p = '1'; + } + + if (format.conversion_char == 'a') { + *--p = 'x'; + } + else { + *--p = 'X'; + } + + *--p = '0'; + + if (dec.sign) { + *--p = '-'; + } + else if (format.sign_options == 1) { + *--p = '+'; + } + else if (format.sign_options == 2) { + *--p = ' '; + } + + return p; +} + +void round_decimal(decimal *dec, int new_length) { + char c; + char* p; + int carry; + + if (new_length < 0) { +return_zero: + dec->exponent = 0; + dec->sig.length = 1; + *dec->sig.text = '0'; + return; + } + + if (new_length >= dec->sig.length) { + return; + } + + p = (char*)dec->sig.text + new_length + 1; + c = *--p - '0'; + + if (c == 5) { + char* q = &((char*)dec->sig.text)[dec->sig.length]; + + while (--q > p && *q == '0'); + carry = (q == p) ? p[-1] & 1 : 1; + } + else { + carry = (c > 5); + } + + while (new_length != 0) { + c = *--p - '0' + carry; + + if ((carry = (c > 9)) != 0 || c == 0) { + --new_length; + } + else { + *p = c + '0'; + break; + } + } + + if (carry != 0) { + dec->exponent += 1; + dec->sig.length = 1; + *dec->sig.text = '1'; + return; + } + else if (new_length == 0) { + goto return_zero; + } + + dec->sig.length = new_length; +} + +char* float2str(long double num, char *buff, print_format format) { + decimal dec; + decform form; + char* p; + char* q; + int n, digits, sign; + int int_digits, frac_digits; + int radix_marker; + + radix_marker = *(unsigned char*)__lconv.decimal_point; + + if (format.precision > 509) { + return 0; + } + + form.style = 0; + form.digits = 0x20; + __num2dec(&form, num, &dec); + p = (char*)dec.sig.text + dec.sig.length; + + while (dec.sig.length > 1 && *--p == '0') { + --dec.sig.length; + ++dec.exponent; + } + + switch (*dec.sig.text) { + case '0': + dec.exponent = 0; + break; + case 'I': + if (num < 0) { + p = buff - 5; + + if (isupper(format.conversion_char)) { + strcpy(p, "-INF"); + } + else { + strcpy(p, "-inf"); + } + } + else { + p = buff - 4; + if (isupper(format.conversion_char)) { + strcpy(p, "INF"); + } + else { + strcpy(p, "inf"); + } + } + + return p; + + case 'N': + if (dec.sign) { + p = buff - 5; + + if (isupper(format.conversion_char)) { + strcpy(p, "-NAN"); + } + else { + strcpy(p, "-nan"); + } + } + else { + p = buff - 4; + if (isupper(format.conversion_char)) { + strcpy(p, "NAN"); + } + else { + strcpy(p, "nan"); + } + } + + return p; + } + + dec.exponent += dec.sig.length - 1; + p = buff; + *--p = 0; + + switch (format.conversion_char) + { + case 'g': + case 'G': + + if (dec.sig.length > format.precision) { + round_decimal(&dec, format.precision); + } + + if (dec.exponent < -4 || dec.exponent >= format.precision) + { + if (format.alternate_form) { + --format.precision; + } + else { + format.precision = dec.sig.length - 1; + } + + if (format.conversion_char == 'g') { + format.conversion_char = 'e'; + } + else { + format.conversion_char = 'E'; + } + + goto e_format; + } + + if (format.alternate_form) { + format.precision -= dec.exponent + 1; + } + else { + if ((format.precision = dec.sig.length - (dec.exponent + 1)) < 0) { + format.precision = 0; + } + } + + goto f_format; + + case 'e': + case 'E': + e_format: + + if (dec.sig.length > format.precision + 1) { + round_decimal(&dec, format.precision + 1); + } + + n = dec.exponent; + sign = '+'; + + if (n < 0) { + n = -n; + sign = '-'; + } + + for (digits = 0; n || digits < 2; ++digits) { + *--p = n % 10 + '0'; + n /= 10; + } + + *--p = sign; + *--p = format.conversion_char; + + if (buff - p + format.precision > 509) { + return 0; + } + + if (dec.sig.length < format.precision + 1) { + for (n = format.precision + 1 - dec.sig.length + 1; --n;) { + *--p = '0'; + } + } + + for (n = dec.sig.length, q = (char*)dec.sig.text + dec.sig.length; --n;) { + *--p = *--q; + } + + if (format.precision || format.alternate_form) { + *--p = radix_marker; + } + + *--p = *dec.sig.text; + + if (dec.sign) + *--p = '-'; + else if (format.sign_options == sign_always) + *--p = '+'; + else if (format.sign_options == space_holder) + *--p = ' '; + + break; + + case 'f': + case 'F': + f_format: + + if ((frac_digits = -dec.exponent + dec.sig.length - 1) < 0) + frac_digits = 0; + + if (frac_digits > format.precision) { + round_decimal(&dec, dec.sig.length - (frac_digits - format.precision)); + + if ((frac_digits = -dec.exponent + dec.sig.length - 1) < 0) + frac_digits = 0; + } + + if ((int_digits = dec.exponent + 1) < 0) + int_digits = 0; + + if (int_digits + frac_digits > 509) + return 0; + + q = (char *) dec.sig.text + dec.sig.length; + + for (digits = 0; digits < (format.precision - frac_digits); ++digits) + *--p = '0'; + + for (digits = 0; digits < frac_digits && digits < dec.sig.length; ++digits) + *--p = *--q; + + for (; digits < frac_digits; ++digits) + *--p = '0'; + + if (format.precision || format.alternate_form) + *--p = radix_marker; + + if (int_digits) { + for (digits = 0; digits < int_digits - dec.sig.length; ++digits) { + *--p = '0'; + } + + for (; digits < int_digits; ++digits) { + *--p = *--q; + } + } + else { + *--p = '0'; + } + + if (dec.sign) { + *--p = '-'; + } + else if (format.sign_options == sign_always) { + *--p = '+'; + } + else if (format.sign_options == space_holder) { + *--p = ' '; + } + + break; + } + + return p; +} + +int __pformatter(void *(*WriteProc)(void *, const char *, size_t), void *WriteProcArg, const char * format_str, va_list arg) { + int num_chars, chars_written, field_width; + const char* format_ptr; + const char* curr_format; + print_format format; + long long_num; + long long long_long_num; + long double long_double_num; + char buff[512]; + char* buff_ptr; + char* string_end; + char fill_char = ' '; + + format_ptr = format_str; + chars_written = 0; + + while (*format_ptr) { + if (!(curr_format = strchr(format_ptr, '%'))) { + num_chars = strlen(format_ptr); + chars_written += num_chars; + + if (num_chars && !(*WriteProc)(WriteProcArg, format_ptr, num_chars)) { + return -1; + } + + break; + } + + num_chars = curr_format - format_ptr; + chars_written += num_chars; + + if (num_chars && !(*WriteProc)(WriteProcArg, format_ptr, num_chars)) { + return -1; + } + + format_ptr = curr_format; + format_ptr = parse_format(format_ptr, (va_list*)arg, &format); + + switch (format.conversion_char) { + case 'd': + case 'i': + if (format.argument_options == long_argument) { + long_num = va_arg(arg, long); + } + else if (format.argument_options == long_long_argument) { + long_long_num = va_arg(arg, long long); + } + else if (format.argument_options == intmax_argument) { + long_long_num = va_arg(arg, intmax_t); + } + else if (format.argument_options == size_t_argument) { + long_num = va_arg(arg, size_t); + } + else if (format.argument_options == ptrdiff_argument) { + long_num = va_arg(arg, ptrdiff_t); + } + else { + long_num = va_arg(arg, int); + } + + if (format.argument_options == short_argument) { + long_num = (short)long_num; + } + + if (format.argument_options == char_argument) { + long_num = (signed char)long_num; + } + + if ((format.argument_options == long_long_argument) || (format.argument_options == intmax_argument)) { + if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) { + goto conversion_error; + } + } + else { + if (!(buff_ptr = long2str(long_num, buff + 512, format))) { + goto conversion_error; + } + } + + num_chars = buff + 512 - 1 - buff_ptr; + break; + + case 'o': + case 'u': + case 'x': + case 'X': + if (format.argument_options == long_argument) { + long_num = va_arg(arg, unsigned long); + } + else if (format.argument_options == long_long_argument) { + long_long_num = va_arg(arg, long long); + } + else if (format.argument_options == intmax_argument) { + long_long_num = va_arg(arg, intmax_t); + } + else if (format.argument_options == size_t_argument) { + long_num = va_arg(arg, size_t); + } + else if (format.argument_options == ptrdiff_argument) { + long_num = va_arg(arg, ptrdiff_t); + } + else { + long_num = va_arg(arg, unsigned int); + } + + if (format.argument_options == short_argument) { + long_num = (unsigned short)long_num; + } + + if (format.argument_options == char_argument) { + long_num = (unsigned char)long_num; + } + + if ((format.argument_options == long_long_argument) || (format.argument_options == intmax_argument)) { + if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) { + goto conversion_error; + } + } + else { + if (!(buff_ptr = long2str(long_num, buff + 512, format))) { + goto conversion_error; + } + } + + num_chars = buff + 512 - 1 - buff_ptr; + break; + + case 'f': + case 'F': + case 'e': + case 'E': + case 'g': + case 'G': + if (format.argument_options == long_double_argument) { + long_double_num = va_arg(arg, long double); + } + else { + long_double_num = va_arg(arg, double); + } + + if (!(buff_ptr = float2str(long_double_num, buff + 512, format))) { + goto conversion_error; + } + + num_chars = buff + 512 - 1 - buff_ptr; + break; + + case 'a': + case 'A': + if (format.argument_options == long_double_argument) { + long_double_num = va_arg(arg, long double); + } + else { + long_double_num = va_arg(arg, double); + } + + if (!(buff_ptr = double2hex(long_double_num, buff + 512, format))) { + goto conversion_error; + } + + num_chars = buff + 512 - 1 - buff_ptr; + break; + + case 's': + if (format.argument_options == wchar_argument) { + wchar_t* wcs_ptr = va_arg(arg, wchar_t*); + + if (wcs_ptr == 0) { + wcs_ptr = L""; + } + + if ((num_chars = wcstombs(buff, wcs_ptr, sizeof(buff))) < 0) { + goto conversion_error; + } + + buff_ptr = &buff[0]; + } + else { + buff_ptr = va_arg(arg, char *); + } + + if (buff_ptr == 0) { + buff_ptr = ""; + } + + if (format.alternate_form) { + num_chars = (unsigned char)*buff_ptr++; + + if (format.precision_specified && num_chars > format.precision) { + num_chars = format.precision; + } + } + else if (format.precision_specified) { + num_chars = format.precision; + + if ((string_end = (char*)memchr(buff_ptr, 0, num_chars)) != 0) { + num_chars = string_end - buff_ptr; + } + } + else { + num_chars = strlen(buff_ptr); + } + + break; + + case 'n': + buff_ptr = va_arg(arg, char *); + + switch (format.argument_options) { + case normal_argument: + *(int*)buff_ptr = chars_written; + break; + case short_argument: + *(short*)buff_ptr = chars_written; + break; + case long_argument: + *(long*)buff_ptr = chars_written; + break; + case intmax_argument: + *(intmax_t*)buff_ptr = chars_written; + break; + case size_t_argument: + *(size_t*)buff_ptr = chars_written; + break; + case ptrdiff_argument: + *(ptrdiff_t*)buff_ptr = chars_written; + break; + case long_long_argument: + *(long long*)buff_ptr = chars_written; + break; + } + + continue; + + case 'c': + buff_ptr = buff; + *buff_ptr = va_arg(arg, int); + num_chars = 1; + break; + + case '%': + buff_ptr = buff; + *buff_ptr = '%'; + num_chars = 1; + break; + + case 0xFF: + default: + conversion_error: + num_chars = strlen(curr_format); + chars_written += num_chars; + + if (num_chars && !(*WriteProc)(WriteProcArg, curr_format, num_chars)) { + return -1; + } + + return chars_written; + break; + } + + field_width = num_chars; + + if (format.justification_options != left_justification) { + fill_char = (format.justification_options == zero_fill) ? '0' : ' '; + + if (((*buff_ptr == '+') || (*buff_ptr == '-') || (*buff_ptr == ' ')) && (fill_char == '0')) { + if ((*WriteProc)(WriteProcArg, buff_ptr, 1) == 0) { + return -1; + } + + ++buff_ptr; + num_chars--; + } + + while (field_width < format.field_width) { + if ((*WriteProc)(WriteProcArg, &fill_char, 1) == 0) { + return -1; + } + + ++field_width; + } + } + + if (num_chars && !(*WriteProc)(WriteProcArg, buff_ptr, num_chars)) { + return -1; + } + + if (format.justification_options == left_justification) { + while (field_width < format.field_width) { + char blank = ' '; + + if ((*WriteProc)(WriteProcArg, &blank, 1) == 0) { + return -1; + } + + ++field_width; + } + } + + chars_written += field_width; + } + + return chars_written; +} + +void* __FileWrite(void *pFile, const char *pBuffer, size_t char_num) { + return (__fwrite(pBuffer, 1, char_num, (FILE*)pFile) == char_num ? pFile : 0); +} + +void* __StringWrite(void *pCtrl, const char *pBuffer, size_t char_num) { + size_t chars; + void* res; + __OutStrCtrl* ctrl = (__OutStrCtrl*)pCtrl; + + chars = ((ctrl->CharsWritten + char_num) <= ctrl->MaxCharCount) ? char_num : ctrl->MaxCharCount - ctrl->CharsWritten; + res = (void*)memcpy(ctrl->CharStr + ctrl->CharsWritten, pBuffer, chars); + ctrl->CharsWritten += chars; + return (void*)1; +} + +int fprintf(FILE *pFile, const char *format, ...) { + int res; + + if (fwide(pFile, -1) >= 0) { + return -1; + } + + { + va_list args; + va_start(args, format); + res = __pformatter(&__FileWrite, (void*)pFile, format, args); + return res; + } +} + +int vsnprintf(char *s, size_t n, const char *format, va_list arg) { + int end; + __OutStrCtrl osc; + osc.CharStr = s; + osc.MaxCharCount = n; + osc.CharsWritten = 0; + + end = __pformatter(&__StringWrite, &osc, format, arg); + + if (s) { + if (end < n) { + s[end] = '\0'; + } + else { + if (n > 0) { + s[n - 1] = '\0'; + } + } + } + + return end; +} + +int vsprintf(char *s, const char *format, va_list arg) { + return vsnprintf(s, 0xFFFFFFFF, format, arg); +} + +int vprintf(const char *pFormat, va_list arg) { + int ret; + + if (fwide(stdout, -1) >= 0) { + return -1; + } + + ret = __pformatter(&__FileWrite, (void*)stdout, pFormat, arg); + return ret; +} + +int snprintf(char *s, size_t n, const char *format, ...) { + va_list args; + va_start(args, format); + return vsnprintf(s, n, format, args); +} + +int sprintf(char *s, const char *format, ...) { + va_list args; + va_start(args, format); + return vsnprintf(s, 0xFFFFFFFF, format, args); +} diff --git a/src/MSL/scanf.c b/src/MSL/scanf.c new file mode 100644 index 00000000..0fb4cf89 --- /dev/null +++ b/src/MSL/scanf.c @@ -0,0 +1,862 @@ +#include "limits.h" +#include "stdarg.h" +#include "stdio_api.h" +#include "ctype.h" + +#include + +#pragma exceptions on + +enum argument_options { + normal_argument, + char_argument, + short_argument, + long_argument, + intmax_argument, + size_t_argument, + ptrdiff_argument, + long_long_argument, + double_argument, + long_double_argument, + wchar_argument +}; + +typedef long long intmax_t; +#define PTRDIFF __typeof__((char*)0 - (char*)0) +typedef PTRDIFF ptrdiff_t; + +#define conversion_buff_size 512 +#define conversion_max 509 +#define bad_conversion 0xFF +typedef size_t rsize_t; + +#define EOF -1L + +typedef unsigned char char_map[32]; + +extern long double __strtold(int max_width, int (*ReadProc)(void*, int, int), + void* ReadProcArg, int* chars_scanned, + int* overflow); +extern unsigned long long __strtoull(int base, int max_width, + int (*ReadProc)(void*, int, int), + void* ReadProcArg, int* chars_scanned, + int* negative, int* overflow); +extern unsigned long __strtoul(int base, int max_width, + int (*ReadProc)(void*, int, int), + void* ReadProcArg, int* chars_scanned, + int* negative, int* overflow); + +int mbtowc(wchar_t* pDest, const char* s, size_t num); + +typedef struct { + unsigned char suppress_assignment; + unsigned char field_width_specified; + unsigned char argument_options; + unsigned char conversion_char; + int field_width; + char_map char_set; +} scan_format; + +#define set_char_map(map, ch) map[(unsigned char)ch >> 3] |= (1 << (ch & 7)) +#define tst_char_map(map, ch) (map[(unsigned char)ch >> 3] & (1 << (ch & 7))) + +static const char* parse_format(const char* format_string, + scan_format* format) { + const char* s = format_string; + int c; + int invert; + + int flag_found; + + scan_format f = {0, 0, normal_argument, 0, INT_MAX, {0}}; + + if ((c = *++s) == '%') { + f.conversion_char = c; + *format = f; + return ((const char*)s + 1); + } + + if (c == '*') { + f.suppress_assignment = 1; + c = *++s; + } + + if (isdigit(c)) { + f.field_width = 0; + + do { + f.field_width = (f.field_width * 10) + (c - '0'); + c = *++s; + } while (isdigit(c)); + + if (f.field_width == 0) { + f.conversion_char = 0xFF; + *format = f; + return ((const char*)s + 1); + } + + f.field_width_specified = 1; + } + + flag_found = 1; + + switch (c) { + case 'h': + f.argument_options = short_argument; + + if (s[1] == 'h') { + f.argument_options = char_argument; + c = *++s; + } + + break; + case 'l': + f.argument_options = long_argument; + + if (s[1] == 'l') { + f.argument_options = long_long_argument; + c = *++s; + } + + break; + case 'L': + f.argument_options = long_double_argument; + break; + + case 'j': + f.argument_options = intmax_argument; + break; + case 'z': + f.argument_options = size_t_argument; + break; + case 't': + f.argument_options = ptrdiff_argument; + break; + default: + flag_found = 0; + } + + if (flag_found) { + c = *++s; + } + + f.conversion_char = c; + + switch (c) { + case 'd': + case 'i': + case 'u': + case 'o': + case 'x': + case 'X': + if (f.argument_options == long_double_argument) { + f.conversion_char = 0xFF; + break; + } + + break; + + case 'a': + case 'A': + case 'f': + case 'F': + case 'e': + case 'E': + case 'g': + case 'G': + if (f.argument_options == char_argument || + f.argument_options == short_argument || + f.argument_options == intmax_argument || + f.argument_options == size_t_argument || + f.argument_options == ptrdiff_argument || + f.argument_options == long_long_argument) { + f.conversion_char = 0xFF; + break; + } + + if (f.argument_options == long_argument) { + f.argument_options = double_argument; + } + + break; + + case 'p': + f.argument_options = long_argument; + f.conversion_char = 'x'; + break; + + case 'c': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } else { + if (f.argument_options != normal_argument) { + f.conversion_char = 0xFF; + } + } + + break; + + case 's': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } else { + if (f.argument_options != normal_argument) { + f.conversion_char = 0xFF; + } + } + + { + int i; + unsigned char* p; + + for (i = sizeof(f.char_set), p = f.char_set; i; --i) { + *p++ = 0xFF; + } + + f.char_set[1] = 0xC1; + f.char_set[4] = 0xFE; + } + + break; + + case 'n': + break; + + case '[': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } else { + if (f.argument_options != normal_argument) { + f.conversion_char = 0xFF; + } + } + + c = *++s; + invert = 0; + + if (c == '^') { + invert = 1; + c = *++s; + } + + if (c == ']') { + set_char_map(f.char_set, ']'); + c = *++s; + } + + while (c && c != ']') { + int d; + set_char_map(f.char_set, c); + + if (*(s + 1) == '-' && (d = *(s + 2)) != 0 && d != ']') { + while (++c <= d) { + set_char_map(f.char_set, c); + } + + c = *(s += 3); + } else { + c = *++s; + } + } + + if (!c) { + f.conversion_char = 0xFF; + break; + } + + if (invert) { + int i; + unsigned char* p; + + for (i = sizeof(f.char_set), p = f.char_set; i; --i, ++p) { + *p = ~*p; + } + + break; + } + + break; + default: + f.conversion_char = 0xFF; + break; + } + + *format = f; + return ((const char*)s + 1); +} + +int __StringRead(void* pPtr, int ch, int act) { + char ret; + __InStrCtrl* Iscp = (__InStrCtrl*)pPtr; + + switch (act) { + case __GetAChar: + ret = *(Iscp->NextChar); + + if (ret == '\0') { + Iscp->NullCharDetected = 1; + return -1; + } else { + Iscp->NextChar++; + return (unsigned char)ret; + } + + case __UngetAChar: + if (Iscp->NullCharDetected == 0) { + Iscp->NextChar--; + } else { + Iscp->NullCharDetected = 0; + } + + return ch; + + case __TestForError: + return Iscp->NullCharDetected; + } + + return 0; +} + +static int __sformatter(int (*ReadProc)(void*, int, int), void* ReadProcArg, + const char* format_str, va_list arg, int is_secure) { + int num_chars, chars_read, items_assigned, conversions; + int base, negative, overflow; + int rval; + const char* format_ptr; + char format_char; + char c; + scan_format format; + long long_num; + unsigned long u_long_num; + long long long_long_num = 0; + unsigned long long u_long_long_num; + long double long_double_num; + char* arg_ptr; + int elem_valid; + size_t elem_maxsize; + int match_failure = 0; + int terminate = 0; + + format_ptr = format_str; + chars_read = 0; + items_assigned = 0; + conversions = 0; + + while (!terminate && (format_char = *format_ptr) != 0) { + if (isspace(format_char)) { + do { + format_char = *++format_ptr; + } while (isspace(format_char)); + + if (!match_failure) { + while (isspace(c = (*ReadProc)(ReadProcArg, 0, __GetAChar))) { + ++chars_read; + } + + (*ReadProc)(ReadProcArg, c, __UngetAChar); + } + continue; + } + + if ((format_char != '%') && (!match_failure)) { + if ((c = (*ReadProc)(ReadProcArg, 0, __GetAChar)) != + (unsigned char)format_char) { + (*ReadProc)(ReadProcArg, c, __UngetAChar); + if (!is_secure) { + goto exit; + } else { + match_failure = 1; + ++format_ptr; + continue; + } + } + + ++chars_read; + ++format_ptr; + + continue; + } + + format_ptr = parse_format(format_ptr, &format); + if (!format.suppress_assignment && format.conversion_char != '%') { + arg_ptr = va_arg(arg, char*); + } else { + arg_ptr = 0; + } + + if ((format.conversion_char != 'n') && (!match_failure) && + (*ReadProc)(ReadProcArg, 0, __TestForError)) { + if (!is_secure) { + goto exit; + } else { + match_failure = 1; + } + } + + switch (format.conversion_char) { + case 'd': + base = 10; + goto signed_int; + + case 'i': + base = 0; + + signed_int: + if (match_failure) { + long_num = 0; + long_long_num = 0; + } else { + if ((format.argument_options == long_long_argument) || + (format.argument_options == intmax_argument)) { + u_long_long_num = __strtoull( + base, format.field_width, ReadProc, ReadProcArg, + &num_chars, &negative, &overflow); + } else { + u_long_num = __strtoul(base, format.field_width, ReadProc, + ReadProcArg, &num_chars, &negative, + &overflow); + } + + if (!num_chars) { + if (!is_secure) { + goto exit; + } else { + match_failure = 1; + long_num = 0; + long_long_num = 0; + goto signed_int_assign; + } + } + + chars_read += num_chars; + + if ((format.argument_options == long_long_argument) || + (format.argument_options == intmax_argument)) { + long_long_num = + (negative ? -u_long_long_num : u_long_long_num); + } else { + long_num = (negative ? -u_long_num : u_long_num); + } + } + + signed_int_assign: + if (arg_ptr) { + switch (format.argument_options) { + case normal_argument: + *(int*)arg_ptr = long_num; + break; + case char_argument: + *(signed char*)arg_ptr = long_num; + break; + case short_argument: + *(short*)arg_ptr = long_num; + break; + case long_argument: + *(long*)arg_ptr = long_num; + break; + case intmax_argument: + *(intmax_t*)arg_ptr = long_long_num; + break; + case size_t_argument: + *(size_t*)arg_ptr = long_num; + break; + case ptrdiff_argument: + *(ptrdiff_t*)arg_ptr = long_num; + break; + case long_long_argument: + *(long long*)arg_ptr = long_long_num; + break; + } + if (!match_failure) { + ++items_assigned; + } + } + + ++conversions; + break; + + case 'o': + base = 8; + goto unsigned_int; + + case 'u': + base = 10; + goto unsigned_int; + + case 'x': + case 'X': + base = 16; + + unsigned_int: + + if (match_failure) { + u_long_num = 0; + u_long_long_num = 0; + } else { + if ((format.argument_options == long_long_argument) || + (format.argument_options == intmax_argument)) { + u_long_long_num = __strtoull( + base, format.field_width, ReadProc, ReadProcArg, + &num_chars, &negative, &overflow); + } else { + u_long_num = __strtoul(base, format.field_width, ReadProc, + ReadProcArg, &num_chars, &negative, + &overflow); + } + + if (!num_chars) { + if (!is_secure) { + goto exit; + } else { + match_failure = 1; + u_long_num = 0; + u_long_long_num = 0; + goto unsigned_int_assign; + } + } + + chars_read += num_chars; + + if (negative) + if (format.argument_options == long_long_argument) + u_long_long_num = -u_long_long_num; + else + + u_long_num = -u_long_num; + } + + unsigned_int_assign: + if (arg_ptr) { + switch (format.argument_options) { + case normal_argument: + *(unsigned int*)arg_ptr = u_long_num; + break; + case char_argument: + *(unsigned char*)arg_ptr = u_long_num; + break; + case short_argument: + *(unsigned short*)arg_ptr = u_long_num; + break; + case long_argument: + *(unsigned long*)arg_ptr = u_long_num; + break; + case intmax_argument: + *(intmax_t*)arg_ptr = u_long_long_num; + break; + case size_t_argument: + *(size_t*)arg_ptr = u_long_num; + break; + case ptrdiff_argument: + *(ptrdiff_t*)arg_ptr = u_long_num; + break; + case long_long_argument: + *(unsigned long long*)arg_ptr = u_long_long_num; + break; + } + + if (!match_failure) { + ++items_assigned; + } + } + + ++conversions; + + break; + + case 'a': + case 'A': + case 'f': + case 'F': + case 'e': + case 'E': + case 'g': + case 'G': + flt: + if (match_failure) { + long_double_num = NAN; + } else { + long_double_num = __strtold(format.field_width, ReadProc, + ReadProcArg, &num_chars, &overflow); + + if (!num_chars) { + if (!is_secure) { + goto exit; + } else { + match_failure = 1; + long_double_num = NAN; + goto assign_float; + } + } + + chars_read += num_chars; + } + + assign_float: + if (arg_ptr) { + switch (format.argument_options) { + case normal_argument: + *(float*)arg_ptr = long_double_num; + break; + case double_argument: + *(double*)arg_ptr = long_double_num; + break; + case long_double_argument: + *(long double*)arg_ptr = long_double_num; + break; + } + + if (!match_failure) { + ++items_assigned; + } + } + + ++conversions; + + break; + case 'c': + if (!format.field_width_specified) { + format.field_width = 1; + } + + if (arg_ptr) { + if (is_secure) { + elem_valid = 1; + elem_maxsize = va_arg(arg, rsize_t); + } + + num_chars = 0; + + if (match_failure) { + if (elem_maxsize > 0) { + *arg_ptr = 0; + } + continue; + } else { + char* arg_start = arg_ptr; + while (format.field_width-- && + (!is_secure || + ((elem_valid = (elem_maxsize > num_chars)) != 0)) && + ((rval = ((*ReadProc)(ReadProcArg, 0, + __GetAChar))) != EOF)) { + c = rval; + if (format.argument_options == wchar_argument) { + mbtowc(((wchar_t*)arg_ptr), (char*)(&c), 1); + arg_ptr += 1; + } else { + *arg_ptr++ = c; + } + ++num_chars; + } + + c = rval; + if (!num_chars || (is_secure && !elem_valid)) { + if (!is_secure) { + goto exit; + } else { + match_failure = 1; + if (elem_maxsize > 0) { + *arg_start = 0; + } + continue; + } + } + + chars_read += num_chars; + ++items_assigned; + } + } else { + num_chars = 0; + + while (format.field_width-- && + ((rval = ((*ReadProc)(ReadProcArg, 0, __GetAChar))) != + EOF)) { + c = rval; + ++num_chars; + } + c = rval; + if (!num_chars) { + goto exit; + } + } + + ++conversions; + break; + + case '%': + if (match_failure) { + continue; + } else { + while (isspace(c = (*ReadProc)(ReadProcArg, 0, __GetAChar))) + ++chars_read; + + if (c != '%') { + (*ReadProc)(ReadProcArg, c, __UngetAChar); + if (!is_secure) { + goto exit; + } else { + match_failure = 1; + continue; + } + } + + ++chars_read; + } + break; + + case 's': + if (!match_failure) { + c = (*ReadProc)(ReadProcArg, 0, __GetAChar); + while (isspace(c)) { + ++chars_read; + c = (*ReadProc)(ReadProcArg, 0, __GetAChar); + } + + (*ReadProc)(ReadProcArg, c, __UngetAChar); + } + case '[': + if (arg_ptr) { + if (is_secure) { + elem_valid = 1; + elem_maxsize = va_arg(arg, rsize_t) - 1; + } + + num_chars = 0; + + if (match_failure) { + if (elem_maxsize > 0) { + *arg_ptr = 0; + } + continue; + } else { + char* arg_start = arg_ptr; + + while ( + format.field_width-- && + (!is_secure || + ((elem_valid = (elem_maxsize >= num_chars)) != 0)) && + ((rval = ((*ReadProc)(ReadProcArg, 0, __GetAChar))) != + EOF)) { + c = rval; + + if (!tst_char_map(format.char_set, c)) { + break; + } + + if (format.argument_options == wchar_argument) { + mbtowc(((wchar_t*)arg_ptr), (char*)&c, 1); + arg_ptr = (char*)((wchar_t*)arg_ptr + 1); + } else { + *arg_ptr++ = c; + } + ++num_chars; + } + c = rval; + + if (!num_chars || (is_secure && !elem_valid)) { + (*ReadProc)(ReadProcArg, c, __UngetAChar); + if (!is_secure) { + goto exit; + } else { + match_failure = 1; + if (elem_maxsize > 0) { + *arg_start = 0; + } + continue; + } + } + + chars_read += num_chars; + + if (format.argument_options == wchar_argument) { + *(wchar_t*)arg_ptr = L'\0'; + } else { + *arg_ptr = 0; + } + + ++items_assigned; + } + } else { + num_chars = 0; + + while (format.field_width-- && + ((rval = ((*ReadProc)(ReadProcArg, 0, __GetAChar))) != + EOF)) { + c = rval; + if (!tst_char_map(format.char_set, c)) { + break; + } + + ++num_chars; + } + c = rval; + + if (!num_chars) { + (*ReadProc)(ReadProcArg, c, __UngetAChar); + break; + } + chars_read += num_chars; + } + + if (format.field_width >= 0) { + (*ReadProc)(ReadProcArg, c, __UngetAChar); + } + + ++conversions; + break; + + case 'n': + if (arg_ptr) { + switch (format.argument_options) { + case normal_argument: + *(int*)arg_ptr = chars_read; + break; + case short_argument: + *(short*)arg_ptr = chars_read; + break; + case long_argument: + *(long*)arg_ptr = chars_read; + break; + case char_argument: + *(char*)arg_ptr = chars_read; + break; + case long_long_argument: + *(long long*)arg_ptr = chars_read; + break; + } + } + + continue; + + case bad_conversion: + default: + goto exit; + } + } + +exit: + + if ((*ReadProc)(ReadProcArg, 0, __TestForError) && conversions == 0) { + return EOF; + } + + return items_assigned; +} + +inline int vsscanf(const char* s, const char* format, va_list arg) { + __InStrCtrl isc; + isc.NextChar = (char*)s; + + if ((s == 0) || (*isc.NextChar == '\0')) { + return -1; + } + + isc.NullCharDetected = 0; + return __sformatter(&__StringRead, (void*)&isc, format, arg, 0); +} + +int sscanf(const char* s, const char* pFormat, ...) { + int ret; + va_list args; + va_start(args, pFormat); + return vsscanf(s, pFormat, args); +} diff --git a/src/MSL/strtold.c b/src/MSL/strtold.c new file mode 100644 index 00000000..876b2277 --- /dev/null +++ b/src/MSL/strtold.c @@ -0,0 +1,635 @@ +#include "ansi_fp.h" +#include "ctype.h" +#include "errno.h" +#include "float.h" +#include "limits.h" +#include "locale.h" +#include "mem.h" +#include "stdio_api.h" + +#pragma exceptions on + +extern double nan(const char*); +extern double __dec2num(const decimal*); + +#define LDBL_MAX 0x1.fffffffffffffP1023L +#define LDBL_EPSILON 0x1.0000000000000P-52L +#define LDBL_MIN 0x1.0000000000000P-1022L + +#define _MSL_SHRT_MAX 0x7FFF +#define _MSL_USHRT_MAX 0x7FFF +#define _MSL_SHRT_MIN (~_MSL_SHRT_MAX) + +#define INFINITY (*(float*)__float_huge) +#define NAN (*(float*)__float_nan) +#define HUGE_VAL (*(double*)__double_huge) + +#define final_state(scan_state) (scan_state & (2048 | 4096)) +#define success(scan_state) (scan_state & 3628) +#define hex_success(count, scan_state) (count - 1 > 2 && scan_state & (398)) + +#define fetch() (count++, (*ReadProc)(ReadProcArg, 0, __GetAChar)) +#define unfetch(c) (*ReadProc)(ReadProcArg, c, __UngetAChar) + +long double __strtold(int max_width, int (*ReadProc)(void*, int, int), + void* ReadProcArg, int* chars_scanned, int* overflow) { + int scan_state = 1; + int hex_scan_state = 0; + int count = 0; + int spaces = 0; + int c; + decimal d = {0, 0, 0, {0, ""}}; + int sig_negative = 0; + int exp_negative = 0; + long exp_value = 0; + int exp_adjust = 0; + register long double result = 0.0; + int sign_detected = 0; + int radix_marker = *(unsigned char*)(__lconv).decimal_point; + + unsigned char* chptr; + unsigned char mantissa[8]; + unsigned mantissa_digits; + unsigned long exponent = 0; + + int ui; + unsigned char uch, uch1; + int NibbleIndex; + int expsign = 0; + int exp_digits = 0; + unsigned intdigits = 0; + + *overflow = 0; + c = fetch(); + + while (count <= max_width && c != -1 && !final_state(scan_state)) { + switch (scan_state) { + case 1: + if (isspace(c)) { + c = fetch(); + count--; + spaces++; + break; + } + + switch (toupper(c)) { + case '-': + sig_negative = 1; + + case '+': + c = fetch(); + sign_detected = 1; + break; + case 'I': + c = fetch(); + scan_state = 16384; + break; + + case 'N': + c = fetch(); + scan_state = 8192; + break; + + default: + scan_state = 2; + break; + } + break; + + case 16384: { + int i = 1; + char model[] = "INFINITY"; + + while ((i < 8) && (toupper(c) == model[i])) { + i++; + c = fetch(); + } + + if ((i == 3) || (i == 8)) { + if (sig_negative) { + result = -INFINITY; + /* TODO -- I AM A HACK */ + __asm { + frsp result, result + } + ; + } else { + result = INFINITY; + } + + *chars_scanned = spaces + i + sign_detected; + return result; + } else { + scan_state = 4096; + } + + break; + } + + case 8192: { + int i = 1, j = 0; + char model[] = "NAN("; + char nan_arg[32] = ""; + while ((i < 4) && (toupper(c) == model[i])) { + i++; + c = fetch(); + } + + if ((i == 3) || (i == 4)) { + if (i == 4) { + while ((j < 32) && + (isdigit(c) || isalpha(c) || (c == radix_marker))) { + nan_arg[j++] = (char)c; + c = fetch(); + } + + if (c != ')') { + scan_state = 4096; + break; + } else { + j++; + } + } + nan_arg[j] = '\0'; + + if (sig_negative) { + result = -nan(nan_arg); + } else { + result = nan(nan_arg); + } + + *chars_scanned = spaces + i + j + sign_detected; + return result; + } else { + scan_state = 4096; + } + break; + } + + case 2: + if (c == radix_marker) { + scan_state = 16; + c = fetch(); + break; + } + if (!isdigit(c)) { + scan_state = 4096; + break; + } + + if (c == '0') { + c = fetch(); + if (toupper(c) == 'X') { + scan_state = 32768; + hex_scan_state = 1; + } else { + scan_state = 4; + } + break; + } + + scan_state = 8; + break; + + case 4: + if (c == '0') { + c = fetch(); + + break; + } + scan_state = 8; + break; + + case 8: + if (!isdigit(c)) { + if (c == radix_marker) { + scan_state = 32; + c = fetch(); + } else { + scan_state = 64; + } + break; + } + if (d.sig.length < 20) { + d.sig.text[d.sig.length++] = (unsigned char)c; + } else { + exp_adjust++; + } + + c = fetch(); + break; + + case 16: + if (!isdigit(c)) { + scan_state = 4096; + break; + } + + scan_state = 32; + break; + + case 32: + if (!isdigit(c)) { + scan_state = 64; + break; + } + + if (d.sig.length < 20) { + if (c != '0' || d.sig.length) { + d.sig.text[d.sig.length++] = (unsigned char)c; + } + + exp_adjust--; + } + c = fetch(); + break; + + case 64: + if (toupper(c) == 'E') { + scan_state = 128; + c = fetch(); + break; + } + scan_state = 2048; + break; + + case 128: + if (c == '+') { + c = fetch(); + } else if (c == '-') { + c = fetch(); + exp_negative = 1; + } + + scan_state = 256; + break; + + case 256: + if (!isdigit(c)) { + scan_state = 4096; + break; + } + + if (c == '0') { + scan_state = 512; + c = fetch(); + break; + } + + scan_state = 1024; + break; + + case 512: + if (c == '0') { + c = fetch(); + break; + } + + scan_state = 1024; + break; + + case 1024: + if (!isdigit(c)) { + scan_state = 2048; + break; + } + + exp_value = exp_value * 10 + (c - '0'); + if (exp_value > SHRT_MAX) { + *overflow = 1; + } + + c = fetch(); + break; + + case 32768: { + switch (hex_scan_state) { + case 1: + memset(mantissa, 0, sizeof(mantissa)); + chptr = mantissa; + mantissa_digits = (53 + 3) / 4; + intdigits = 0; + NibbleIndex = 0; + hex_scan_state = 2; + c = fetch(); + break; + + case 2: + if (c == '0') { + c = fetch(); + break; + } + + hex_scan_state = 4; + break; + + case 4: + if (!isxdigit(c)) { + if (c == radix_marker) { + hex_scan_state = 8; + c = fetch(); + } + + else { + hex_scan_state = 16; + } + break; + } + + if (intdigits < mantissa_digits) { + intdigits++; + uch = *(chptr + NibbleIndex / 2); + + ui = toupper(c); + if (ui >= 'A') { + ui = ui - 'A' + 10; + } else { + ui -= '0'; + } + + uch1 = (unsigned char)ui; + + if ((NibbleIndex % 2) != 0) { + uch |= uch1; + } else { + uch |= (unsigned char)(uch1 << 4); + } + + *(chptr + NibbleIndex++ / 2) = uch; + c = fetch(); + } + + else { + c = fetch(); + } + + break; + + case 8: + if (!isxdigit(c)) { + hex_scan_state = 16; + break; + } + + if (intdigits < mantissa_digits) { + uch = *(chptr + NibbleIndex / 2); + ui = toupper(c); + + if (ui >= 'A') { + ui = ui - 'A' + 10; + } else { + ui -= '0'; + } + + uch1 = (unsigned char)ui; + + if ((NibbleIndex % 2) != 0) { + uch |= uch1; + } else { + uch |= (unsigned char)(uch1 << 4); + } + + *(chptr + NibbleIndex++ / 2) = uch; + c = fetch(); + } else { + c = fetch(); + } + break; + + case 16: + if (toupper(c) == 'P') { + hex_scan_state = 32; + exp_digits++; + c = fetch(); + } else { + scan_state = 2048; + } + + break; + + case 32: + exp_digits++; + if (c == '-') { + expsign = 1; + } else if (c != '+') { + c = unfetch(c); + count--; + exp_digits--; + } + + hex_scan_state = 64; + c = fetch(); + break; + + case 64: + if (!isdigit(c)) { + scan_state = 4096; + break; + } + + if (c == '0') { + exp_digits++; + hex_scan_state = 128; + c = fetch(); + break; + } + + hex_scan_state = 256; + break; + + case 128: + if (c == '0') { + c = fetch(); + break; + } + + hex_scan_state = 256; + break; + + case 256: + if (!isdigit(c)) { + scan_state = 2048; + break; + } + + exponent = exponent * 10 + (c - '0'); + + if (exp_value > SHRT_MAX) { + *overflow = 1; + } + + exp_digits++; + c = fetch(); + + break; + } + } break; + } + } + + if (scan_state != 32768 ? !success(scan_state) + : !hex_success(count, hex_scan_state)) { + count = 0; + *chars_scanned = 0; + } else { + count--; + *chars_scanned = count + spaces; + } + + unfetch(c); + + if (hex_scan_state == 0) { + if (exp_negative) { + exp_value = -exp_value; + } + + { + int n = d.sig.length; + unsigned char* p = &d.sig.text[n]; + + while (n-- && *--p == '0') { + exp_adjust++; + } + + d.sig.length = (unsigned char)(n + 1); + + if (d.sig.length == 0) { + d.sig.text[d.sig.length++] = '0'; + } + } + + exp_value += exp_adjust; + + // idk SHRT_MIN does not work... + if (-0x8000 > exp_value || SHRT_MAX < exp_value) { + *overflow = 1; + } + + if (*overflow) { + if (exp_negative) { + return 0.0; + } else { + return sig_negative ? -HUGE_VAL : HUGE_VAL; + } + } + + d.exponent = (short)exp_value; + + result = __dec2num(&d); + + if (result != 0.0 && result < LDBL_MIN) { + *overflow = 1; + } else if (result > LDBL_MAX) { + *overflow = 1; + result = HUGE_VAL; + } + + if (sig_negative && success(scan_state)) { + result = -result; + } + + return result; + } else { + unsigned mantissa_bit, dbl_bit; + unsigned one_bit; + long double dbl_bits_storage; + unsigned char* dbl_bits = (unsigned char*)&dbl_bits_storage; + + if (expsign) { + exponent = -exponent; + } + + exponent += intdigits * 4; + + one_bit = 0; + while (one_bit < 4 && !(mantissa[0] & (0x80 >> one_bit))) { + one_bit++; + exponent--; + } + + exponent--; + + if (1) { + one_bit++; + } + + if (one_bit) { + unsigned char carry = 0; + for (chptr = mantissa + sizeof(mantissa) - 1; chptr >= mantissa; + chptr--) { + unsigned char a = *chptr; + *chptr = (unsigned char)((a << one_bit) | carry); + carry = (unsigned char)(a >> (8 - one_bit)); + } + } + + memset(dbl_bits, 0, sizeof(dbl_bits_storage)); + dbl_bit = (64 - 52); + + for (mantissa_bit = 0; mantissa_bit < 52; mantissa_bit += 8) { + unsigned char ui = mantissa[mantissa_bit >> 3]; + int halfbits; + + if (mantissa_bit + 8 > 52) { + ui &= 0xff << (52 - mantissa_bit); + } + + halfbits = (dbl_bit & 7); + dbl_bits[dbl_bit >> 3] |= (unsigned char)(ui >> halfbits); + dbl_bit += 8; + dbl_bits[dbl_bit >> 3] |= (unsigned char)(ui << (8 - halfbits)); + } + + exponent += 1024 - 1; + + if ((exponent & ~(1024 * 2 - 1))) { + *overflow = 1; + return 0.0; + } + + exponent <<= 32 - 11; + + dbl_bits[0] |= exponent >> 25; + + if (11 > 7) { + dbl_bits[1] |= exponent >> 17; + } + + if (11 > 15) { + dbl_bits[2] |= exponent >> 9; + } + + if (11 > 23) { + dbl_bits[3] |= exponent >> 1; + } + + if (sig_negative) { + dbl_bits[0] |= 0x80; + } + + result = *(long double*)dbl_bits; + + return result; + } +} + +double atof(const char* str, char** end) { + double abs_value; + double value; + int overflow; + int count; + + __InStrCtrl isc; + isc.NextChar = (char*)str; + isc.NullCharDetected = 0; + + value = __strtold(INT_MAX, &__StringRead, (void*)&isc, &count, &overflow); + + abs_value = __fabs(value); + + if (overflow || + (value != 0.0 && (abs_value < DBL_MIN || abs_value > DBL_MAX))) + errno = ERANGE; + + return value; +} From 53964f57953e765215480dcb2f1dd46eb52a521b Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Fri, 26 Sep 2025 03:52:35 -0400 Subject: [PATCH 21/25] consolidate duplicates --- include/MSL/alloc.h | 117 +++++++++++++++++++++++++++++ include/MSL/internal/math_api.h | 15 ---- include/MSL/internal/mbstring.h | 15 ---- include/MSL/internal/pformatter.h | 48 ++++++++++++ include/MSL/internal/sformatter.h | 34 +++++++++ include/MSL/internal/str_scan.h | 22 ++++++ include/MSL/internal/wmem.h | 14 ---- include/MSL/internal/wstring.h | 18 ----- include/MSL/limits.h | 11 +++ include/MSL/math.h | 2 +- include/MSL/math_api.h | 14 +++- include/MSL/mbstring.h | 4 +- include/MSL/stdlib.h | 2 +- include/MSL/wchar.h | 4 +- include/MSL/wctype.h | 15 ++++ include/MSL/wmem.h | 7 +- include/MSL/wstring.h | 4 +- src/MSL/alloc.c | 120 +----------------------------- src/MSL/ansi_fp.c | 1 - src/MSL/printf.c | 53 +------------ src/MSL/scanf.c | 46 ++---------- src/MSL/strtold.c | 17 +---- src/MSL/strtoul.c | 16 +--- src/MSL/wprintf.c | 67 +---------------- 24 files changed, 289 insertions(+), 377 deletions(-) create mode 100644 include/MSL/alloc.h delete mode 100644 include/MSL/internal/math_api.h delete mode 100644 include/MSL/internal/mbstring.h create mode 100644 include/MSL/internal/pformatter.h create mode 100644 include/MSL/internal/sformatter.h create mode 100644 include/MSL/internal/str_scan.h delete mode 100644 include/MSL/internal/wmem.h delete mode 100644 include/MSL/internal/wstring.h diff --git a/include/MSL/alloc.h b/include/MSL/alloc.h new file mode 100644 index 00000000..c5bfc6ab --- /dev/null +++ b/include/MSL/alloc.h @@ -0,0 +1,117 @@ +typedef struct Block { + struct Block* prev; + struct Block* next; + unsigned long max_size; + unsigned long size; +} Block; + +typedef struct SubBlock { + unsigned long size; + Block* block; + struct SubBlock* prev; + struct SubBlock* next; +} SubBlock; + +struct FixSubBlock; + +typedef struct FixBlock { + struct FixBlock* prev_; + struct FixBlock* next_; + unsigned long client_size_; + struct FixSubBlock* start_; + unsigned long n_allocated_; +} FixBlock; + +typedef struct FixSubBlock { + FixBlock* block_; + struct FixSubBlock* next_; +} FixSubBlock; + +typedef struct FixStart { + FixBlock* tail_; + FixBlock* head_; +} FixStart; + +typedef struct __mem_pool_obj { + Block* start_; + FixStart fix_start[6]; +} __mem_pool_obj; + +typedef struct __mem_pool { + void* reserved[14]; +} __mem_pool; + +typedef signed long tag_word; + +typedef struct block_header { + tag_word tag; + struct block_header* prev; + struct block_header* next; +} block_header; + +typedef struct list_header { + block_header* rover; + block_header header; +} list_header; + +typedef struct heap_header { + struct heap_header* prev; + struct heap_header* next; +} heap_header; + +struct mem_pool_obj; +typedef void* (*sys_alloc_ptr)(unsigned long, struct mem_pool_obj*); +typedef void (*sys_free_ptr)(void*, struct mem_pool_obj*); + +typedef struct pool_options { + sys_alloc_ptr sys_alloc_func; + sys_free_ptr sys_free_func; + unsigned long min_heap_size; + int always_search_first; +} pool_options; + +typedef struct mem_pool_obj { + list_header free_list; + pool_options options; + heap_header* heap_list; + void* userData; + +} mem_pool_obj; + +static const unsigned long fix_pool_sizes[] = {4, 12, 20, 36, 52, 68}; + +#define SubBlock_size(ths) ((ths)->size & 0xFFFFFFF8) +#define SubBlock_block(ths) ((Block*)((unsigned long)((ths)->block) & ~0x1)) +#define Block_size(ths) ((ths)->size & 0xFFFFFFF8) +#define Block_start(ths) \ + (*(SubBlock**)((char*)(ths) + Block_size((ths)) - sizeof(unsigned long))) + +#define SubBlock_set_free(ths) \ + unsigned long this_size = SubBlock_size((ths)); \ + (ths)->size &= ~0x2; \ + *(unsigned long*)((char*)(ths) + this_size) &= ~0x4; \ + *(unsigned long*)((char*)(ths) + this_size - sizeof(unsigned long)) = \ + this_size + +#define SubBlock_is_free(ths) !((ths)->size & 2) +#define SubBlock_set_size(ths, sz) \ + (ths)->size &= ~0xFFFFFFF8; \ + (ths)->size |= (sz)&0xFFFFFFF8; \ + if (SubBlock_is_free((ths))) \ + *(unsigned long*)((char*)(ths) + (sz) - sizeof(unsigned long)) = (sz) + +#define SubBlock_from_pointer(ptr) ((SubBlock*)((char*)(ptr)-8)) +#define FixSubBlock_from_pointer(ptr) ((FixSubBlock*)((char*)(ptr)-4)) + +#define FixBlock_client_size(ths) ((ths)->client_size_) +#define FixSubBlock_size(ths) (FixBlock_client_size((ths)->block_)) + +#define classify(ptr) \ + (*(unsigned long*)((char*)(ptr) - sizeof(unsigned long)) & 1) +#define __msize_inline(ptr) \ + (!classify(ptr) ? FixSubBlock_size(FixSubBlock_from_pointer(ptr)) \ + : SubBlock_size(SubBlock_from_pointer(ptr)) - 8) + +#define Block_empty(ths) \ + (_sb = (SubBlock*)((char*)(ths) + 16)), \ + SubBlock_is_free(_sb) && SubBlock_size(_sb) == Block_size((ths)) - 24 diff --git a/include/MSL/internal/math_api.h b/include/MSL/internal/math_api.h deleted file mode 100644 index a8b168c4..00000000 --- a/include/MSL/internal/math_api.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef MSL_MATH_API_H -#define MSL_MATH_API_H -#include -#ifdef __cplusplus -extern "C" { -#endif - -int __fpclassify(long double); -int __fpclassifyd(double); -int __fpclassifyf(float); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/include/MSL/internal/mbstring.h b/include/MSL/internal/mbstring.h deleted file mode 100644 index e0cb5d5f..00000000 --- a/include/MSL/internal/mbstring.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef MSL_MBSTRING_H -#define MSL_MBSTRING_H -#include -#ifdef __cplusplus -extern "C" { -#endif - -int mbtowc(wchar_t*, const char*, size_t); -size_t mbstowcs(wchar_t*, const char*, size_t); -size_t wcstombs(char*, const wchar_t*, size_t); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/include/MSL/internal/pformatter.h b/include/MSL/internal/pformatter.h new file mode 100644 index 00000000..ea41f65e --- /dev/null +++ b/include/MSL/internal/pformatter.h @@ -0,0 +1,48 @@ +#ifndef MSL_INTERNAL_PFORMATTER_H +#define MSL_INTERNAL_PFORMATTER_H + +#include "stddef.h" + +enum justification_options { + left_justification, + right_justification, + zero_fill +}; + +enum sign_options { only_minus, sign_always, space_holder }; + +enum argument_options { + normal_argument, + char_argument, + short_argument, + long_argument, + long_long_argument, + wchar_argument, + intmax_argument, + size_t_argument, + ptrdiff_argument, + long_double_argument +}; + +typedef struct { + char* CharStr; + size_t MaxCharCount; + size_t CharsWritten; +} __OutStrCtrl; + +#define LDBL_MANT_DIG 24 +#define LDBL_MAX_EXP 128 +#define TARGET_FLOAT_BITS 32 +#define TARGET_FLOAT_BYTES (TARGET_FLOAT_BITS / 8) +#define TARGET_FLOAT_MAX_EXP LDBL_MAX_EXP +#define TARGET_FLOAT_MANT_DIG LDBL_MANT_DIG +#define TARGET_FLOAT_IMPLICIT_J_BIT 1 +#define TARGET_FLOAT_MANT_BITS (TARGET_FLOAT_MANT_DIG - TARGET_FLOAT_IMPLICIT_J_BIT) +#define TARGET_FLOAT_EXP_BITS (TARGET_FLOAT_BITS - TARGET_FLOAT_MANT_BITS - 1) + +typedef long long intmax_t; + +#define PTRDIFF __typeof__((char*)0-(char*)0) +typedef PTRDIFF ptrdiff_t; + +#endif // MSL_INTERNAL_PFORMATTER_H diff --git a/include/MSL/internal/sformatter.h b/include/MSL/internal/sformatter.h new file mode 100644 index 00000000..2db52788 --- /dev/null +++ b/include/MSL/internal/sformatter.h @@ -0,0 +1,34 @@ +#ifndef MSL_INTERNAL_SFORMATTER_H +#define MSL_INTERNAL_SFORMATTER_H + +#include "stddef.h" + +enum argument_options { + normal_argument, + char_argument, + short_argument, + long_argument, + intmax_argument, + size_t_argument, + ptrdiff_argument, + long_long_argument, + double_argument, + long_double_argument, + wchar_argument +}; + +typedef unsigned char char_map[32]; + +#define set_char_map(map, ch) ((map)[(unsigned char)(ch) >> 3] |= (1 << ((ch) & 7))) +#define tst_char_map(map, ch) ((map)[(unsigned char)(ch) >> 3] & (1 << ((ch) & 7))) + +typedef struct { + unsigned char suppress_assignment; + unsigned char field_width_specified; + unsigned char argument_options; + unsigned char conversion_char; + int field_width; + char_map char_set; +} scan_format; + +#endif // MSL_INTERNAL_SFORMATTER_H \ No newline at end of file diff --git a/include/MSL/internal/str_scan.h b/include/MSL/internal/str_scan.h new file mode 100644 index 00000000..267f2d9b --- /dev/null +++ b/include/MSL/internal/str_scan.h @@ -0,0 +1,22 @@ +#ifndef MSL_INTERNAL_STR_SCAN_H +#define MSL_INTERNAL_STR_SCAN_H + +#include "stdio_api.h" + +enum scan_states { + start = 0x01, + check_for_zero = 0x02, + leading_zero = 0x04, + need_digit = 0x08, + digit_loop = 0x10, + finished = 0x20, + failure = 0x40 +}; + +#define final_state(scan_state) ((scan_state) & (finished | failure)) +#define success(scan_state) ((scan_state) & (leading_zero | digit_loop | finished)) + +#define fetch() (count++, (*ReadProc)(ReadProcArg, 0, __GetAChar)) +#define unfetch(c) ((*ReadProc)(ReadProcArg, c, __UngetAChar)) + +#endif // MSL_INTERNAL_STR_SCAN_H \ No newline at end of file diff --git a/include/MSL/internal/wmem.h b/include/MSL/internal/wmem.h deleted file mode 100644 index 903e666e..00000000 --- a/include/MSL/internal/wmem.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef MSL_WMEM_H -#define MSL_WMEM_H -#include -#ifdef __cplusplus -extern "C" { -#endif - -void* wmemcpy(void*, const void*, size_t); -void* wmemchr(const void*, int, size_t); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/include/MSL/internal/wstring.h b/include/MSL/internal/wstring.h deleted file mode 100644 index bc977897..00000000 --- a/include/MSL/internal/wstring.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef MSL_WSTRING_H -#define MSL_WSTRING_H -#include -#ifdef __cplusplus -extern "C" { -#endif - -size_t wcslen(const wchar_t*); -wchar_t* wcscpy(wchar_t*, const wchar_t*); -wchar_t* wcsncpy(wchar_t*, const wchar_t*, size_t); -wchar_t* wcscat(wchar_t*, const wchar_t*); -int wcscmp(const wchar_t*, const wchar_t*); -wchar_t* wcschr(const wchar_t*, wchar_t); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/include/MSL/limits.h b/include/MSL/limits.h index f301a0fc..ffe2c07c 100644 --- a/include/MSL/limits.h +++ b/include/MSL/limits.h @@ -32,6 +32,17 @@ extern "C" { #define DBL_MIN 2.2250738585072014E-308L #define DBL_MAX 1.7976931348623157E+308L +#define LDBL_MIN 0x1.0000000000000P-1022L +#define LDBL_MAX 0x1.fffffffffffffP1023L +#define LDBL_EPSILON 0x1.0000000000000P-52L + +#define INFINITY (*(float*)__float_huge) + +// NAN and HUGE_VAL are redefined in a bunch of locations +//#define NAN (*(float*)__float_nan) +//#define HUGE_VAL (*(double*)__double_huge) + + #ifdef __cplusplus } #endif diff --git a/include/MSL/math.h b/include/MSL/math.h index 58cea7b6..1be0a4c0 100644 --- a/include/MSL/math.h +++ b/include/MSL/math.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/MSL/math_api.h b/include/MSL/math_api.h index f55ccfad..95df9f2c 100644 --- a/include/MSL/math_api.h +++ b/include/MSL/math_api.h @@ -1,9 +1,14 @@ -#ifndef MATH_API_H -#define MATH_API_H +#ifndef MSL_MATH_API_H +#define MSL_MATH_API_H +#ifdef __cplusplus +extern "C" { +#endif int __fpclassifyf(float); int __signbitd(double); int __fpclassifyd(double); +int __fpclassify(long double); + double copysign(double, double); double frexp(double, int *); @@ -11,4 +16,7 @@ double ldexp(double, int); double nan(const char *); -#endif // MATH_API_H \ No newline at end of file +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/MSL/mbstring.h b/include/MSL/mbstring.h index 788f4cff..1a6e2651 100644 --- a/include/MSL/mbstring.h +++ b/include/MSL/mbstring.h @@ -1,5 +1,5 @@ -#ifndef _MBSTRING_H -#define _MBSTRING_H +#ifndef MSL_MBSTRING_H +#define MSL_MBSTRING_H #include "types.h" diff --git a/include/MSL/stdlib.h b/include/MSL/stdlib.h index 06827cb5..0b334830 100644 --- a/include/MSL/stdlib.h +++ b/include/MSL/stdlib.h @@ -1,7 +1,7 @@ #ifndef MSL_STDLIB_H #define MSL_STDLIB_H #include -#include +#include #include #include #endif diff --git a/include/MSL/wchar.h b/include/MSL/wchar.h index 693adb95..96981a68 100644 --- a/include/MSL/wchar.h +++ b/include/MSL/wchar.h @@ -1,8 +1,8 @@ #ifndef MSL_WCHAR_H #define MSL_WCHAR_H -#include +#include #include -#include +#include #include #include #ifdef __cplusplus diff --git a/include/MSL/wctype.h b/include/MSL/wctype.h index 788ec040..6389ea31 100644 --- a/include/MSL/wctype.h +++ b/include/MSL/wctype.h @@ -2,9 +2,24 @@ #define WCTYPE_H #include "types.h" +#include "wchar.h" +#include "locale.h" extern const unsigned short __wctype_mapC[0x100]; extern const wchar_t __wlower_mapC[0x100]; extern const wchar_t __wupper_mapC[0x100]; +inline int iswdigit(wint_t c) { + return ((c < 0) || (c >= 0x100)) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & 0x8); +} + +inline int iswupper(wint_t c) { + return ((c < 0) || (c >= 0x100)) + ? 0 + : (int)(_current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & + 0x200); +} + #endif // WCTYPE_H diff --git a/include/MSL/wmem.h b/include/MSL/wmem.h index f581d950..9d9ffb79 100644 --- a/include/MSL/wmem.h +++ b/include/MSL/wmem.h @@ -1,9 +1,14 @@ #ifndef MSL_WMEM_H #define MSL_WMEM_H - #include "types.h" +#ifdef __cplusplus +extern "C" { +#endif wchar_t* wmemcpy(wchar_t*, const wchar_t*, size_t); wchar_t* wmemchr(wchar_t*, wchar_t, size_t); +#ifdef __cplusplus +} +#endif #endif diff --git a/include/MSL/wstring.h b/include/MSL/wstring.h index c7cba7d5..91beaf79 100644 --- a/include/MSL/wstring.h +++ b/include/MSL/wstring.h @@ -1,5 +1,5 @@ -#ifndef _WSTRING_H -#define _WSTRING_H +#ifndef MSL_WSTRING_H +#define MSL_WSTRING_H #include "types.h" diff --git a/src/MSL/alloc.c b/src/MSL/alloc.c index d15aaa2e..0c3ed795 100644 --- a/src/MSL/alloc.c +++ b/src/MSL/alloc.c @@ -1,128 +1,12 @@ +#include "alloc.h" + #pragma exceptions on void __sys_free(void* ptr); void* memset(void*, int, int); -typedef struct Block { - struct Block* prev; - struct Block* next; - unsigned long max_size; - unsigned long size; -} Block; - -typedef struct SubBlock { - unsigned long size; - Block* block; - struct SubBlock* prev; - struct SubBlock* next; -} SubBlock; - -struct FixSubBlock; - -typedef struct FixBlock { - struct FixBlock* prev_; - struct FixBlock* next_; - unsigned long client_size_; - struct FixSubBlock* start_; - unsigned long n_allocated_; -} FixBlock; - -typedef struct FixSubBlock { - FixBlock* block_; - struct FixSubBlock* next_; -} FixSubBlock; - -typedef struct FixStart { - FixBlock* tail_; - FixBlock* head_; -} FixStart; - -typedef struct __mem_pool_obj { - Block* start_; - FixStart fix_start[6]; -} __mem_pool_obj; - -typedef struct __mem_pool { - void* reserved[14]; -} __mem_pool; - -typedef signed long tag_word; - -typedef struct block_header { - tag_word tag; - struct block_header* prev; - struct block_header* next; -} block_header; - -typedef struct list_header { - block_header* rover; - block_header header; -} list_header; - -typedef struct heap_header { - struct heap_header* prev; - struct heap_header* next; -} heap_header; - -struct mem_pool_obj; -typedef void* (*sys_alloc_ptr)(unsigned long, struct mem_pool_obj*); -typedef void (*sys_free_ptr)(void*, struct mem_pool_obj*); - -typedef struct pool_options { - sys_alloc_ptr sys_alloc_func; - sys_free_ptr sys_free_func; - unsigned long min_heap_size; - int always_search_first; -} pool_options; - -typedef struct mem_pool_obj { - list_header free_list; - pool_options options; - heap_header* heap_list; - void* userData; - -} mem_pool_obj; - static void SubBlock_merge_next(SubBlock*, SubBlock**); -static const unsigned long fix_pool_sizes[] = {4, 12, 20, 36, 52, 68}; - -#define SubBlock_size(ths) ((ths)->size & 0xFFFFFFF8) -#define SubBlock_block(ths) ((Block*)((unsigned long)((ths)->block) & ~0x1)) -#define Block_size(ths) ((ths)->size & 0xFFFFFFF8) -#define Block_start(ths) \ - (*(SubBlock**)((char*)(ths) + Block_size((ths)) - sizeof(unsigned long))) - -#define SubBlock_set_free(ths) \ - unsigned long this_size = SubBlock_size((ths)); \ - (ths)->size &= ~0x2; \ - *(unsigned long*)((char*)(ths) + this_size) &= ~0x4; \ - *(unsigned long*)((char*)(ths) + this_size - sizeof(unsigned long)) = \ - this_size - -#define SubBlock_is_free(ths) !((ths)->size & 2) -#define SubBlock_set_size(ths, sz) \ - (ths)->size &= ~0xFFFFFFF8; \ - (ths)->size |= (sz)&0xFFFFFFF8; \ - if (SubBlock_is_free((ths))) \ - *(unsigned long*)((char*)(ths) + (sz) - sizeof(unsigned long)) = (sz) - -#define SubBlock_from_pointer(ptr) ((SubBlock*)((char*)(ptr)-8)) -#define FixSubBlock_from_pointer(ptr) ((FixSubBlock*)((char*)(ptr)-4)) - -#define FixBlock_client_size(ths) ((ths)->client_size_) -#define FixSubBlock_size(ths) (FixBlock_client_size((ths)->block_)) - -#define classify(ptr) \ - (*(unsigned long*)((char*)(ptr) - sizeof(unsigned long)) & 1) -#define __msize_inline(ptr) \ - (!classify(ptr) ? FixSubBlock_size(FixSubBlock_from_pointer(ptr)) \ - : SubBlock_size(SubBlock_from_pointer(ptr)) - 8) - -#define Block_empty(ths) \ - (_sb = (SubBlock*)((char*)(ths) + 16)), \ - SubBlock_is_free(_sb) && SubBlock_size(_sb) == Block_size((ths)) - 24 - inline static SubBlock* SubBlock_merge_prev(SubBlock* ths, SubBlock** start) { unsigned long prevsz; SubBlock* p; diff --git a/src/MSL/ansi_fp.c b/src/MSL/ansi_fp.c index 718b527c..6fa33597 100644 --- a/src/MSL/ansi_fp.c +++ b/src/MSL/ansi_fp.c @@ -89,7 +89,6 @@ const char _Date_Format_C[] = "%m/%d/%y\0\0\0"; const char _Day_Names_C[] = "Sun|Sunday|Mon|Monday|Tue|Tuesday|Wed|Wednesday|Thu|Thursday|Fri|Friday|Sat|Saturday\0\0\0"; const char _Month_Names_C[] = "Jan|January|Feb|February|Mar|March|Apr|April|May|May|Jun|June|Jul|July|Aug|August|Sep|September|Oct|October|Nov|November|Dec|December\0\0"; -#define INFINITY (*(float*)__float_huge) #define SIGDIGLEN 36 extern double pow(double, double); diff --git a/src/MSL/printf.c b/src/MSL/printf.c index f8d072b3..a223155d 100644 --- a/src/MSL/printf.c +++ b/src/MSL/printf.c @@ -1,51 +1,12 @@ #include #include "ansi_fp.h" #include "string.h" +#include "internal/pformatter.h" #pragma exceptions on -#define LDBL_MANT_DIG 24 -#define LDBL_MAX_EXP 128 -#define TARGET_FLOAT_BITS 32 -#define TARGET_FLOAT_BYTES (TARGET_FLOAT_BITS/8) -#define TARGET_FLOAT_MAX_EXP LDBL_MAX_EXP -#define TARGET_FLOAT_MANT_DIG LDBL_MANT_DIG -#define TARGET_FLOAT_IMPLICIT_J_BIT 1 -#define TARGET_FLOAT_MANT_BITS (TARGET_FLOAT_MANT_DIG - TARGET_FLOAT_IMPLICIT_J_BIT) -#define TARGET_FLOAT_EXP_BITS (TARGET_FLOAT_BITS - TARGET_FLOAT_MANT_BITS - 1) - -typedef long long intmax_t; - -#define PTRDIFF __typeof__((char*)0-(char*)0) -typedef PTRDIFF ptrdiff_t; - size_t __fwrite(const void *pPtr, size_t memb_size, size_t num_memb, FILE *pFile); -enum justification_options { - left_justification, - right_justification, - zero_fill -}; - -enum sign_options { - only_minus, - sign_always, - space_holder -}; - -enum argument_options { - normal_argument, - char_argument, - short_argument, - long_argument, - long_long_argument, - wchar_argument, - intmax_argument, - size_t_argument, - ptrdiff_argument, - long_double_argument -}; - typedef struct { unsigned char justification_options; // 0x0 unsigned char sign_options; // 0x1 @@ -57,13 +18,7 @@ typedef struct { int precision; // 0xC } print_format; -typedef struct { - char* CharStr; - size_t MaxCharCount; - size_t CharsWritten; -} __OutStrCtrl; - -/*static*/ const char* parse_format(const char *format_string, va_list *arg, print_format *format) { +const char* parse_format(const char *format_string, va_list *arg, print_format *format) { print_format f; const char* s = format_string; int c; @@ -231,7 +186,7 @@ typedef struct { } if (!f.precision_specified) { - f.precision = 1; + f.precision = 6; } break; @@ -1316,7 +1271,7 @@ void* __StringWrite(void *pCtrl, const char *pBuffer, size_t char_num) { return (void*)1; } -int fprintf(FILE *pFile, const char *format, ...) { +inline int fprintf(FILE *pFile, const char *format, ...) { int res; if (fwide(pFile, -1) >= 0) { diff --git a/src/MSL/scanf.c b/src/MSL/scanf.c index 0fb4cf89..497bbfc5 100644 --- a/src/MSL/scanf.c +++ b/src/MSL/scanf.c @@ -1,26 +1,14 @@ +#include "ctype.h" #include "limits.h" +#include "sformatter.h" #include "stdarg.h" #include "stdio_api.h" -#include "ctype.h" +#include "str_scan.h" #include #pragma exceptions on -enum argument_options { - normal_argument, - char_argument, - short_argument, - long_argument, - intmax_argument, - size_t_argument, - ptrdiff_argument, - long_long_argument, - double_argument, - long_double_argument, - wchar_argument -}; - typedef long long intmax_t; #define PTRDIFF __typeof__((char*)0 - (char*)0) typedef PTRDIFF ptrdiff_t; @@ -32,33 +20,13 @@ typedef size_t rsize_t; #define EOF -1L -typedef unsigned char char_map[32]; +extern long double __strtold(int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* overflow); +extern unsigned long long __strtoull(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* negative, int* overflow); +extern unsigned long __strtoul(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* negative, int* overflow); -extern long double __strtold(int max_width, int (*ReadProc)(void*, int, int), - void* ReadProcArg, int* chars_scanned, - int* overflow); -extern unsigned long long __strtoull(int base, int max_width, - int (*ReadProc)(void*, int, int), - void* ReadProcArg, int* chars_scanned, - int* negative, int* overflow); -extern unsigned long __strtoul(int base, int max_width, - int (*ReadProc)(void*, int, int), - void* ReadProcArg, int* chars_scanned, - int* negative, int* overflow); -int mbtowc(wchar_t* pDest, const char* s, size_t num); -typedef struct { - unsigned char suppress_assignment; - unsigned char field_width_specified; - unsigned char argument_options; - unsigned char conversion_char; - int field_width; - char_map char_set; -} scan_format; - -#define set_char_map(map, ch) map[(unsigned char)ch >> 3] |= (1 << (ch & 7)) -#define tst_char_map(map, ch) (map[(unsigned char)ch >> 3] & (1 << (ch & 7))) +int mbtowc(wchar_t* pDest, const char* s, size_t num); static const char* parse_format(const char* format_string, scan_format* format) { diff --git a/src/MSL/strtold.c b/src/MSL/strtold.c index 876b2277..46de6c14 100644 --- a/src/MSL/strtold.c +++ b/src/MSL/strtold.c @@ -5,32 +5,17 @@ #include "limits.h" #include "locale.h" #include "mem.h" -#include "stdio_api.h" +#include "str_scan.h" #pragma exceptions on extern double nan(const char*); extern double __dec2num(const decimal*); -#define LDBL_MAX 0x1.fffffffffffffP1023L -#define LDBL_EPSILON 0x1.0000000000000P-52L -#define LDBL_MIN 0x1.0000000000000P-1022L - -#define _MSL_SHRT_MAX 0x7FFF -#define _MSL_USHRT_MAX 0x7FFF -#define _MSL_SHRT_MIN (~_MSL_SHRT_MAX) - -#define INFINITY (*(float*)__float_huge) -#define NAN (*(float*)__float_nan) #define HUGE_VAL (*(double*)__double_huge) -#define final_state(scan_state) (scan_state & (2048 | 4096)) -#define success(scan_state) (scan_state & 3628) #define hex_success(count, scan_state) (count - 1 > 2 && scan_state & (398)) -#define fetch() (count++, (*ReadProc)(ReadProcArg, 0, __GetAChar)) -#define unfetch(c) (*ReadProc)(ReadProcArg, c, __UngetAChar) - long double __strtold(int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* overflow) { int scan_state = 1; diff --git a/src/MSL/strtoul.c b/src/MSL/strtoul.c index 7b634729..5cc3cc7d 100644 --- a/src/MSL/strtoul.c +++ b/src/MSL/strtoul.c @@ -3,21 +3,7 @@ #include "errno.h" #include "limits.h" #include "stdio.h" - -enum scan_states { - start = 0x01, - check_for_zero = 0x02, - leading_zero = 0x04, - need_digit = 0x08, - digit_loop = 0x10, - finished = 0x20, - failure = 0x40 -}; - -#define final_state(scan_state) (scan_state & (finished | failure)) -#define success(scan_state) (scan_state & (leading_zero | digit_loop | finished)) -#define fetch() (count++, (*ReadProc)(ReadProcArg, 0, __GetAChar)) -#define unfetch(c) (*ReadProc)(ReadProcArg, c, __UngetAChar) +#include "str_scan.h" #pragma exceptions on diff --git a/src/MSL/wprintf.c b/src/MSL/wprintf.c index 6cf78dad..fa6511a9 100644 --- a/src/MSL/wprintf.c +++ b/src/MSL/wprintf.c @@ -1,62 +1,19 @@ #include "ansi_fp.h" #include "stdio_api.h" -#include "wstring.h" -#include "stdarg.h" -#include "wchar.h" -#include "locale.h" +#include "pformatter.h" +#include "wctype.h" #pragma exceptions on -#define LDBL_MANT_DIG 24 -#define LDBL_MAX_EXP 128 -#define TARGET_FLOAT_BITS 32 -#define TARGET_FLOAT_BYTES (TARGET_FLOAT_BITS/8) -#define TARGET_FLOAT_MAX_EXP LDBL_MAX_EXP -#define TARGET_FLOAT_MANT_DIG LDBL_MANT_DIG -#define TARGET_FLOAT_IMPLICIT_J_BIT 1 -#define TARGET_FLOAT_MANT_BITS (TARGET_FLOAT_MANT_DIG - TARGET_FLOAT_IMPLICIT_J_BIT) -#define TARGET_FLOAT_EXP_BITS (TARGET_FLOAT_BITS - TARGET_FLOAT_MANT_BITS - 1) - -typedef long long intmax_t; - -#define PTRDIFF __typeof__((char*)0-(char*)0) -typedef PTRDIFF ptrdiff_t; - inline long double fabsl(long double x) { return __fabs((double)x); } - wchar_t* wcscpy(wchar_t *pDest, const wchar_t *pSrc); size_t strlen(const char *pStr); void* memchr(const void *, int, size_t); int mbtowc(wchar_t *pDest, const char *s, size_t num); -enum justification_options { - left_justification, - right_justification, - zero_fill -}; - -enum sign_options { - only_minus, - sign_always, - space_holder -}; - -enum argument_options { - normal_argument, - char_argument, - short_argument, - long_argument, - long_long_argument, - wchar_argument, - intmax_argument, - size_t_argument, - ptrdiff_argument, - long_double_argument -}; - typedef struct { unsigned char justification_options; // 0x0 unsigned char sign_options; // 0x1 @@ -68,26 +25,6 @@ typedef struct { int precision; // 0xC } print_format; -typedef struct { - char* CharStr; - size_t MaxCharCount; - size_t CharsWritten; -} __OutStrCtrl; - -inline int iswdigit(wint_t c) { - return ((c < 0) || (c >= 0x100)) - ? 0 - : (int)(_current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & - 0x8); -} - -inline int iswupper(wint_t c) { - return ((c < 0) || (c >= 0x100)) - ? 0 - : (int)(_current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & - 0x200); -} - const wchar_t* parse_format(const wchar_t *format_string, va_list *arg, print_format *format) { print_format f; const wchar_t* s = format_string; From e2dd925c23ce05e08032af21adeb02c5d98dad55 Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Fri, 26 Sep 2025 04:05:19 -0400 Subject: [PATCH 22/25] clean up files --- include/MSL/UART.h | 2 +- include/MSL/internal/file_struct.h | 2 +- include/MSL/internal/sformatter.h | 2 +- include/MSL/internal/str_scan.h | 2 +- include/MSL/locale.h | 6 +++--- include/MSL/math_api.h | 6 ++---- include/MSL/scanf.h | 6 ------ include/MSL/va_list.h | 2 +- include/MSL/wchar_io.h | 2 +- include/MSL/wstring.h | 1 - src/MSL/abort_exit_ppc_eabi.c | 2 +- src/MSL/arith.c | 2 +- src/MSL/direct_io.c | 2 +- src/MSL/wchar_io.c | 2 +- 14 files changed, 15 insertions(+), 24 deletions(-) delete mode 100644 include/MSL/scanf.h diff --git a/include/MSL/UART.h b/include/MSL/UART.h index 9d6abdf0..a1f00cbe 100644 --- a/include/MSL/UART.h +++ b/include/MSL/UART.h @@ -34,4 +34,4 @@ UARTError InitializeUART(UARTBaudRate); UARTError WriteUARTN(const void *, unsigned long); -#endif // UART_H \ No newline at end of file +#endif // UART_H diff --git a/include/MSL/internal/file_struct.h b/include/MSL/internal/file_struct.h index e0f5b149..5bcd3a1f 100644 --- a/include/MSL/internal/file_struct.h +++ b/include/MSL/internal/file_struct.h @@ -95,4 +95,4 @@ extern FILE __files[]; #define stdout (&__std(__files[1])) -#endif // FILE_STRUCT_H \ No newline at end of file +#endif // FILE_STRUCT_H diff --git a/include/MSL/internal/sformatter.h b/include/MSL/internal/sformatter.h index 2db52788..0daf2079 100644 --- a/include/MSL/internal/sformatter.h +++ b/include/MSL/internal/sformatter.h @@ -31,4 +31,4 @@ typedef struct { char_map char_set; } scan_format; -#endif // MSL_INTERNAL_SFORMATTER_H \ No newline at end of file +#endif // MSL_INTERNAL_SFORMATTER_H diff --git a/include/MSL/internal/str_scan.h b/include/MSL/internal/str_scan.h index 267f2d9b..1d35f589 100644 --- a/include/MSL/internal/str_scan.h +++ b/include/MSL/internal/str_scan.h @@ -19,4 +19,4 @@ enum scan_states { #define fetch() (count++, (*ReadProc)(ReadProcArg, 0, __GetAChar)) #define unfetch(c) ((*ReadProc)(ReadProcArg, c, __UngetAChar)) -#endif // MSL_INTERNAL_STR_SCAN_H \ No newline at end of file +#endif // MSL_INTERNAL_STR_SCAN_H diff --git a/include/MSL/locale.h b/include/MSL/locale.h index 97a18d28..88901027 100644 --- a/include/MSL/locale.h +++ b/include/MSL/locale.h @@ -1,5 +1,5 @@ -#ifndef LOCALE_H -#define LOCALE_H +#ifndef MSL_LOCALE_H +#define MSL_LOCALE_H #include "ansi_params.h" #include "wchar_io.h" @@ -112,4 +112,4 @@ struct __locale { extern struct __locale _current_locale; extern struct lconv __lconv; -#endif // LOCALE_H \ No newline at end of file +#endif // LOCALE_H diff --git a/include/MSL/math_api.h b/include/MSL/math_api.h index 95df9f2c..e90b22ee 100644 --- a/include/MSL/math_api.h +++ b/include/MSL/math_api.h @@ -4,16 +4,14 @@ extern "C" { #endif +int __fpclassify(long double); +int __fpclassifyd(double); int __fpclassifyf(float); int __signbitd(double); -int __fpclassifyd(double); -int __fpclassify(long double); - double copysign(double, double); double frexp(double, int *); double ldexp(double, int); - double nan(const char *); #ifdef __cplusplus diff --git a/include/MSL/scanf.h b/include/MSL/scanf.h deleted file mode 100644 index a4068394..00000000 --- a/include/MSL/scanf.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef SCANF_H -#define SCANF_H - - - -#endif // SCANF_H \ No newline at end of file diff --git a/include/MSL/va_list.h b/include/MSL/va_list.h index 16506e0d..20507db1 100644 --- a/include/MSL/va_list.h +++ b/include/MSL/va_list.h @@ -19,4 +19,4 @@ typedef __va_list va_list; } #endif -#endif // VA_LIST_H \ No newline at end of file +#endif // VA_LIST_H diff --git a/include/MSL/wchar_io.h b/include/MSL/wchar_io.h index 4cc827b7..1d74b3be 100644 --- a/include/MSL/wchar_io.h +++ b/include/MSL/wchar_io.h @@ -5,4 +5,4 @@ int fwide(FILE *, int); -#endif // WCHAR_IO_H \ No newline at end of file +#endif // WCHAR_IO_H diff --git a/include/MSL/wstring.h b/include/MSL/wstring.h index 91beaf79..966db183 100644 --- a/include/MSL/wstring.h +++ b/include/MSL/wstring.h @@ -17,5 +17,4 @@ wchar_t* wcschr(const wchar_t*, wchar_t); #ifdef __cplusplus } #endif - #endif diff --git a/src/MSL/abort_exit_ppc_eabi.c b/src/MSL/abort_exit_ppc_eabi.c index 81f51745..9ad5aa34 100644 --- a/src/MSL/abort_exit_ppc_eabi.c +++ b/src/MSL/abort_exit_ppc_eabi.c @@ -1 +1 @@ -void (*__stdio_exit)(void); \ No newline at end of file +void (*__stdio_exit)(void); diff --git a/src/MSL/arith.c b/src/MSL/arith.c index cb788d2a..fc272e35 100644 --- a/src/MSL/arith.c +++ b/src/MSL/arith.c @@ -2,4 +2,4 @@ int abs(int x) { return ((x >> 31) ^ x) - (x >> 31); -} \ No newline at end of file +} diff --git a/src/MSL/direct_io.c b/src/MSL/direct_io.c index fd31399b..cc137c54 100644 --- a/src/MSL/direct_io.c +++ b/src/MSL/direct_io.c @@ -113,4 +113,4 @@ size_t __fwrite(const void *pPtr, size_t memb_size, size_t num_memb, FILE *pFile } return bytes_written / memb_size; -} \ No newline at end of file +} diff --git a/src/MSL/wchar_io.c b/src/MSL/wchar_io.c index 64fd7c2e..9f558daf 100644 --- a/src/MSL/wchar_io.c +++ b/src/MSL/wchar_io.c @@ -32,4 +32,4 @@ int fwide(FILE *pFile, int file_mode) { } return res; -} \ No newline at end of file +} From c340d4c1e85c2889f4efef46c643cb5a2fac0914 Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Fri, 26 Sep 2025 16:58:27 -0400 Subject: [PATCH 23/25] get free() to match --- src/MSL/alloc.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/MSL/alloc.c b/src/MSL/alloc.c index 0c3ed795..2397bbe4 100644 --- a/src/MSL/alloc.c +++ b/src/MSL/alloc.c @@ -177,21 +177,6 @@ void deallocate_from_fixed_pools(__mem_pool_obj* pool_obj, void* ptr, } } -inline void __init_pool_obj(__mem_pool* pool_obj) { - memset(pool_obj, 0, sizeof(__mem_pool_obj)); -} - -inline static __mem_pool* get_malloc_pool(void) { - static __mem_pool protopool; - static unsigned char init = 0; - if (!init) { - __init_pool_obj(&protopool); - init = 1; - } - - return &protopool; -} - inline void __pool_free(__mem_pool* pool, void* ptr) { __mem_pool_obj* pool_obj; unsigned long size; @@ -211,5 +196,15 @@ inline void __pool_free(__mem_pool* pool, void* ptr) { } void free(void* ptr) { - __pool_free(get_malloc_pool(), ptr); + static unsigned char init = 0; + static __mem_pool protopool; + __mem_pool* pool; + + if (!init) { + memset(&protopool, 0, sizeof(__mem_pool_obj)); + init = 1; + } + + pool = &protopool; + __pool_free(pool, ptr); } From f5cc976306e5a342e35138cd87910c1131b7ed9b Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Fri, 26 Sep 2025 17:36:50 -0400 Subject: [PATCH 24/25] get ansi_fp to match 100% --- configure.py | 2 +- src/MSL/ansi_fp.c | 23 ++++++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/configure.py b/configure.py index a872e890..181f3fb8 100755 --- a/configure.py +++ b/configure.py @@ -729,7 +729,7 @@ def MatchingFor(*versions): Object(NonMatching, "MSL/alloc.c"), Object(Matching, "MSL/errno.c"), Object(NonMatching, "MSL/ansi_files.c"), - Object(NonMatching, "MSL/ansi_fp.c"), + Object(Matching, "MSL/ansi_fp.c"), Object(NonMatching, "MSL/locale.c"), Object(Matching, "MSL/arith.c"), Object(Matching, "MSL/buffer_io.c"), diff --git a/src/MSL/ansi_fp.c b/src/MSL/ansi_fp.c index 6fa33597..a63ebf42 100644 --- a/src/MSL/ansi_fp.c +++ b/src/MSL/ansi_fp.c @@ -140,12 +140,33 @@ static inline int __must_round(const decimal* d, int digits) { } static inline void __rounddec(decimal* d, int digits) { + u8* i; + u8* b; + if (digits > 0 && digits < d->sig.length) { int unkBool = __must_round(d, digits); d->sig.length = digits; if (unkBool >= 0) { - __dorounddecup(d, digits); + // using __dorounddecup causes r4 and r5 registers to swap + // __dorounddecup(d, digits); + // manually inlined code from __dorounddecup: + + b = d->sig.text; + i = b + digits - 1; + + while (1) { + if (*i < 9) { + *i += 1; + break; + } + if (i == b) { + *i = 1; + d->exponent++; + break; + } + *i-- = 0; + } } } } From 1513ac372adcba1b56b4d874a1c9ed7f30109d41 Mon Sep 17 00:00:00 2001 From: Alex9303 Date: Fri, 26 Sep 2025 19:05:23 -0400 Subject: [PATCH 25/25] fix some issues --- include/MSL/internal/str_scan.h | 22 ----------------- src/MSL/locale.c | 42 ++++++++++++++++----------------- src/MSL/scanf.c | 3 --- src/MSL/strtold.c | 6 ++++- src/MSL/strtoul.c | 17 ++++++++++++- 5 files changed, 42 insertions(+), 48 deletions(-) delete mode 100644 include/MSL/internal/str_scan.h diff --git a/include/MSL/internal/str_scan.h b/include/MSL/internal/str_scan.h deleted file mode 100644 index 1d35f589..00000000 --- a/include/MSL/internal/str_scan.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef MSL_INTERNAL_STR_SCAN_H -#define MSL_INTERNAL_STR_SCAN_H - -#include "stdio_api.h" - -enum scan_states { - start = 0x01, - check_for_zero = 0x02, - leading_zero = 0x04, - need_digit = 0x08, - digit_loop = 0x10, - finished = 0x20, - failure = 0x40 -}; - -#define final_state(scan_state) ((scan_state) & (finished | failure)) -#define success(scan_state) ((scan_state) & (leading_zero | digit_loop | finished)) - -#define fetch() (count++, (*ReadProc)(ReadProcArg, 0, __GetAChar)) -#define unfetch(c) ((*ReadProc)(ReadProcArg, c, __UngetAChar)) - -#endif // MSL_INTERNAL_STR_SCAN_H diff --git a/src/MSL/locale.c b/src/MSL/locale.c index c03a0186..1a3828bb 100644 --- a/src/MSL/locale.c +++ b/src/MSL/locale.c @@ -5,15 +5,15 @@ #include "ansi_fp.h" struct lconv __lconv = { - "", - "", - "", - "", - "", - "", - "", - "", - "", + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 127, 127, 127, @@ -21,7 +21,7 @@ struct lconv __lconv = { 127, 127, 127, - "", + 0, 127, 127, 127, @@ -69,12 +69,12 @@ struct _loc_coll_cmpt _loc_coll_C = { struct _loc_mon_cmpt _loc_mon_C = { "C", - "", - "", - "", - "", - "", - "", + 0, + 0, + 0, + 0, + 0, + 0, 127, 127, 127, @@ -82,7 +82,7 @@ struct _loc_mon_cmpt _loc_mon_C = { 127, 127, 127, - "", + 0, 127, 127, 127, @@ -94,9 +94,9 @@ struct _loc_mon_cmpt _loc_mon_C = { struct _loc_num_cmpt _loc_num_C = { "C", - "", - "", - "" + 0, + 0, + 0 }; struct _loc_time_cmpt _loc_tim_C = { @@ -108,7 +108,7 @@ struct _loc_time_cmpt _loc_tim_C = { _Time_Format_C, _Day_Names_C, _Month_Names_C, - "" + 0 }; struct __locale _current_locale = { diff --git a/src/MSL/scanf.c b/src/MSL/scanf.c index 497bbfc5..016d5fd5 100644 --- a/src/MSL/scanf.c +++ b/src/MSL/scanf.c @@ -3,7 +3,6 @@ #include "sformatter.h" #include "stdarg.h" #include "stdio_api.h" -#include "str_scan.h" #include @@ -24,8 +23,6 @@ extern long double __strtold(int max_width, int (*ReadProc)(void*, int, int), vo extern unsigned long long __strtoull(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* negative, int* overflow); extern unsigned long __strtoul(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* negative, int* overflow); - - int mbtowc(wchar_t* pDest, const char* s, size_t num); static const char* parse_format(const char* format_string, diff --git a/src/MSL/strtold.c b/src/MSL/strtold.c index 46de6c14..ebd2f8dc 100644 --- a/src/MSL/strtold.c +++ b/src/MSL/strtold.c @@ -5,7 +5,7 @@ #include "limits.h" #include "locale.h" #include "mem.h" -#include "str_scan.h" +#include "stdio_api.h" #pragma exceptions on @@ -14,7 +14,11 @@ extern double __dec2num(const decimal*); #define HUGE_VAL (*(double*)__double_huge) +#define success(scan_state) (scan_state & 3628) #define hex_success(count, scan_state) (count - 1 > 2 && scan_state & (398)) +#define final_state(scan_state) ((scan_state) & (2048 | 4096)) +#define fetch() (count++, (*ReadProc)(ReadProcArg, 0, __GetAChar)) +#define unfetch(c) ((*ReadProc)(ReadProcArg, c, __UngetAChar)) long double __strtold(int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* overflow) { diff --git a/src/MSL/strtoul.c b/src/MSL/strtoul.c index 5cc3cc7d..03e4ad58 100644 --- a/src/MSL/strtoul.c +++ b/src/MSL/strtoul.c @@ -3,10 +3,25 @@ #include "errno.h" #include "limits.h" #include "stdio.h" -#include "str_scan.h" +#include "stdio_api.h" #pragma exceptions on +enum scan_states { + start = 0x01, + check_for_zero = 0x02, + leading_zero = 0x04, + need_digit = 0x08, + digit_loop = 0x10, + finished = 0x20, + failure = 0x40 +}; + +#define final_state(scan_state) (scan_state & (0x20 | 0x40)) +#define success(scan_state) (scan_state & (0x4 | 0x10 | 0x20)) +#define fetch() (count++, (*ReadProc)(ReadProcArg, 0, __GetAChar)) +#define unfetch(c) ((*ReadProc)(ReadProcArg, c, __UngetAChar)) + // jumptable_80398FEC located in scanf unsigned long __strtoul(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg,