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>
This commit is contained in:
parent
cb54031e01
commit
71511d4ac8
|
@ -353,6 +353,7 @@ check_PROGRAMS =
|
|||
@ELIX_LEVEL_1_FALSE@am__append_19 = \
|
||||
@ELIX_LEVEL_1_FALSE@ libc/locale/duplocale.c \
|
||||
@ELIX_LEVEL_1_FALSE@ libc/locale/freelocale.c \
|
||||
@ELIX_LEVEL_1_FALSE@ libc/locale/getlocalename_l.c \
|
||||
@ELIX_LEVEL_1_FALSE@ libc/locale/lctype.c \
|
||||
@ELIX_LEVEL_1_FALSE@ libc/locale/lmessages.c \
|
||||
@ELIX_LEVEL_1_FALSE@ libc/locale/lnumeric.c \
|
||||
|
@ -1383,6 +1384,7 @@ am__objects_21 = $(am__objects_20)
|
|||
@ELIX_LEVEL_1_FALSE@am__objects_23 = \
|
||||
@ELIX_LEVEL_1_FALSE@ libc/locale/libc_a-duplocale.$(OBJEXT) \
|
||||
@ELIX_LEVEL_1_FALSE@ libc/locale/libc_a-freelocale.$(OBJEXT) \
|
||||
@ELIX_LEVEL_1_FALSE@ libc/locale/libc_a-getlocalename_l.$(OBJEXT) \
|
||||
@ELIX_LEVEL_1_FALSE@ libc/locale/libc_a-lctype.$(OBJEXT) \
|
||||
@ELIX_LEVEL_1_FALSE@ libc/locale/libc_a-lmessages.$(OBJEXT) \
|
||||
@ELIX_LEVEL_1_FALSE@ libc/locale/libc_a-lnumeric.$(OBJEXT) \
|
||||
|
@ -3937,6 +3939,7 @@ pdfdir = @pdfdir@
|
|||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
shared_machine_dir = @shared_machine_dir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
|
@ -6602,6 +6605,9 @@ libc/locale/libc_a-duplocale.$(OBJEXT): libc/locale/$(am__dirstamp) \
|
|||
libc/locale/$(DEPDIR)/$(am__dirstamp)
|
||||
libc/locale/libc_a-freelocale.$(OBJEXT): libc/locale/$(am__dirstamp) \
|
||||
libc/locale/$(DEPDIR)/$(am__dirstamp)
|
||||
libc/locale/libc_a-getlocalename_l.$(OBJEXT): \
|
||||
libc/locale/$(am__dirstamp) \
|
||||
libc/locale/$(DEPDIR)/$(am__dirstamp)
|
||||
libc/locale/libc_a-lctype.$(OBJEXT): libc/locale/$(am__dirstamp) \
|
||||
libc/locale/$(DEPDIR)/$(am__dirstamp)
|
||||
libc/locale/libc_a-lmessages.$(OBJEXT): libc/locale/$(am__dirstamp) \
|
||||
|
@ -12774,6 +12780,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@libc/iconv/lib/$(DEPDIR)/libc_a-ucsconv.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@libc/locale/$(DEPDIR)/libc_a-duplocale.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@libc/locale/$(DEPDIR)/libc_a-freelocale.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@libc/locale/$(DEPDIR)/libc_a-getlocalename_l.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@libc/locale/$(DEPDIR)/libc_a-lctype.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@libc/locale/$(DEPDIR)/libc_a-lmessages.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@libc/locale/$(DEPDIR)/libc_a-lmonetary.Po@am__quote@
|
||||
|
@ -28041,6 +28048,20 @@ libc/locale/libc_a-freelocale.obj: libc/locale/freelocale.c
|
|||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -c -o libc/locale/libc_a-freelocale.obj `if test -f 'libc/locale/freelocale.c'; then $(CYGPATH_W) 'libc/locale/freelocale.c'; else $(CYGPATH_W) '$(srcdir)/libc/locale/freelocale.c'; fi`
|
||||
|
||||
libc/locale/libc_a-getlocalename_l.o: libc/locale/getlocalename_l.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -MT libc/locale/libc_a-getlocalename_l.o -MD -MP -MF libc/locale/$(DEPDIR)/libc_a-getlocalename_l.Tpo -c -o libc/locale/libc_a-getlocalename_l.o `test -f 'libc/locale/getlocalename_l.c' || echo '$(srcdir)/'`libc/locale/getlocalename_l.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libc/locale/$(DEPDIR)/libc_a-getlocalename_l.Tpo libc/locale/$(DEPDIR)/libc_a-getlocalename_l.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libc/locale/getlocalename_l.c' object='libc/locale/libc_a-getlocalename_l.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -c -o libc/locale/libc_a-getlocalename_l.o `test -f 'libc/locale/getlocalename_l.c' || echo '$(srcdir)/'`libc/locale/getlocalename_l.c
|
||||
|
||||
libc/locale/libc_a-getlocalename_l.obj: libc/locale/getlocalename_l.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -MT libc/locale/libc_a-getlocalename_l.obj -MD -MP -MF libc/locale/$(DEPDIR)/libc_a-getlocalename_l.Tpo -c -o libc/locale/libc_a-getlocalename_l.obj `if test -f 'libc/locale/getlocalename_l.c'; then $(CYGPATH_W) 'libc/locale/getlocalename_l.c'; else $(CYGPATH_W) '$(srcdir)/libc/locale/getlocalename_l.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libc/locale/$(DEPDIR)/libc_a-getlocalename_l.Tpo libc/locale/$(DEPDIR)/libc_a-getlocalename_l.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libc/locale/getlocalename_l.c' object='libc/locale/libc_a-getlocalename_l.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -c -o libc/locale/libc_a-getlocalename_l.obj `if test -f 'libc/locale/getlocalename_l.c'; then $(CYGPATH_W) 'libc/locale/getlocalename_l.c'; else $(CYGPATH_W) '$(srcdir)/libc/locale/getlocalename_l.c'; fi`
|
||||
|
||||
libc/locale/libc_a-lctype.o: libc/locale/lctype.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -MT libc/locale/libc_a-lctype.o -MD -MP -MF libc/locale/$(DEPDIR)/libc_a-lctype.Tpo -c -o libc/locale/libc_a-lctype.o `test -f 'libc/locale/lctype.c' || echo '$(srcdir)/'`libc/locale/lctype.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libc/locale/$(DEPDIR)/libc_a-lctype.Tpo libc/locale/$(DEPDIR)/libc_a-lctype.Po
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue