From e622e75e531e689589811b04087c4dd5981e1360 Mon Sep 17 00:00:00 2001 From: zerico <71151164+ZERICO2005@users.noreply.github.com> Date: Sat, 1 Nov 2025 23:31:37 -0600 Subject: [PATCH] added locale.h and added more wide-char prototypes --- src/libc/header_test.c | 1 + src/libc/include/__wchar_def.h | 7 --- src/libc/include/cdefs.h | 13 +++-- src/libc/include/inttypes.h | 24 ++++----- src/libc/include/limits.h | 4 ++ src/libc/include/locale.h | 53 ++++++++++++++++++++ src/libc/include/stddef.h | 7 --- src/libc/include/stdlib.h | 14 ++++++ src/libc/include/string.h | 4 ++ src/libc/include/wchar.h | 90 ++++++++++++++++++++++++++++++++++ src/libc/include/wctype.h | 12 +++++ src/libc/locale.c | 51 +++++++++++++++++++ src/libcxx/header_test.cpp | 2 + src/libcxx/include/cinttypes | 3 ++ src/libcxx/include/clocale | 16 ++++++ src/libcxx/include/cstdlib | 5 ++ src/libcxx/include/cstring | 3 ++ src/libcxx/include/cwchar | 44 +++++++++++++++++ src/libcxx/include/cwctype | 7 +++ 19 files changed, 331 insertions(+), 29 deletions(-) create mode 100644 src/libc/include/locale.h create mode 100644 src/libc/locale.c create mode 100644 src/libcxx/include/clocale diff --git a/src/libc/header_test.c b/src/libc/header_test.c index 36dbf7419..edbbff196 100644 --- a/src/libc/header_test.c +++ b/src/libc/header_test.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/src/libc/include/__wchar_def.h b/src/libc/include/__wchar_def.h index aa35a1a84..e31f1751d 100644 --- a/src/libc/include/__wchar_def.h +++ b/src/libc/include/__wchar_def.h @@ -3,13 +3,6 @@ #include -#ifndef _WCHAR_T_DEFINED -#define _WCHAR_T_DEFINED -#ifndef __cplusplus -typedef __WCHAR_TYPE__ wchar_t; -#endif /* __cplusplus */ -#endif /* _WCHAR_T_DEFINED */ - #ifndef _WINT_T_DEFINED #define _WINT_T_DEFINED typedef __WINT_TYPE__ wint_t; diff --git a/src/libc/include/cdefs.h b/src/libc/include/cdefs.h index 8f97878f8..a56bc4a2b 100644 --- a/src/libc/include/cdefs.h +++ b/src/libc/include/cdefs.h @@ -36,9 +36,16 @@ # endif /* __cplusplus */ #endif /* NULL */ -#ifndef SIZE_T_DEFINED -#define SIZE_T_DEFINED +#ifndef _SIZE_T_DEFINED +#define _SIZE_T_DEFINED typedef __SIZE_TYPE__ size_t; -#endif /* SIZE_T_DEFINED */ +#endif /* _SIZE_T_DEFINED */ + +#ifndef _WCHAR_T_DEFINED +#define _WCHAR_T_DEFINED +#ifndef __cplusplus +typedef __WCHAR_TYPE__ wchar_t; +#endif /* __cplusplus */ +#endif /* _WCHAR_T_DEFINED */ #endif /* _CDEFS_H */ diff --git a/src/libc/include/inttypes.h b/src/libc/include/inttypes.h index d762282e7..deb1d32c5 100644 --- a/src/libc/include/inttypes.h +++ b/src/libc/include/inttypes.h @@ -177,21 +177,21 @@ typedef struct { __BEGIN_DECLS -extern intmax_t imaxabs(intmax_t __n) __NOEXCEPT_CONST; +intmax_t imaxabs(intmax_t __n) __NOEXCEPT_CONST; -extern imaxdiv_t imaxdiv(intmax_t __numer, intmax_t __denom) __NOEXCEPT_CONST; +imaxdiv_t imaxdiv(intmax_t __numer, intmax_t __denom) __NOEXCEPT_CONST; -intmax_t strtoimax( - const char *__restrict nptr, - char **__restrict endptr, - int base -) __attribute__((nonnull(1))); +intmax_t strtoimax(const char *__restrict nptr, char **__restrict endptr, int base) + __attribute__((nonnull(1))); -uintmax_t strtoumax( - const char *__restrict nptr, - char **__restrict endptr, - int base -) __attribute__((nonnull(1))); +uintmax_t strtoumax(const char *__restrict nptr, char **__restrict endptr, int base) + __attribute__((nonnull(1))); + +intmax_t wcstoimax(const wchar_t *__restrict nptr, wchar_t **__restrict endptr, int base) + __attribute__((nonnull(1))); + +uintmax_t wcstoumax(const wchar_t *__restrict nptr, wchar_t **__restrict endptr, int base) + __attribute__((nonnull(1))); __END_DECLS diff --git a/src/libc/include/limits.h b/src/libc/include/limits.h index e85216285..ecda03476 100644 --- a/src/libc/include/limits.h +++ b/src/libc/include/limits.h @@ -48,4 +48,8 @@ #define ULLONG_MAX __ULONG_LONG_MAX__ #define ULLONG_WIDTH __LLONG_WIDTH__ +#ifndef MB_LEN_MAX +#define MB_LEN_MAX 1 +#endif /* MB_LEN_MAX */ + #endif /* _LIMITS_H */ diff --git a/src/libc/include/locale.h b/src/libc/include/locale.h new file mode 100644 index 000000000..ed0b19ad8 --- /dev/null +++ b/src/libc/include/locale.h @@ -0,0 +1,53 @@ +#ifndef _LOCALE_H +#define _LOCALE_H + +#include + +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_MAX */ + char p_cs_precedes; /* CHAR_MAX */ + char n_cs_precedes; /* CHAR_MAX */ + char p_sep_by_space; /* CHAR_MAX */ + char n_sep_by_space; /* CHAR_MAX */ + char p_sign_posn; /* CHAR_MAX */ + char n_sign_posn; /* CHAR_MAX */ + char* int_curr_symbol; /* "" */ + char int_frac_digits; /* CHAR_MAX */ + char int_p_cs_precedes; /* CHAR_MAX */ + char int_n_cs_precedes; /* CHAR_MAX */ + char int_p_sep_by_space; /* CHAR_MAX */ + char int_n_sep_by_space; /* CHAR_MAX */ + char int_p_sign_posn; /* CHAR_MAX */ + char int_n_sign_posn; /* CHAR_MAX */ +}; + +#define LC_COLLATE (0x010) +#define LC_CTYPE (0x020) +#define LC_MONETARY (0x040) +#define LC_NUMERIC (0x080) +#define LC_TIME (0x100) +#define LC_MESSAGES (0x200) +#define LC_ALL (LC_COLLATE | LC_CTYPE | LC_MONETARY | LC_NUMERIC | LC_TIME | LC_MESSAGES) + +#ifdef __cplusplus +extern "C" { +#endif + +char* setlocale(int category, const char* locale); + +struct lconv* localeconv(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _LOCALE_H */ diff --git a/src/libc/include/stddef.h b/src/libc/include/stddef.h index 72b90e5c7..d8d4265b7 100644 --- a/src/libc/include/stddef.h +++ b/src/libc/include/stddef.h @@ -7,13 +7,6 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t; -#ifndef _WCHAR_T_DEFINED -#define _WCHAR_T_DEFINED -#ifndef __cplusplus -typedef __WCHAR_TYPE__ wchar_t; -#endif /* __cplusplus */ -#endif /* _WCHAR_T_DEFINED */ - #if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L typedef struct { long long __max_align_ll __attribute__((__aligned__(__alignof__( long long)))); diff --git a/src/libc/include/stdlib.h b/src/libc/include/stdlib.h index d4a0d8920..3faa63441 100644 --- a/src/libc/include/stdlib.h +++ b/src/libc/include/stdlib.h @@ -123,6 +123,20 @@ lldiv_t lldiv(long long numer, long long denom); i48div_t i48div(signed __int48 numer, signed __int48 denom) __NOEXCEPT_CONST; #endif /* __SIZEOF_INT48__ */ +int mblen(const char* s, size_t n); + +int mbtowc(wchar_t* pwc, const char* s, size_t n); + +int wctomb(char* s, wchar_t wchar); + +size_t mbstowcs(wchar_t* pwcs, const char* s, size_t n); + +size_t wcstombs(char* s, const wchar_t* pwcs, size_t n); + +int __mb_cur_max(void); + +#define MB_CUR_MAX __mb_cur_max() + __END_DECLS #endif /* _STDLIB_H */ diff --git a/src/libc/include/string.h b/src/libc/include/string.h index 67cc527ec..e7bf7f18e 100644 --- a/src/libc/include/string.h +++ b/src/libc/include/string.h @@ -118,6 +118,10 @@ int strncasecmp(const char *s1, const char *s2, size_t n) char* strerror(int errnum); +int strcoll(const char *s1, const char *s2); + +size_t strxfrm(char *__restrict dest, const char *__restrict src, size_t n); + __END_DECLS #endif /* _STRING_H */ diff --git a/src/libc/include/wchar.h b/src/libc/include/wchar.h index 0ecf88c56..3ad611a1e 100644 --- a/src/libc/include/wchar.h +++ b/src/libc/include/wchar.h @@ -2,6 +2,16 @@ #define _WCHAR_H #include <__wchar_def.h> +#include +#include + +typedef struct { + int __count; + union { + wint_t __value; + unsigned char __bytes[sizeof(wint_t)]; + }; +} mbstate_t; __BEGIN_DECLS @@ -65,6 +75,86 @@ int wcscmp(const wchar_t *s1, const wchar_t *s2) int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n) __attribute__((nonnull(1, 2))); +int wprintf(const wchar_t *__restrict format, ...); + +int vwprintf(const wchar_t *__restrict format, va_list va); + +int swprintf(wchar_t *__restrict buffer, size_t count, const wchar_t *__restrict format, ...); + +int vswprintf(wchar_t *__restrict buffer, size_t count, const wchar_t *__restrict format, va_list va); + +int fwprintf(FILE *__restrict stream, const wchar_t *__restrict format, ...); + +int vfwprintf(FILE *__restrict stream, const wchar_t *__restrict format, va_list va); + +int wscanf(const wchar_t *__restrict format, ...); + +int vwscanf(const wchar_t *__restrict format, va_list arg); + +int swscanf(const wchar_t *__restrict s, const wchar_t *__restrict format, ...); + +int vswscanf(const wchar_t *__restrict s, const wchar_t *__restrict format, va_list arg); + +int fwscanf(FILE *__restrict stream, const wchar_t *__restrict format, ...); + +int vfwscanf(FILE *__restrict stream, const wchar_t *__restrict format, va_list arg); + +wint_t fgetwc(FILE *stream); + +wchar_t *fgetws(wchar_t *__restrict s, int n, FILE *__restrict stream); + +wint_t fputwc(wchar_t c, FILE *stream); + +int fputws(const wchar_t *__restrict s, FILE *__restrict stream); + +int fwide(FILE *stream, int mode); + +wint_t getwc(FILE *stream); + +wint_t getwchar(void); + +wint_t putwc(wchar_t c, FILE *stream); + +wint_t putwchar(wchar_t c); + +wint_t ungetwc(wint_t c, FILE *stream); + +float wcstof(const wchar_t *__restrict nptr, wchar_t * *__restrict endptr); + +double wcstod(const wchar_t *__restrict nptr, wchar_t **__restrict endptr); + +long double wcstold(const wchar_t *__restrict nptr, wchar_t **__restrict endptr); + +long wcstol(const wchar_t *__restrict nptr, wchar_t **__restrict endptr, int base); + +long long wcstoll(const wchar_t *__restrict nptr, wchar_t **__restrict endptr, int base); + +unsigned long wcstoul(const wchar_t *__restrict nptr, wchar_t **__restrict endptr, int base); + +unsigned long long wcstoull(const wchar_t *__restrict nptr, wchar_t **__restrict endptr, int base); + +size_t wcsftime(wchar_t *__restrict s, size_t maxsize, const wchar_t *__restrict format, const struct tm *__restrict timeptr); + +int wcscoll(const wchar_t* s1, const wchar_t* s2); + +size_t wcsxfrm(wchar_t *__restrict s1, const wchar_t *__restrict s2, size_t n); + +wint_t btowc(int c); + +int wctob(wint_t c); + +int mbsinit(const mbstate_t* ps); + +size_t mbrlen(const char *__restrict s, size_t n, mbstate_t *__restrict ps); + +size_t mbrtowc(wchar_t *__restrict pwc, const char *__restrict s, size_t n, mbstate_t *__restrict ps); + +size_t wcrtomb(char *__restrict s, wchar_t wc, mbstate_t *__restrict ps); + +size_t mbsrtowcs(wchar_t *__restrict dst, const char* *__restrict src, size_t len, mbstate_t *__restrict ps); + +size_t wcsrtombs(char *__restrict dst, const wchar_t **__restrict src, size_t len, mbstate_t *__restrict ps); + __END_DECLS #endif /* _WCHAR_H */ diff --git a/src/libc/include/wctype.h b/src/libc/include/wctype.h index 9b38b87a0..b8afaffbb 100644 --- a/src/libc/include/wctype.h +++ b/src/libc/include/wctype.h @@ -3,6 +3,10 @@ #include <__wchar_def.h> +typedef int wctrans_t; + +typedef int wctype_t; + __BEGIN_DECLS int iswalnum(wint_t wc); @@ -33,6 +37,14 @@ wint_t towlower(wint_t wc); wint_t towupper(wint_t wc); +wint_t towctrans(wint_t wc, wctrans_t desc); + +wctrans_t wctrans(const char *str); + +int iswctype(wint_t wc, wctype_t desc); + +wctype_t wctype(const char *property); + __END_DECLS #endif /* _WCTYPE_H */ diff --git a/src/libc/locale.c b/src/libc/locale.c new file mode 100644 index 000000000..3eb7110dd --- /dev/null +++ b/src/libc/locale.c @@ -0,0 +1,51 @@ +#include +#include + +const struct lconv __c_locale = { + .decimal_point = ".", + .thousands_sep = "", + .grouping = "", + .mon_decimal_point = "", + .mon_thousands_sep = "", + .mon_grouping = "", + .positive_sign = "", + .negative_sign = "", + .currency_symbol = "", + .frac_digits = CHAR_MAX, + .p_cs_precedes = CHAR_MAX, + .n_cs_precedes = CHAR_MAX, + .p_sep_by_space = CHAR_MAX, + .n_sep_by_space = CHAR_MAX, + .p_sign_posn = CHAR_MAX, + .n_sign_posn = CHAR_MAX, + .int_curr_symbol = "", + .int_frac_digits = CHAR_MAX, + .int_p_cs_precedes = CHAR_MAX, + .int_n_cs_precedes = CHAR_MAX, + .int_p_sep_by_space = CHAR_MAX, + .int_n_sep_by_space = CHAR_MAX, + .int_p_sign_posn = CHAR_MAX, + .int_n_sign_posn = CHAR_MAX, +}; + +char *setlocale(__attribute__((__unused__)) int category, const char *locale) { + // query the locale without modifiying it + if (locale == NULL) { + return "C"; + } + // use preferred locale (the "C" locale) + if (locale[0] == '\0') { + return "C"; + } + // use the "C" locale + if (locale[0] == 'C' && locale[1] == '\0') { + return "C"; + } + // unknown locale + return NULL; +} + +struct lconv *localeconv(void) { + // it is undefined behavior to modify the returned object + return (struct lconv*)&__c_locale; +} diff --git a/src/libcxx/header_test.cpp b/src/libcxx/header_test.cpp index e41236337..ab45ec624 100644 --- a/src/libcxx/header_test.cpp +++ b/src/libcxx/header_test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #if __cplusplus >= 201907L #include @@ -52,6 +53,7 @@ #include #include #include +#include #include #include #include diff --git a/src/libcxx/include/cinttypes b/src/libcxx/include/cinttypes index b77c0bfe7..e806b759b 100644 --- a/src/libcxx/include/cinttypes +++ b/src/libcxx/include/cinttypes @@ -17,6 +17,9 @@ using ::imaxdiv; using ::strtoimax; using ::strtoumax; +using ::wcstoimax; +using ::wcstoumax; + #if __INTMAX_WIDTH__ > __LLONG_WIDTH__ inline constexpr intmax_t abs(intmax_t __x) { return imaxabs(__x); } inline constexpr imaxdiv_t div(intmax_t __x, intmax_t __y) { return imaxdiv(__x, __y); } diff --git a/src/libcxx/include/clocale b/src/libcxx/include/clocale new file mode 100644 index 000000000..4bdf85831 --- /dev/null +++ b/src/libcxx/include/clocale @@ -0,0 +1,16 @@ +// -*- C++ -*- +#ifndef _EZCXX_CLOCALE +#define _EZCXX_CLOCALE + +#include + +#pragma clang system_header + +namespace std { +using ::lconv; + +using ::setlocale; +using ::localeconv; +} // namespace std + +#endif // _EZCXX_CLOCALE diff --git a/src/libcxx/include/cstdlib b/src/libcxx/include/cstdlib index 135cc3369..b4a23357d 100644 --- a/src/libcxx/include/cstdlib +++ b/src/libcxx/include/cstdlib @@ -52,6 +52,11 @@ using ::i48div; inline i48div_t div(signed __int48 __x, signed __int48 __y) { return i48div(__x, __y); } #endif // __SIZEOF_INT48__ +using ::mblen; +using ::mbtowc; +using ::wctomb; +using ::mbstowcs; +using ::wcstombs; } // namespace std #endif // _EZCXX_CSTDLIB diff --git a/src/libcxx/include/cstring b/src/libcxx/include/cstring index 7adbf29d1..887baa6c5 100644 --- a/src/libcxx/include/cstring +++ b/src/libcxx/include/cstring @@ -47,6 +47,9 @@ using ::strncmp; using ::strcasecmp; using ::strncasecmp; using ::strerror; + +using ::strcoll; +using ::strxfrm; } // namespace std #endif // _EZCXX_CSTRING diff --git a/src/libcxx/include/cwchar b/src/libcxx/include/cwchar index dd230543e..e4056ab72 100644 --- a/src/libcxx/include/cwchar +++ b/src/libcxx/include/cwchar @@ -8,6 +8,9 @@ namespace std { using ::wint_t; +using ::mbstate_t; +using ::size_t; +using ::tm; using ::wmemcpy; using ::wmemmove; @@ -29,6 +32,47 @@ using ::wcslen; using ::wcsnlen; using ::wcscmp; using ::wcsncmp; + +using ::wprintf; +using ::vwprintf; +using ::swprintf; +using ::vswprintf; +using ::fwprintf; +using ::vfwprintf; +using ::wscanf; +using ::vwscanf; +using ::swscanf; +using ::vswscanf; +using ::fwscanf; +using ::vfwscanf; +using ::fgetwc; +using ::fgetws; +using ::fputwc; +using ::fputws; +using ::fwide; +using ::getwc; +using ::getwchar; +using ::putwc; +using ::putwchar; +using ::ungetwc; +using ::wcstof; +using ::wcstod; +using ::wcstold; +using ::wcstol; +using ::wcstoll; +using ::wcstoul; +using ::wcstoull; +using ::wcsftime; +using ::wcscoll; +using ::wcsxfrm; +using ::btowc; +using ::wctob; +using ::mbsinit; +using ::mbrlen; +using ::mbrtowc; +using ::wcrtomb; +using ::mbsrtowcs; +using ::wcsrtombs; } // namespace std #endif // _EZCXX_CWCHAR diff --git a/src/libcxx/include/cwctype b/src/libcxx/include/cwctype index f45d2e3a2..1e1278bcd 100644 --- a/src/libcxx/include/cwctype +++ b/src/libcxx/include/cwctype @@ -8,6 +8,8 @@ namespace std { using ::wint_t; +using ::wctrans_t; +using ::wctype_t; using ::iswalnum; using ::iswalpha; @@ -23,6 +25,11 @@ using ::iswupper; using ::iswxdigit; using ::towlower; using ::towupper; + +using ::towctrans; +using ::wctrans; +using ::iswctype; +using ::wctype; } // namespace std #endif // _EZCXX_CWCTYPE