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
+27 -3
View File
@@ -6,6 +6,9 @@
#define _CTYPE_H
#include <locale_t.h>
#ifdef __cplusplus
extern "C" {
#endif
@@ -27,6 +30,22 @@ int toascii(int);
int tolower(int);
int toupper(int);
int isalnum_l(int, locale_t);
int isalpha_l(int, locale_t);
int isblank_l(int, locale_t);
int iscntrl_l(int, locale_t);
int isdigit_l(int, locale_t);
int isgraph_l(int, locale_t);
int islower_l(int, locale_t);
int isprint_l(int, locale_t);
int ispunct_l(int, locale_t);
int isspace_l(int, locale_t);
int isupper_l(int, locale_t);
int isxdigit_l(int, locale_t);
int tolower_l(int, locale_t);
int toupper_l(int, locale_t);
enum {
_ISblank = 0x0001, /* blank */
_IScntrl = 0x0002, /* control */
@@ -48,14 +67,19 @@ extern const unsigned short int *__ctype_b;
extern const int *__ctype_tolower;
extern const int *__ctype_toupper;
extern const unsigned short int **__ctype_b_loc();
extern const int **__ctype_tolower_loc();
extern const int **__ctype_toupper_loc();
#define __isctype(c, type) \
(__ctype_b[(int)(c)] & (unsigned short int)type)
((*__ctype_b_loc())[(int)(c)] & (unsigned short int)type)
#define tolower(c) ((int)(*__ctype_tolower_loc())[(int)(c)])
#define toupper(c) ((int)(*__ctype_toupper_loc())[(int)(c)])
#define isascii(c) (((c) & ~0x7f) == 0) /* ASCII characters have bit 8 cleared */
#define toascii(c) ((c) & 0x7f) /* Clear higher bits */
#define tolower(c) ((int)__ctype_tolower[(int)(c)])
#define toupper(c) ((int)__ctype_toupper[(int)(c)])
#define _tolower(c) tolower(c)
#define _toupper(c) toupper(c)
+1
View File
@@ -145,6 +145,7 @@ enum {
__BEGIN_DECLS
extern char* nl_langinfo(nl_item item);
extern char* nl_langinfo_l(nl_item item, locale_t locale);
__END_DECLS
+19
View File
@@ -6,6 +6,7 @@
#define _LOCALE_H_
#include <locale_t.h>
#include <null.h>
struct lconv {
@@ -48,6 +49,19 @@ struct lconv {
*/
#define LC_LAST LC_MESSAGES
#define LC_COLLATE_MASK (1 << (LC_COLLATE - 1))
#define LC_CTYPE_MASK (1 << (LC_CTYPE - 1))
#define LC_MONETARY_MASK (1 << (LC_MONETARY - 1))
#define LC_NUMERIC_MASK (1 << (LC_NUMERIC - 1))
#define LC_TIME_MASK (1 << (LC_TIME - 1))
#define LC_MESSAGES_MASK (1 << (LC_MESSAGES - 1))
#define LC_ALL_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | \
LC_MONETARY_MASK | LC_NUMERIC_MASK | \
LC_TIME_MASK | LC_MESSAGES_MASK)
#define LC_GLOBAL_LOCALE ((locale_t)-1)
#ifdef __cplusplus
extern "C" {
#endif
@@ -55,6 +69,11 @@ extern "C" {
extern struct lconv *localeconv(void);
extern char *setlocale(int category, const char *locale);
extern locale_t duplocale(locale_t);
extern void freelocale(locale_t);
extern locale_t newlocale(int, const char *, locale_t);
extern locale_t uselocale(locale_t);
#ifdef __cplusplus
}
#endif
+12
View File
@@ -0,0 +1,12 @@
/*
* Copyright 2022 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _LOCALE_T_H_
#define _LOCALE_T_H_
typedef void* locale_t;
#endif
+2 -1
View File
@@ -6,7 +6,7 @@
#define _MONETARY_H_
#include <locale.h>
#include <locale_t.h>
#include <stddef.h>
#include <sys/cdefs.h>
#include <sys/types.h>
@@ -15,6 +15,7 @@
__BEGIN_DECLS
extern ssize_t strfmon(char* s, size_t maxsize, const char* format, ...);
extern ssize_t strfmon_l(char* s, size_t maxsize, locale_t locale, const char* format, ...);
__END_DECLS
+6
View File
@@ -6,6 +6,7 @@
#define _STRING_H_
#include <locale_t.h>
#include <sys/types.h>
@@ -74,6 +75,11 @@ extern char *strupr(char *string);
extern const char *strsignal(int signum);
/* locale versions of string functions */
extern int strcoll_l(const char *string1, const char *string2, locale_t locale);
extern char *strerror_l(int errorCode, locale_t locale);
extern size_t strxfrm_l(char *string1, const char *string2, size_t length, locale_t locale);
/* for compatibility, pull in functions declared in strings.h */
#include <strings.h>
+5
View File
@@ -6,6 +6,7 @@
#define _STRINGS_H_
#include <locale_t.h>
#include <sys/types.h>
@@ -19,6 +20,10 @@ extern int strcasecmp(const char *string1, const char *string2);
extern int strncasecmp(const char *string1, const char *string2,
size_t length);
extern int strcasecmp_l(const char *string1, const char *string2, locale_t locale);
extern int strncasecmp_l(const char *string1, const char *string2,
size_t length, locale_t locale);
/* legacy compatibility -- might be removed one day */
#define bcmp(a, b, length) memcmp((a), (b), (length))
#define bcopy(source, dest, length) memmove((dest), (source), (length))
+3
View File
@@ -6,6 +6,7 @@
#define _TIME_H_
#include <locale_t.h>
#include <sys/types.h>
@@ -92,6 +93,8 @@ extern struct tm *localtime_r(const time_t *timer, struct tm *tm);
extern int nanosleep(const struct timespec *, struct timespec *);
extern size_t strftime(char *buffer, size_t maxSize, const char *format,
const struct tm *tm);
extern size_t strftime_l(char *buffer, size_t maxSize, const char *format,
const struct tm *tm, locale_t locale);
extern char *strptime(const char *buf, const char *format, struct tm *tm);
/* clock functions */
+7
View File
@@ -7,6 +7,7 @@
#include <limits.h>
#include <locale.h>
#include <stddef.h>
#include <stdio.h>
#include <time.h>
@@ -93,6 +94,7 @@ 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);
#ifdef _GNU_SOURCE
@@ -100,6 +102,7 @@ extern wchar_t *wcschrnul(const wchar_t *wcs, wchar_t wc);
#endif
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);
@@ -110,6 +113,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);
@@ -136,6 +141,8 @@ extern unsigned long long wcstoull(const wchar_t *wcs, wchar_t **endPtr,
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);
+24
View File
@@ -6,6 +6,7 @@
#define _WCTYPE_H_
#include <locale.h>
#include <wchar.h>
typedef int wctrans_t;
@@ -36,6 +37,29 @@ extern wint_t towupper(wint_t wc);
extern wctrans_t wctrans(const char *charClass);
extern wctype_t wctype(const char *property);
extern int iswalnum_l(wint_t wc, locale_t locale);
extern int iswalpha_l(wint_t wc, locale_t locale);
extern int iswcntrl_l(wint_t wc, locale_t locale);
extern int iswctype_l(wint_t wc, wctype_t desc, locale_t locale);
extern int iswdigit_l(wint_t wc, locale_t locale);
extern int iswgraph_l(wint_t wc, locale_t locale);
extern int iswlower_l(wint_t wc, locale_t locale);
extern int iswprint_l(wint_t wc, locale_t locale);
extern int iswpunct_l(wint_t wc, locale_t locale);
extern int iswspace_l(wint_t wc, locale_t locale);
extern int iswupper_l(wint_t wc, locale_t locale);
extern int iswxdigit_l(wint_t wc, locale_t locale);
extern int iswblank_l(wint_t wc, locale_t locale);
extern wint_t towctrans_l(wint_t wc, wctrans_t transition, locale_t locale);
extern wint_t towlower_l(wint_t wc, locale_t locale);
extern wint_t towupper_l(wint_t wc, locale_t locale);
extern wctrans_t wctrans_l(const char *charClass, locale_t locale);
extern wctype_t wctype_l(const char *property, locale_t locale);
#ifdef __cplusplus
}
#endif
+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, trungnt282910@gmail.com
* 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);
+1
View File
@@ -21,6 +21,7 @@ enum {
TLS_ON_EXIT_THREAD_SLOT,
TLS_USER_THREAD_SLOT,
TLS_DYNAMIC_THREAD_VECTOR,
TLS_LOCALE_SLOT,
// Note: these entries can safely be changed between
// releases; 3rd party code always calls tls_allocate()