public inbox for newlib-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin/main] getlocalename_l: implement per SUS Base Specifications Issue 8 draft
@ 2024-02-01 11:38 Corinna Vinschen
  0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2024-02-01 11:38 UTC (permalink / raw)
  To: newlib-cvs

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=71511d4ac8686c2220093cc01525311d9c88bc4e

commit 71511d4ac8686c2220093cc01525311d9c88bc4e
Author:     Corinna Vinschen <corinna@vinschen.de>
AuthorDate: Sun Jan 21 13:23:09 2024 +0100
Commit:     Corinna Vinschen <corinna@vinschen.de>
CommitDate: Wed Jan 31 20:11:57 2024 +0100

    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>

Diff:
---
 newlib/Makefile.in                   | 21 ++++++++++
 newlib/libc/include/locale.h         |  5 +++
 newlib/libc/include/sys/reent.h      | 12 ++++++
 newlib/libc/locale/Makefile.inc      |  1 +
 newlib/libc/locale/getlocalename_l.c | 77 ++++++++++++++++++++++++++++++++++++
 5 files changed, 116 insertions(+)

diff --git a/newlib/Makefile.in b/newlib/Makefile.in
index 9a32646abe96..61a89ff65c93 100644
--- a/newlib/Makefile.in
+++ b/newlib/Makefile.in
@@ -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
diff --git a/newlib/libc/include/locale.h b/newlib/libc/include/locale.h
index ec7f86119c4e..e3a702a5eaef 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 a02e7c2bd994..4e60c3096ae2 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 cef4131d08ec..0189643c2a94 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 000000000000..7060c8df5952
--- /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);
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-02-01 11:38 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-01 11:38 [newlib-cygwin/main] getlocalename_l: implement per SUS Base Specifications Issue 8 draft Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).