[newlib-cygwin/cygwin-3_6-branch] locale: drop global_locale_string, add locale_string to locale_t

Corinna Vinschen corinna@sourceware.org
Mon Mar 24 20:59:20 GMT 2025


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

commit b0a66722a9076b88d13a6ea861a3f2133114d834
Author:     Corinna Vinschen <corinna@vinschen.de>
AuthorDate: Mon Mar 24 21:17:47 2025 +0100
Commit:     Corinna Vinschen <corinna@vinschen.de>
CommitDate: Mon Mar 24 21:50:08 2025 +0100

    locale: drop global_locale_string, add locale_string to locale_t
    
    After 71511d4ac868 ("getlocalename_l: implement per SUS Base
    Specifications Issue 8 draft") the Austin Group changed the definition
    of getlocalename_l() to return setlocale-compatible strings if LC_ALL
    has been specified.  In contrast to the former definition which
    disallowed LC_ALL as category.
    
    In preparation, add a locale_string to every locale_t, and drop
    the static global_locale_string.
    
    This in turn requires to change currentlocale() to work locale-agnostic.
    Rename to  __currentlocale and take two parameters, the locale object
    and a target string to store the locale string.  The latter is required
    to allow specifiying a target string not in the current locale.
    
    Link: https://www.austingroupbugs.net/view.php?id=1741
    Fixes: 71511d4ac868 ("getlocalename_l: implement per SUS Base Specifications Issue 8 draft")
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
    (cherry picked from commit e5a9f552ecf908f1639b08729edc191c66f4e7d0)

Diff:
---
 newlib/libc/locale/locale.c    | 46 ++++++++++++++++++++++--------------------
 newlib/libc/locale/setlocale.h |  5 +++++
 2 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/newlib/libc/locale/locale.c b/newlib/libc/locale/locale.c
index b16ec15114a5..9e950a570c62 100644
--- a/newlib/libc/locale/locale.c
+++ b/newlib/libc/locale/locale.c
@@ -199,6 +199,7 @@ static char *categories[_LC_LAST] = {
  */
 #ifndef DEFAULT_LOCALE
 #define DEFAULT_LOCALE	"C"
+#define DEFAULT_LOCALE_IS_C
 #endif
 
 #ifdef _MB_CAPABLE
@@ -211,6 +212,9 @@ char __default_locale[ENCODING_LEN + 1] = DEFAULT_LOCALE;
 const struct __locale_t __C_locale =
 {
   { "C", "C", "C", "C", "C", "C", "C", },
+#ifdef _MB_CAPABLE
+  "C",
+#endif
   __ascii_wctomb,
   __ascii_mbtowc,
   0,
@@ -247,6 +251,13 @@ const struct __locale_t __C_locale =
 struct __locale_t __global_locale =
 {
   { "C", "C", DEFAULT_LOCALE, "C", "C", "C", "C", },
+#ifdef _MB_CAPABLE
+# ifdef DEFAULT_LOCALE_IS_C
+  "C",
+# else
+  "C/" DEFAULT_LOCALE "/C/C/C/C",
+# endif
+#endif
 #ifdef __CYGWIN__
   __utf8_wctomb,
   __utf8_mbtowc,
@@ -285,16 +296,6 @@ struct __locale_t __global_locale =
 #endif /* __HAVE_LOCALE_INFO__ */
 };
 
-#ifdef _MB_CAPABLE
-/* Renamed from current_locale_string to make clear this is only the
-   *global* string for setlocale (LC_ALL, NULL).  There's no equivalent
-   functionality for uselocale. */
-static char global_locale_string[_LC_LAST * (ENCODING_LEN + 1/*"/"*/ + 1)]
-	    = "C";
-static char *currentlocale (void);
-
-#endif /* _MB_CAPABLE */
-
 char *
 _setlocale_r (struct _reent *p,
        int category,
@@ -323,7 +324,7 @@ _setlocale_r (struct _reent *p,
 
   if (locale == NULL)
     return category != LC_ALL ? __get_global_locale ()->categories[category]
-			      : global_locale_string;
+			      : __get_global_locale ()->locale_string;
 
   /*
    * Default to the current locale for everything.
@@ -420,7 +421,8 @@ _setlocale_r (struct _reent *p,
     {
       ret = __loadlocale (__get_global_locale (), category,
 			  new_categories[category]);
-      currentlocale ();
+      __currentlocale (__get_global_locale (),
+		       __get_global_locale ()->locale_string);
       return ret;
     }
 
@@ -444,31 +446,31 @@ _setlocale_r (struct _reent *p,
 	  return NULL;
 	}
     }
-  return currentlocale ();
+  return __currentlocale (__get_global_locale (),
+			  __get_global_locale ()->locale_string);
 #endif /* _MB_CAPABLE */
 }
 
 #ifdef _MB_CAPABLE
-static char *
-currentlocale ()
+char *
+__currentlocale (struct __locale_t *locobj, char *locale_string)
 {
   int i;
 
-  strcpy (global_locale_string, __get_global_locale ()->categories[1]);
+  strcpy (locale_string, locobj->categories[1]);
 
   for (i = 2; i < _LC_LAST; ++i)
-    if (strcmp (__get_global_locale ()->categories[1],
-		__get_global_locale ()->categories[i]))
+    if (strcmp (locobj->categories[1],
+		locobj->categories[i]))
       {
 	for (i = 2; i < _LC_LAST; ++i)
 	  {
-	    (void)strcat(global_locale_string, "/");
-	    (void)strcat(global_locale_string,
-			 __get_global_locale ()->categories[i]);
+	    (void)strcat(locale_string, "/");
+	    (void)strcat(locale_string, locobj->categories[i]);
 	  }
 	break;
       }
-  return global_locale_string;
+  return locale_string;
 }
 
 extern void __set_ctype (struct __locale_t *, const char *charset);
diff --git a/newlib/libc/locale/setlocale.h b/newlib/libc/locale/setlocale.h
index e91034ac85fb..572b198b5a73 100644
--- a/newlib/libc/locale/setlocale.h
+++ b/newlib/libc/locale/setlocale.h
@@ -183,6 +183,10 @@ struct __lc_cats
 struct __locale_t
 {
   char			 categories[_LC_LAST][ENCODING_LEN + 1];
+#ifdef _MB_CAPABLE
+  char			 locale_string[_LC_LAST
+				       * (ENCODING_LEN + 1/*"/"*/ + 1)];
+#endif
   int			(*wctomb) (struct _reent *, char *, wchar_t,
 				   mbstate_t *);
   int			(*mbtowc) (struct _reent *, wchar_t *,
@@ -200,6 +204,7 @@ struct __locale_t
 };
 
 #ifdef _MB_CAPABLE
+char *__currentlocale (struct __locale_t *, char *);
 extern char *__loadlocale (struct __locale_t *, int, char *);
 extern const char *__get_locale_env(struct _reent *, int);
 #endif /* _MB_CAPABLE */


More information about the Newlib-cvs mailing list