LibC: Define locale_t as an poiter

A lot of ports seem to depend on this casting nullptr into locale_t
This commit is contained in:
2026-07-10 00:23:56 +03:00
parent 4df58c5155
commit 511ab7e99c
6 changed files with 108 additions and 82 deletions

View File

@@ -7,10 +7,13 @@
__BEGIN_DECLS __BEGIN_DECLS
#ifndef __locale_t_defined typedef enum { __ENC_ASCII, __ENC_UTF8 } __encoding_e;
#define __locale_t_defined 1 struct __locale_t
typedef enum { LOCALE_INVALID, LOCALE_POSIX, LOCALE_UTF8 } locale_t; {
#endif const char* name;
__encoding_e encoding;
};
typedef struct __locale_t* locale_t;
__END_DECLS __END_DECLS

View File

@@ -8,11 +8,10 @@ static const char* nl_langinfo_impl(nl_item item)
// only codeset is affected by current locales // only codeset is affected by current locales
if (item == CODESET) if (item == CODESET)
{ {
switch (__getlocale(LC_CTYPE)) switch (__getlocale(LC_CTYPE)->encoding)
{ {
case LOCALE_INVALID: ASSERT_NOT_REACHED(); case __ENC_ASCII: return "ANSI_X3.4-1968";
case LOCALE_UTF8: return "UTF-8"; case __ENC_UTF8: return "UTF-8";
case LOCALE_POSIX: return "ANSI_X3.4-1968";
} }
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }

View File

@@ -5,35 +5,37 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
static __locale_t s_locale_posix {
.name = "C",
.encoding = __ENC_ASCII,
};
static __locale_t s_locale_utf8 {
.name = "C.UTF-8",
.encoding = __ENC_UTF8,
};
static locale_t s_current_locales[LC_ALL] { static locale_t s_current_locales[LC_ALL] {
LOCALE_POSIX, &s_locale_posix,
LOCALE_POSIX, &s_locale_posix,
LOCALE_POSIX, &s_locale_posix,
LOCALE_POSIX, &s_locale_posix,
LOCALE_POSIX, &s_locale_posix,
LOCALE_POSIX, &s_locale_posix,
}; };
static_assert(LC_ALL == 6); static_assert(LC_ALL == 6);
static locale_t str_to_locale(const char* locale) static locale_t str_to_locale(const char* locale)
{ {
if (*locale == '\0') if (*locale == '\0')
return LOCALE_UTF8; return &s_locale_utf8;
if (strcmp(locale, "C") == 0 || strcmp(locale, "POSIX") == 0)
return &s_locale_posix;
if (strcmp(locale, "C") == 0 || strcmp(locale, "LOCALE_POSIX") == 0)
return LOCALE_POSIX;
if (strcmp(locale, "C.UTF-8") == 0) if (strcmp(locale, "C.UTF-8") == 0)
return LOCALE_UTF8; return &s_locale_utf8;
return LOCALE_INVALID;
}
static const char* locale_to_str(locale_t locale) return nullptr;
{
if (locale == LOCALE_POSIX)
return "C";
if (locale == LOCALE_UTF8)
return "C.UTF-8";
ASSERT_NOT_REACHED();
} }
struct lconv* localeconv(void) struct lconv* localeconv(void)
@@ -80,17 +82,18 @@ char* setlocale(int category, const char* locale_str)
case LC_MONETARY: case LC_MONETARY:
case LC_NUMERIC: case LC_NUMERIC:
case LC_TIME: case LC_TIME:
strcpy(s_locale_buffer, locale_to_str(s_current_locales[category])); strcpy(s_locale_buffer, s_current_locales[category]->name);
break; break;
case LC_ALL: case LC_ALL:
sprintf(s_locale_buffer, "%s;%s;%s;%s;%s;%s", sprintf(s_locale_buffer, "%s;%s;%s;%s;%s;%s",
locale_to_str(s_current_locales[0]), s_current_locales[0]->name,
locale_to_str(s_current_locales[1]), s_current_locales[1]->name,
locale_to_str(s_current_locales[2]), s_current_locales[2]->name,
locale_to_str(s_current_locales[3]), s_current_locales[3]->name,
locale_to_str(s_current_locales[4]), s_current_locales[4]->name,
locale_to_str(s_current_locales[5]) s_current_locales[5]->name
); );
static_assert(LC_ALL == 6);
break; break;
default: default:
return nullptr; return nullptr;
@@ -100,7 +103,7 @@ char* setlocale(int category, const char* locale_str)
} }
locale_t locale = str_to_locale(locale_str); locale_t locale = str_to_locale(locale_str);
if (locale == LOCALE_INVALID) if (locale == nullptr)
return nullptr; return nullptr;
switch (category) switch (category)
@@ -121,7 +124,7 @@ char* setlocale(int category, const char* locale_str)
return nullptr; return nullptr;
} }
strcpy(s_locale_buffer, locale_to_str(locale)); strcpy(s_locale_buffer, locale->name);
return s_locale_buffer; return s_locale_buffer;
} }
@@ -137,6 +140,30 @@ locale_t __getlocale(int category)
case LC_TIME: case LC_TIME:
return s_current_locales[category]; return s_current_locales[category];
default: default:
return LOCALE_INVALID; return nullptr;
} }
} }
#include <BAN/Debug.h>
locale_t newlocale(int category_mask, const char* locale, locale_t base)
{
(void)category_mask;
(void)locale;
(void)base;
dwarnln("TODO: newlocale");
return nullptr;
}
void freelocale(locale_t locobj)
{
(void)locobj;
dwarnln("TODO: freelocale");
}
locale_t uselocale(locale_t newloc)
{
(void)newloc;
dwarnln("TODO: uselocale");
return nullptr;
}

View File

@@ -355,13 +355,12 @@ int mblen(const char* s, size_t n)
return 0; return 0;
if (n == 0) if (n == 0)
return -1; return -1;
switch (__getlocale(LC_CTYPE))
switch (__getlocale(LC_CTYPE)->encoding)
{ {
case LOCALE_INVALID: case __ENC_ASCII:
ASSERT_NOT_REACHED();
case LOCALE_POSIX:
return 1; return 1;
case LOCALE_UTF8: case __ENC_UTF8:
const auto bytes = BAN::UTF8::byte_length(*s); const auto bytes = BAN::UTF8::byte_length(*s);
if (bytes == BAN::UTF8::invalid) if (bytes == BAN::UTF8::invalid)
return -1; return -1;
@@ -369,6 +368,7 @@ int mblen(const char* s, size_t n)
return -1; return -1;
return bytes; return bytes;
} }
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
@@ -378,15 +378,13 @@ int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n)
if (s == nullptr) if (s == nullptr)
return 0; return 0;
switch (__getlocale(LC_CTYPE)) switch (__getlocale(LC_CTYPE)->encoding)
{ {
case LOCALE_INVALID: case __ENC_ASCII:
ASSERT_NOT_REACHED();
case LOCALE_POSIX:
if (pwc != nullptr) if (pwc != nullptr)
*pwc = *s; *pwc = *s;
return *s ? 1 : 0; return *s ? 1 : 0;
case LOCALE_UTF8: case __ENC_UTF8:
const auto* us = reinterpret_cast<const unsigned char*>(s); const auto* us = reinterpret_cast<const unsigned char*>(s);
const uint32_t length = BAN::UTF8::byte_length(*us); const uint32_t length = BAN::UTF8::byte_length(*us);
@@ -416,17 +414,16 @@ size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n)
{ {
size_t written = 0; size_t written = 0;
switch (__getlocale(LC_CTYPE)) switch (__getlocale(LC_CTYPE)->encoding)
{ {
case LOCALE_INVALID: case __ENC_ASCII:
ASSERT_NOT_REACHED();
case LOCALE_POSIX:
if (pwcs == nullptr) if (pwcs == nullptr)
written = strlen(s); written = strlen(s);
else for (; s[written] && written < n; written++) else for (; s[written] && written < n; written++)
pwcs[written] = s[written]; pwcs[written] = s[written];
break; break;
case LOCALE_UTF8: case __ENC_UTF8:
{
const auto* us = reinterpret_cast<const unsigned char*>(s); const auto* us = reinterpret_cast<const unsigned char*>(s);
for (; *us && (pwcs == nullptr || written < n); written++) for (; *us && (pwcs == nullptr || written < n); written++)
{ {
@@ -441,6 +438,9 @@ size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n)
us += BAN::UTF8::byte_length(*us); us += BAN::UTF8::byte_length(*us);
} }
break; break;
}
default:
ASSERT_NOT_REACHED();
} }
if (pwcs != nullptr && written < n) if (pwcs != nullptr && written < n)
@@ -454,14 +454,12 @@ int wctomb(char* s, wchar_t wchar)
if (s == nullptr) if (s == nullptr)
return 0; return 0;
switch (__getlocale(LC_CTYPE)) switch (__getlocale(LC_CTYPE)->encoding)
{ {
case locale_t::LOCALE_INVALID: case __ENC_ASCII:
ASSERT_NOT_REACHED();
case locale_t::LOCALE_POSIX:
*s = wchar; *s = wchar;
return wchar ? 1 : 0; return wchar ? 1 : 0;
case locale_t::LOCALE_UTF8: case __ENC_UTF8:
char buffer[5]; char buffer[5];
if (!BAN::UTF8::from_codepoints(&wchar, 1, buffer)) if (!BAN::UTF8::from_codepoints(&wchar, 1, buffer))
return -1; return -1;
@@ -477,11 +475,9 @@ size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n)
{ {
size_t written = 0; size_t written = 0;
switch (__getlocale(LC_CTYPE)) switch (__getlocale(LC_CTYPE)->encoding)
{ {
case locale_t::LOCALE_INVALID: case __ENC_ASCII:
ASSERT_NOT_REACHED();
case locale_t::LOCALE_POSIX:
for (size_t i = 0; pwcs[i] && (s == nullptr || written < n); i++) for (size_t i = 0; pwcs[i] && (s == nullptr || written < n); i++)
{ {
if (pwcs[i] > 0xFF) if (pwcs[i] > 0xFF)
@@ -491,7 +487,7 @@ size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n)
written++; written++;
} }
break; break;
case locale_t::LOCALE_UTF8: case __ENC_UTF8:
for (size_t i = 0; pwcs[i] && (s == nullptr || written < n); i++) for (size_t i = 0; pwcs[i] && (s == nullptr || written < n); i++)
{ {
char buffer[5]; char buffer[5];
@@ -507,6 +503,8 @@ size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n)
written += len; written += len;
} }
break; break;
default:
ASSERT_NOT_REACHED();
} }
if (s && written < n) if (s && written < n)

View File

@@ -162,13 +162,11 @@ int strcoll(const char* s1, const char* s2)
int strcoll_l(const char *s1, const char *s2, locale_t locale) int strcoll_l(const char *s1, const char *s2, locale_t locale)
{ {
switch (locale) switch (locale->encoding)
{ {
case LOCALE_INVALID: case __ENC_ASCII:
ASSERT_NOT_REACHED();
case LOCALE_POSIX:
return strcmp(s1, s2); return strcmp(s1, s2);
case LOCALE_UTF8: case __ENC_UTF8:
{ {
const unsigned char* u1 = (unsigned char*)s1; const unsigned char* u1 = (unsigned char*)s1;
const unsigned char* u2 = (unsigned char*)s2; const unsigned char* u2 = (unsigned char*)s2;
@@ -195,6 +193,7 @@ int strcoll_l(const char *s1, const char *s2, locale_t locale)
return wc1 - wc2; return wc1 - wc2;
} }
} }
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }

View File

@@ -45,19 +45,19 @@ size_t wcrtomb(char* __restrict s, wchar_t ws, mbstate_t* __restrict ps)
if (s == nullptr) if (s == nullptr)
return 1; return 1;
switch (__getlocale(LC_CTYPE)) switch (__getlocale(LC_CTYPE)->encoding)
{ {
case locale_t::LOCALE_INVALID: case __ENC_ASCII:
ASSERT_NOT_REACHED();
case locale_t::LOCALE_POSIX:
if (ws > 0x7F) if (ws > 0x7F)
break; break;
*s = ws; *s = ws;
return 1; return 1;
case locale_t::LOCALE_UTF8: case __ENC_UTF8:
if (!BAN::UTF8::from_codepoints(&ws, 1, s)) if (!BAN::UTF8::from_codepoints(&ws, 1, s))
break; break;
return BAN::UTF8::byte_length(s[0]); return BAN::UTF8::byte_length(s[0]);
default:
ASSERT_NOT_REACHED();
} }
errno = EILSEQ; errno = EILSEQ;
@@ -74,17 +74,17 @@ size_t mbrtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n, mbst
const auto locale = __getlocale(LC_CTYPE); const auto locale = __getlocale(LC_CTYPE);
size_t bytes = -1; size_t bytes = -1;
switch (locale) switch (locale->encoding)
{ {
case locale_t::LOCALE_INVALID: case __ENC_ASCII:
ASSERT_NOT_REACHED();
case locale_t::LOCALE_POSIX:
bytes = 1; bytes = 1;
break; break;
case locale_t::LOCALE_UTF8: case __ENC_UTF8:
if (auto b = BAN::UTF8::byte_length(s[0]); b != BAN::UTF8::invalid) if (auto b = BAN::UTF8::byte_length(s[0]); b != BAN::UTF8::invalid)
bytes = b; bytes = b;
break; break;
default:
ASSERT_NOT_REACHED();
} }
if (bytes == static_cast<size_t>(-1)) if (bytes == static_cast<size_t>(-1))
@@ -97,17 +97,17 @@ size_t mbrtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n, mbst
return -1; return -1;
wchar_t codepoint = WEOF; wchar_t codepoint = WEOF;
switch (locale) switch (locale->encoding)
{ {
case locale_t::LOCALE_INVALID: case __ENC_ASCII:
ASSERT_NOT_REACHED();
case locale_t::LOCALE_POSIX:
codepoint = s[0]; codepoint = s[0];
break; break;
case locale_t::LOCALE_UTF8: case __ENC_UTF8:
if (auto cp = BAN::UTF8::to_codepoint(s); cp != BAN::UTF8::invalid) if (auto cp = BAN::UTF8::to_codepoint(s); cp != BAN::UTF8::invalid)
codepoint = cp; codepoint = cp;
break; break;
default:
ASSERT_NOT_REACHED();
} }
if (codepoint == WEOF) if (codepoint == WEOF)