aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2024-01-21 13:23:09 +0100
committerCorinna Vinschen <corinna@vinschen.de>2024-01-31 20:11:57 +0100
commit71511d4ac8686c2220093cc01525311d9c88bc4e (patch)
tree9973f9166452e4b5d2b80625d48cade547ea0f03 /newlib/libc
parentcb54031e01a8485743cb6eb68e59f7e19548ae1a (diff)
downloadnewlib-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.h5
-rw-r--r--newlib/libc/include/sys/reent.h12
-rw-r--r--newlib/libc/locale/Makefile.inc1
-rw-r--r--newlib/libc/locale/getlocalename_l.c77
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);
+}