libs/posix: Implemented new locale functions

Implemented the missing POSIX functions in <locale.h>:
newlocale, duplocale, uselocale, and freelocale, and also
provided missing type definitions for <locale.h>.

Implemented missing POSIX locale-based function variants.

Modified LocaleBackend so that it could support thread-local
locales.

Some glibc-like locale-related variables supporting
ctype and printf family of functions have also been updated
to reflect the thread-local variables present in the latest
glibc sources.

As there have been some modifications to global symbols
in libroot, libroot_stubs.c has been regenerated.

Bug: #17168
Change-Id: Ibf296c58c47d42d1d1dfb2ce64042442f2679431
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5351
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
Trung Nguyen
2022-07-11 16:30:16 +00:00
committed by waddlesplash
parent 86fa1c21e1
commit d338200e2b
64 changed files with 2116 additions and 965 deletions
+56 -18
View File
@@ -8,11 +8,11 @@
#include <SupportDefs.h>
#include <locale.h>
#include <time.h>
#include <wctype.h>
struct lconv;
struct lc_time_t;
struct locale_data; // glibc
@@ -22,29 +22,38 @@ namespace Libroot {
struct LocaleCtypeDataBridge {
const unsigned short** addrOfClassInfoTable;
const int** addrOfToLowerTable;
const int** addrOfToUpperTable;
private:
const unsigned short* localClassInfoTable;
const int* localToLowerTable;
const int* localToUpperTable;
const unsigned short* posixClassInfo;
const int* posixToLowerMap;
const int* posixToUpperMap;
public:
const unsigned short** addrOfClassInfoTable;
const int** addrOfToLowerTable;
const int** addrOfToUpperTable;
LocaleCtypeDataBridge();
const unsigned short* const posixClassInfo;
const int* const posixToLowerMap;
const int* const posixToUpperMap;
bool isGlobal;
LocaleCtypeDataBridge(bool isGlobal);
void setMbCurMax(unsigned short mbCurMax);
void ApplyToCurrentThread();
};
struct LocaleMessagesDataBridge {
const char** posixLanginfo;
const char** const posixLanginfo;
LocaleMessagesDataBridge();
};
struct LocaleMonetaryDataBridge {
const struct lconv* posixLocaleConv;
const struct lconv* const posixLocaleConv;
LocaleMonetaryDataBridge();
};
@@ -71,29 +80,42 @@ private:
values[6];
};
locale_data* originalGlibcLocale;
GlibcNumericLocale glibcNumericLocaleData;
public:
const struct lconv* posixLocaleConv;
GlibcNumericLocale glibcNumericLocale;
const struct lconv* const posixLocaleConv;
GlibcNumericLocale* glibcNumericLocale;
bool isGlobal;
LocaleNumericDataBridge();
LocaleNumericDataBridge(bool isGlobal);
~LocaleNumericDataBridge();
void ApplyToCurrentThread();
};
struct LocaleTimeDataBridge {
const struct lc_time_t* posixLCTimeInfo;
const struct lc_time_t* const posixLCTimeInfo;
LocaleTimeDataBridge();
};
struct TimeConversionDataBridge {
private:
int localDaylight;
long localTimezone;
char* localTZName[2];
char localTZName0[64];
char localTZName1[64];
public:
int* addrOfDaylight;
long* addrOfTimezone;
char** addrOfTZName;
bool isGlobal;
TimeConversionDataBridge();
TimeConversionDataBridge(bool isGlobal);
};
@@ -104,9 +126,12 @@ struct LocaleDataBridge {
LocaleNumericDataBridge numericDataBridge;
LocaleTimeDataBridge timeDataBridge;
TimeConversionDataBridge timeConversionDataBridge;
const char** posixLanginfo;
const char** const posixLanginfo;
bool isGlobal;
LocaleDataBridge();
LocaleDataBridge(bool isGlobal);
void ApplyToCurrentThread();
};
@@ -162,12 +187,25 @@ public:
virtual void Initialize(LocaleDataBridge* dataBridge) = 0;
static status_t LoadBackend();
static LocaleBackend* CreateBackend();
static void DestroyBackend(LocaleBackend* instance);
};
extern LocaleBackend* gLocaleBackend;
// The real struct behind locale_t
struct LocaleBackendData {
int magic;
LocaleBackend* backend;
LocaleDataBridge* databridge;
};
LocaleBackendData* GetCurrentLocaleInfo();
void SetCurrentLocaleInfo(LocaleBackendData* newLocale);
LocaleBackend* GetCurrentLocaleBackend();
extern LocaleBackend* gGlobalLocaleBackend;
extern LocaleDataBridge gGlobalLocaleDataBridge;
} // namespace Libroot
} // namespace BPrivate
@@ -0,0 +1,60 @@
/*
* Copyright 2022, Trung Nguyen, [email protected]
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef _THREAD_LOCALE_H
#define _THREAD_LOCALE_H
#include "LocaleBackend.h"
namespace BPrivate {
namespace Libroot {
// This struct is taken from glibc's __locale_struct
// from xlocale.h.
// It will also be used by glibc so it should have the same
// layout.
struct GlibcLocaleStruct {
void *__locales[7]; /* 7 = __LC_LAST. */
const unsigned short int *__ctype_b;
const int *__ctype_tolower;
const int *__ctype_toupper;
};
// Taken from glibc's bits/locale.h
// glibc uses different codes from our the native locale.h.
// This should be the values used for the indexes
// in GlibcLocaleStruct.
enum {
GLIBC_LC_CTYPE = 0,
GLIBC_LC_NUMERIC = 1,
GLIBC_LC_TIME = 2,
GLIBC_LC_COLLATE = 3,
GLIBC_LC_MONETARY = 4,
GLIBC_LC_MESSAGES = 5,
GLIBC_LC_ALL = 6,
};
// The pointer in the TLS will point to this struct.
struct ThreadLocale {
GlibcLocaleStruct glibcLocaleStruct;
LocaleBackendData* threadLocaleInfo;
};
ThreadLocale* GetCurrentThreadLocale();
} // namespace Libroot
} // namespace BPrivate
#endif // _THREAD_LOCALE_H
+2
View File
@@ -29,6 +29,7 @@
#define _TIMELOCAL_H_
#include <locale.h>
#include <sys/cdefs.h>
@@ -54,6 +55,7 @@ struct lc_time_t {
__BEGIN_DECLS
const struct lc_time_t* __get_current_time_locale(void);
const struct lc_time_t* __get_time_locale(locale_t);
__END_DECLS
+8
View File
@@ -33,11 +33,15 @@ extern wchar_t *__wcpcpy(wchar_t *dest, const wchar_t *src);
extern wchar_t *__wcpncpy(wchar_t *dest, const wchar_t *src, size_t srcLength);
extern size_t __wcrtomb(char *dest, wchar_t wc, mbstate_t *mbState);
extern int __wcscasecmp(const wchar_t *wcs1, const wchar_t *wcs2);
extern int __wcscasecmp_l(const wchar_t *wcs1, const wchar_t *wcs2,
locale_t locale);
extern wchar_t *__wcscat(wchar_t *dest, const wchar_t *src);
extern wchar_t *__wcschr(const wchar_t *wcs, wchar_t wc);
extern wchar_t *__wcschrnul(const wchar_t *wcs, wchar_t wc);
extern int __wcscmp(const wchar_t *wcs1, const wchar_t *wcs2);
extern int __wcscoll(const wchar_t *wcs1, const wchar_t *wcs2);
extern int __wcscoll_l(const wchar_t *wcs1, const wchar_t *wcs2,
locale_t locale);
extern wchar_t *__wcscpy(wchar_t *dest, const wchar_t *src);
extern size_t __wcscspn(const wchar_t *wcs, const wchar_t *reject);
extern wchar_t *__wcsdup(const wchar_t *wcs);
@@ -48,6 +52,8 @@ extern size_t __wcslcpy(wchar_t *dest, const wchar_t *src, size_t maxLength);
extern size_t __wcslen(const wchar_t *wcs);
extern int __wcsncasecmp(const wchar_t *wcs1, const wchar_t *wcs2,
size_t maxLength);
extern int __wcsncasecmp_l(const wchar_t *wcs1, const wchar_t *wcs2,
size_t maxLength, locale_t locale);
extern wchar_t *__wcsncat(wchar_t *dest, const wchar_t *src, size_t srcLength);
extern int __wcsncmp(const wchar_t *wcs1, const wchar_t *wcs2,
size_t length);
@@ -76,6 +82,8 @@ extern int __wctomb(char *string, wchar_t wc);
extern wchar_t *__wcswcs(const wchar_t *haystack, const wchar_t *needle);
extern int __wcswidth(const wchar_t *wcs, size_t length);
extern size_t __wcsxfrm(wchar_t *dest, const wchar_t *src, size_t destLength);
extern size_t __wcsxfrm_l(wchar_t *dest, const wchar_t *src, size_t destLength,
locale_t locale);
extern int __wctob(wint_t wc);
extern int __wcwidth(wchar_t wc);
extern wchar_t *__wmemchr(const wchar_t *wcs, wchar_t wc, size_t n);