diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2024-01-21 13:23:09 +0100 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2024-01-31 20:11:57 +0100 |
commit | 71511d4ac8686c2220093cc01525311d9c88bc4e (patch) | |
tree | 9973f9166452e4b5d2b80625d48cade547ea0f03 /newlib/libc | |
parent | cb54031e01a8485743cb6eb68e59f7e19548ae1a (diff) | |
download | newlib-71511d4ac8686c2220093cc01525311d9c88bc4e.zip newlib-71511d4ac8686c2220093cc01525311d9c88bc4e.tar.gz newlib-71511d4ac8686c2220093cc01525311d9c88bc4e.tar.bz2 |
getlocalename_l: implement per SUS Base Specifications Issue 8 draft
#include <locale.h>
const char *getlocalename_l(int category, locale_t locobj);
Most notably, we need a per-thread space to store the string
returned if locobj is LC_GLOBAL_LOCALE. No errors are defined
for getlocalename_l. So we can't use buffer allocation which
might lead to an ENOMEM error. We have to use a "static" buffer
in the per-thread state.
Note that the feature test macro in locale.h is not quite correct.
This needs to be fixed as soon as the
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diffstat (limited to 'newlib/libc')
-rw-r--r-- | newlib/libc/include/locale.h | 5 | ||||
-rw-r--r-- | newlib/libc/include/sys/reent.h | 12 | ||||
-rw-r--r-- | newlib/libc/locale/Makefile.inc | 1 | ||||
-rw-r--r-- | newlib/libc/locale/getlocalename_l.c | 77 |
4 files changed, 95 insertions, 0 deletions
diff --git a/newlib/libc/include/locale.h b/newlib/libc/include/locale.h index ec7f861..e3a702a 100644 --- a/newlib/libc/include/locale.h +++ b/newlib/libc/include/locale.h @@ -76,6 +76,7 @@ struct __locale_t *_newlocale_r (struct _reent *, int, const char *, void _freelocale_r (struct _reent *, struct __locale_t *); struct __locale_t *_duplocale_r (struct _reent *, struct __locale_t *); struct __locale_t *_uselocale_r (struct _reent *, struct __locale_t *); +const char *_getlocalename_l_r (struct _reent *, int, struct __locale_t *); #ifndef _REENT_ONLY @@ -89,6 +90,10 @@ locale_t duplocale (locale_t); locale_t uselocale (locale_t); #endif /* __POSIX_VISIBLE >= 200809 */ +#if __POSIX_VISIBLE >= 200809 /* FIXME? Starting with issue 8 */ +const char *getlocalename_l (int, struct __locale_t *); +#endif + #endif /* _REENT_ONLY */ _END_STD_C diff --git a/newlib/libc/include/sys/reent.h b/newlib/libc/include/sys/reent.h index a02e7c2..4e60c30 100644 --- a/newlib/libc/include/sys/reent.h +++ b/newlib/libc/include/sys/reent.h @@ -369,6 +369,9 @@ struct _misc_reent _mbstate_t _mbsrtowcs_state; _mbstate_t _wcrtomb_state; _mbstate_t _wcsrtombs_state; +#ifdef _MB_CAPABLE + char _getlocalename_l_buf[32 /*ENCODING + 1*/]; +#endif }; /* This version of _reent is laid out with "int"s in pairs, to help @@ -530,6 +533,7 @@ struct _reent _r->_misc->_wcrtomb_state.__value.__wch = 0; \ _r->_misc->_wcsrtombs_state.__count = 0; \ _r->_misc->_wcsrtombs_state.__value.__wch = 0; \ + _r->_misc->_getlocale_l_buf[0] = '\0'; \ _r->_misc->_l64a_buf[0] = '\0'; \ _r->_misc->_getdate_err = 0; \ } while (0) @@ -561,6 +565,7 @@ struct _reent #define _REENT_WCSRTOMBS_STATE(ptr) ((ptr)->_misc->_wcsrtombs_state) #define _REENT_L64A_BUF(ptr) ((ptr)->_misc->_l64a_buf) #define _REENT_GETDATE_ERR_P(ptr) (&((ptr)->_misc->_getdate_err)) +#define _REENT_GETLOCALENAME_L_BUF(ptr) ((ptr)->_misc->_getlocalename_l_buf) #define _REENT_SIGNAL_BUF(ptr) ((ptr)->_signal_buf) #else /* !_REENT_SMALL */ @@ -631,6 +636,10 @@ struct _reent _mbstate_t _mbrtoc16_state; _mbstate_t _mbrtoc32_state; #endif + /* No errors are defined for getlocalename_l. So we can't use + buffer allocation which might lead to an ENOMEM error. We + have to use a "static" buffer here instead. */ + char _getlocalename_l_buf[32 /* ENCODING_LEN + 1 */]; } _reent; #ifdef _REENT_BACKWARD_BINARY_COMPAT struct @@ -750,6 +759,7 @@ struct _reent #define _REENT_L64A_BUF(ptr) ((ptr)->_new._reent._l64a_buf) #define _REENT_SIGNAL_BUF(ptr) ((ptr)->_new._reent._signal_buf) #define _REENT_GETDATE_ERR_P(ptr) (&((ptr)->_new._reent._getdate_err)) +#define _REENT_GETLOCALENAME_L_BUF(ptr)((ptr)->_new._reent._getlocalename_l_buf) #endif /* !_REENT_SMALL */ @@ -842,6 +852,8 @@ extern _Thread_local char _tls_l64a_buf[8]; extern _Thread_local struct __locale_t *_tls_locale; #define _REENT_LOCALE(_ptr) (_tls_locale) extern _Thread_local _mbstate_t _tls_mblen_state; +#define _REENT_GETLOCALENAME_L_BUF(ptr) (_tls_getlocalename_l_buf) +extern _Thread_local char _tls_getlocalename_l_buf[32 /*ENCODING + 1*/]; #define _REENT_MBLEN_STATE(_ptr) (_tls_mblen_state) extern _Thread_local _mbstate_t _tls_mbrlen_state; #define _REENT_MBRLEN_STATE(_ptr) (_tls_mbrlen_state) diff --git a/newlib/libc/locale/Makefile.inc b/newlib/libc/locale/Makefile.inc index cef4131..0189643 100644 --- a/newlib/libc/locale/Makefile.inc +++ b/newlib/libc/locale/Makefile.inc @@ -8,6 +8,7 @@ if !ELIX_LEVEL_1 libc_a_SOURCES += \ %D%/duplocale.c \ %D%/freelocale.c \ + %D%/getlocalename_l.c \ %D%/lctype.c \ %D%/lmessages.c \ %D%/lnumeric.c \ diff --git a/newlib/libc/locale/getlocalename_l.c b/newlib/libc/locale/getlocalename_l.c new file mode 100644 index 0000000..7060c8d --- /dev/null +++ b/newlib/libc/locale/getlocalename_l.c @@ -0,0 +1,77 @@ +/* +FUNCTION + <<getlocalename_l>>---create or modify a locale object + +INDEX + getlocalename_l + +INDEX + _getlocalename_l_r + +SYNOPSIS + #include <locale.h> + locale_t getlocalename_l(int <[category]>, locale_t <[locobj]>); + + locale_t _getlocalename_l_r(void *<[reent]>, int <[category]>, + locale_t <[locobj]>); + +DESCRIPTION +The <<getlocalename_l>> function shall return the locale name for the +given locale category of the locale object locobj, or of the global +locale if locobj is the special locale object LC_GLOBAL_LOCALE. + +The category argument specifies the locale category to be queried. If +the value is LC_ALL or is not a supported locale category value (see +<<setlocale>>), <<getlocalename_l>> shall fail. + +The behavior is undefined if the locobj argument is neither the special +locale object LC_GLOBAL_LOCALE nor a valid locale object handle. + +RETURNS +Upon successful completion, <<getlocalename_l>> shall return a pointer +to a string containing the locale name; otherwise, a null pointer shall +be returned. + +If locobj is LC_GLOBAL_LOCALE, the returned string pointer might be +invalidated or the string content might be overwritten by a subsequent +call in the same thread to <<getlocalename_l>> with LC_GLOBAL_LOCALE; +the returned string pointer might also be invalidated if the calling +thread is terminated. Otherwise, the returned string pointer and content +shall remain valid until the locale object locobj is used in a call to +<<freelocale>> or as the base argument in a successful call to +<<newlocale>>. + +No errors are defined. + +PORTABILITY +<<getlocalename_l>> is POSIX-1.2008 since Base Specification Issue 8 +*/ + +#include <newlib.h> +#include "setlocale.h" + +const char * +_getlocalename_l_r (struct _reent *ptr, int category, struct __locale_t *locobj) +{ + if (category <= LC_ALL || category > LC_MESSAGES) + return NULL; +#ifndef _MB_CAPABLE + return "C"; +#else + if (locobj == LC_GLOBAL_LOCALE) + { + /* getlocalename_l is supposed to return the value in a + thread-safe manner. This requires to copy over the + category string into thread-local storage. */ + strcpy (_REENT_GETLOCALENAME_L_BUF (ptr), + __get_global_locale ()->categories[category]); + } + return locobj->categories[category]; +#endif +} + +const char * +getlocalename_l (int category, struct __locale_t *locobj) +{ + return _getlocalename_l_r (_REENT, category, locobj); +} |