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-20 04:07:23 +03:00
parent 4df58c5155
commit 511ab7e99c
6 changed files with 108 additions and 82 deletions
@@ -7,10 +7,13 @@
__BEGIN_DECLS
#ifndef __locale_t_defined
#define __locale_t_defined 1
typedef enum { LOCALE_INVALID, LOCALE_POSIX, LOCALE_UTF8 } locale_t;
#endif
typedef enum { __ENC_ASCII, __ENC_UTF8 } __encoding_e;
struct __locale_t
{
const char* name;
__encoding_e encoding;
};
typedef struct __locale_t* locale_t;
__END_DECLS
+3 -4
View File
@@ -8,11 +8,10 @@ static const char* nl_langinfo_impl(nl_item item)
// only codeset is affected by current locales
if (item == CODESET)
{
switch (__getlocale(LC_CTYPE))
switch (__getlocale(LC_CTYPE)->encoding)
{
case LOCALE_INVALID: ASSERT_NOT_REACHED();
case LOCALE_UTF8: return "UTF-8";
case LOCALE_POSIX: return "ANSI_X3.4-1968";
case __ENC_ASCII: return "ANSI_X3.4-1968";
case __ENC_UTF8: return "UTF-8";
}
ASSERT_NOT_REACHED();
}
+56 -29
View File
@@ -5,35 +5,37 @@
#include <stdio.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] {
LOCALE_POSIX,
LOCALE_POSIX,
LOCALE_POSIX,
LOCALE_POSIX,
LOCALE_POSIX,
LOCALE_POSIX,
&s_locale_posix,
&s_locale_posix,
&s_locale_posix,
&s_locale_posix,
&s_locale_posix,
&s_locale_posix,
};
static_assert(LC_ALL == 6);
static locale_t str_to_locale(const char* locale)
{
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)
return LOCALE_UTF8;
return LOCALE_INVALID;
}
return &s_locale_utf8;
static const char* locale_to_str(locale_t locale)
{
if (locale == LOCALE_POSIX)
return "C";
if (locale == LOCALE_UTF8)
return "C.UTF-8";
ASSERT_NOT_REACHED();
return nullptr;
}
struct lconv* localeconv(void)
@@ -80,17 +82,18 @@ char* setlocale(int category, const char* locale_str)
case LC_MONETARY:
case LC_NUMERIC:
case LC_TIME:
strcpy(s_locale_buffer, locale_to_str(s_current_locales[category]));
strcpy(s_locale_buffer, s_current_locales[category]->name);
break;
case LC_ALL:
sprintf(s_locale_buffer, "%s;%s;%s;%s;%s;%s",
locale_to_str(s_current_locales[0]),
locale_to_str(s_current_locales[1]),
locale_to_str(s_current_locales[2]),
locale_to_str(s_current_locales[3]),
locale_to_str(s_current_locales[4]),
locale_to_str(s_current_locales[5])
s_current_locales[0]->name,
s_current_locales[1]->name,
s_current_locales[2]->name,
s_current_locales[3]->name,
s_current_locales[4]->name,
s_current_locales[5]->name
);
static_assert(LC_ALL == 6);
break;
default:
return nullptr;
@@ -100,7 +103,7 @@ char* setlocale(int category, const char* locale_str)
}
locale_t locale = str_to_locale(locale_str);
if (locale == LOCALE_INVALID)
if (locale == nullptr)
return nullptr;
switch (category)
@@ -121,7 +124,7 @@ char* setlocale(int category, const char* locale_str)
return nullptr;
}
strcpy(s_locale_buffer, locale_to_str(locale));
strcpy(s_locale_buffer, locale->name);
return s_locale_buffer;
}
@@ -137,6 +140,30 @@ locale_t __getlocale(int category)
case LC_TIME:
return s_current_locales[category];
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;
}
+23 -25
View File
@@ -355,13 +355,12 @@ int mblen(const char* s, size_t n)
return 0;
if (n == 0)
return -1;
switch (__getlocale(LC_CTYPE))
switch (__getlocale(LC_CTYPE)->encoding)
{
case LOCALE_INVALID:
ASSERT_NOT_REACHED();
case LOCALE_POSIX:
case __ENC_ASCII:
return 1;
case LOCALE_UTF8:
case __ENC_UTF8:
const auto bytes = BAN::UTF8::byte_length(*s);
if (bytes == BAN::UTF8::invalid)
return -1;
@@ -369,6 +368,7 @@ int mblen(const char* s, size_t n)
return -1;
return bytes;
}
ASSERT_NOT_REACHED();
}
@@ -378,15 +378,13 @@ int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n)
if (s == nullptr)
return 0;
switch (__getlocale(LC_CTYPE))
switch (__getlocale(LC_CTYPE)->encoding)
{
case LOCALE_INVALID:
ASSERT_NOT_REACHED();
case LOCALE_POSIX:
case __ENC_ASCII:
if (pwc != nullptr)
*pwc = *s;
return *s ? 1 : 0;
case LOCALE_UTF8:
case __ENC_UTF8:
const auto* us = reinterpret_cast<const unsigned char*>(s);
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;
switch (__getlocale(LC_CTYPE))
switch (__getlocale(LC_CTYPE)->encoding)
{
case LOCALE_INVALID:
ASSERT_NOT_REACHED();
case LOCALE_POSIX:
case __ENC_ASCII:
if (pwcs == nullptr)
written = strlen(s);
else for (; s[written] && written < n; written++)
pwcs[written] = s[written];
break;
case LOCALE_UTF8:
case __ENC_UTF8:
{
const auto* us = reinterpret_cast<const unsigned char*>(s);
for (; *us && (pwcs == nullptr || written < n); written++)
{
@@ -442,6 +439,9 @@ size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n)
}
break;
}
default:
ASSERT_NOT_REACHED();
}
if (pwcs != nullptr && written < n)
pwcs[written] = L'\0';
@@ -454,14 +454,12 @@ int wctomb(char* s, wchar_t wchar)
if (s == nullptr)
return 0;
switch (__getlocale(LC_CTYPE))
switch (__getlocale(LC_CTYPE)->encoding)
{
case locale_t::LOCALE_INVALID:
ASSERT_NOT_REACHED();
case locale_t::LOCALE_POSIX:
case __ENC_ASCII:
*s = wchar;
return wchar ? 1 : 0;
case locale_t::LOCALE_UTF8:
case __ENC_UTF8:
char buffer[5];
if (!BAN::UTF8::from_codepoints(&wchar, 1, buffer))
return -1;
@@ -477,11 +475,9 @@ size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n)
{
size_t written = 0;
switch (__getlocale(LC_CTYPE))
switch (__getlocale(LC_CTYPE)->encoding)
{
case locale_t::LOCALE_INVALID:
ASSERT_NOT_REACHED();
case locale_t::LOCALE_POSIX:
case __ENC_ASCII:
for (size_t i = 0; pwcs[i] && (s == nullptr || written < n); i++)
{
if (pwcs[i] > 0xFF)
@@ -491,7 +487,7 @@ size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n)
written++;
}
break;
case locale_t::LOCALE_UTF8:
case __ENC_UTF8:
for (size_t i = 0; pwcs[i] && (s == nullptr || written < n); i++)
{
char buffer[5];
@@ -507,6 +503,8 @@ size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n)
written += len;
}
break;
default:
ASSERT_NOT_REACHED();
}
if (s && written < n)
+4 -5
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)
{
switch (locale)
switch (locale->encoding)
{
case LOCALE_INVALID:
ASSERT_NOT_REACHED();
case LOCALE_POSIX:
case __ENC_ASCII:
return strcmp(s1, s2);
case LOCALE_UTF8:
case __ENC_UTF8:
{
const unsigned char* u1 = (unsigned char*)s1;
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;
}
}
ASSERT_NOT_REACHED();
}
+15 -15
View File
@@ -45,19 +45,19 @@ size_t wcrtomb(char* __restrict s, wchar_t ws, mbstate_t* __restrict ps)
if (s == nullptr)
return 1;
switch (__getlocale(LC_CTYPE))
switch (__getlocale(LC_CTYPE)->encoding)
{
case locale_t::LOCALE_INVALID:
ASSERT_NOT_REACHED();
case locale_t::LOCALE_POSIX:
case __ENC_ASCII:
if (ws > 0x7F)
break;
*s = ws;
return 1;
case locale_t::LOCALE_UTF8:
case __ENC_UTF8:
if (!BAN::UTF8::from_codepoints(&ws, 1, s))
break;
return BAN::UTF8::byte_length(s[0]);
default:
ASSERT_NOT_REACHED();
}
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);
size_t bytes = -1;
switch (locale)
switch (locale->encoding)
{
case locale_t::LOCALE_INVALID:
ASSERT_NOT_REACHED();
case locale_t::LOCALE_POSIX:
case __ENC_ASCII:
bytes = 1;
break;
case locale_t::LOCALE_UTF8:
case __ENC_UTF8:
if (auto b = BAN::UTF8::byte_length(s[0]); b != BAN::UTF8::invalid)
bytes = b;
break;
default:
ASSERT_NOT_REACHED();
}
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;
wchar_t codepoint = WEOF;
switch (locale)
switch (locale->encoding)
{
case locale_t::LOCALE_INVALID:
ASSERT_NOT_REACHED();
case locale_t::LOCALE_POSIX:
case __ENC_ASCII:
codepoint = s[0];
break;
case locale_t::LOCALE_UTF8:
case __ENC_UTF8:
if (auto cp = BAN::UTF8::to_codepoint(s); cp != BAN::UTF8::invalid)
codepoint = cp;
break;
default:
ASSERT_NOT_REACHED();
}
if (codepoint == WEOF)