From 3f36c6fa62eb9c961c5addedca9bed2b05934d6b Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 23 Aug 2016 12:49:23 +0200 Subject: [PATCH] Add __get_C_locale inline function and fix new locale code for !_MB_CAPABLE targets Only access "C" locale using the new __get_C_locale inline function. Enable __global_locale for !_MB_CAPABLE targets. Accommodate !_MB_CAPABLE targets in new locale code. Signed-off-by: Corinna Vinschen --- newlib/libc/locale/duplocale.c | 8 ++++++-- newlib/libc/locale/freelocale.c | 5 ++++- newlib/libc/locale/locale.c | 5 +++++ newlib/libc/locale/newlocale.c | 8 ++++++-- newlib/libc/locale/setlocale.h | 16 +++++++++++++++- 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/newlib/libc/locale/duplocale.c b/newlib/libc/locale/duplocale.c index 263a2b511..06ebfcd6e 100644 --- a/newlib/libc/locale/duplocale.c +++ b/newlib/libc/locale/duplocale.c @@ -45,12 +45,15 @@ _duplocale_r (struct _reent *p, struct __locale_t *locobj) struct __locale_t tmp_locale, *new_locale; int i; +#ifndef _MB_CAPABLE + return __get_C_locale (); +#else /* _MB_CAPABLE */ /* LC_GLOBAL_LOCALE denotes the global locale. */ if (locobj == LC_GLOBAL_LOCALE) locobj = __get_global_locale (); /* The "C" locale is used statically, never copied. */ - else if (locobj == &__C_locale) - return (struct __locale_t *) &__C_locale; + else if (locobj == __get_C_locale ()) + return __get_C_locale (); /* Copy locale content. */ tmp_locale = *locobj; #ifdef __HAVE_LOCALE_INFO__ @@ -86,6 +89,7 @@ error: #endif /* __HAVE_LOCALE_INFO__ */ return NULL; +#endif /* _MB_CAPABLE */ } #ifndef _REENT_ONLY diff --git a/newlib/libc/locale/freelocale.c b/newlib/libc/locale/freelocale.c index eba439e7d..dd3c0f95e 100644 --- a/newlib/libc/locale/freelocale.c +++ b/newlib/libc/locale/freelocale.c @@ -40,8 +40,10 @@ PORTABILITY void _freelocale_r (struct _reent *p, struct __locale_t *locobj) { + /* Nothing to do on !_MB_CAPABLE targets. */ +#ifdef _MB_CAPABLE /* Sanity check. The "C" locale is static, don't try to free it. */ - if (!locobj || locobj == &__C_locale || locobj == LC_GLOBAL_LOCALE) + if (!locobj || locobj == __get_C_locale () || locobj == LC_GLOBAL_LOCALE) return; #ifdef __HAVE_LOCALE_INFO__ for (int i = 1; i < _LC_LAST; ++i) @@ -52,6 +54,7 @@ _freelocale_r (struct _reent *p, struct __locale_t *locobj) } #endif /* __HAVE_LOCALE_INFO__ */ _free_r (p, locobj); +#endif /* _MB_CAPABLE */ } void diff --git a/newlib/libc/locale/locale.c b/newlib/libc/locale/locale.c index 9808022d1..fe04395b6 100644 --- a/newlib/libc/locale/locale.c +++ b/newlib/libc/locale/locale.c @@ -203,6 +203,7 @@ static char *categories[_LC_LAST] = { "LC_TIME", "LC_MESSAGES", }; +#endif /* _MB_CAPABLE */ /* * Default locale per POSIX. Can be overridden on a per-target base. @@ -210,6 +211,8 @@ static char *categories[_LC_LAST] = { #ifndef DEFAULT_LOCALE #define DEFAULT_LOCALE "C" #endif + +#ifdef _MB_CAPABLE /* * This variable can be changed by any outside mechanism. This allows, * for instance, to load the default locale from a file. @@ -250,6 +253,7 @@ const struct __locale_t __C_locale = }, #endif /* __HAVE_LOCALE_INFO__ */ }; +#endif /* _MB_CAPABLE */ struct __locale_t __global_locale = { @@ -291,6 +295,7 @@ 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. */ diff --git a/newlib/libc/locale/newlocale.c b/newlib/libc/locale/newlocale.c index b4a477801..bd4e38584 100644 --- a/newlib/libc/locale/newlocale.c +++ b/newlib/libc/locale/newlocale.c @@ -86,6 +86,9 @@ struct __locale_t * _newlocale_r (struct _reent *p, int category_mask, const char *locale, struct __locale_t *base) { +#ifndef _MB_CAPABLE + return __get_C_locale (); +#else /* _MB_CAPABLE */ char new_categories[_LC_LAST][ENCODING_LEN + 1]; struct __locale_t tmp_locale, *new_locale; int i; @@ -108,9 +111,9 @@ _newlocale_r (struct _reent *p, int category_mask, const char *locale, if ((!base && category_mask == 0) || (category_mask == LC_VALID_MASK && (!strcmp (locale, "C") || !strcmp (locale, "POSIX")))) - return (struct __locale_t *) &__C_locale; + return __get_C_locale (); /* Start with setting all values to the default locale values. */ - tmp_locale = __C_locale; + tmp_locale = *__get_C_locale (); /* Fill out new category strings. */ for (i = 1; i < _LC_LAST; ++i) { @@ -206,6 +209,7 @@ error: #endif /* __HAVE_LOCALE_INFO__ */ return NULL; +#endif /* _MB_CAPABLE */ } struct __locale_t * diff --git a/newlib/libc/locale/setlocale.h b/newlib/libc/locale/setlocale.h index 86b638b70..daf932308 100644 --- a/newlib/libc/locale/setlocale.h +++ b/newlib/libc/locale/setlocale.h @@ -194,9 +194,10 @@ struct __locale_t #endif }; -extern const struct __locale_t __C_locale; +#ifdef _MB_CAPABLE extern char *__loadlocale (struct __locale_t *, int, const char *); extern const char *__get_locale_env(struct _reent *, int); +#endif /* _MB_CAPABLE */ extern struct lconv *__localeconv_l (struct __locale_t *locale); @@ -229,6 +230,19 @@ __get_current_locale () return _REENT->_locale ?: __get_global_locale (); } +/* Only access fixed "C" locale using this function. Fake for !_MB_CAPABLE + targets by returning ptr to globale locale. */ +_ELIDABLE_INLINE struct __locale_t * +__get_C_locale () +{ +#ifndef _MB_CAPABLE + return __get_global_locale (); +#else + extern const struct __locale_t __C_locale; + return (struct __locale_t *) &__C_locale; +#endif +} + #ifdef __CYGWIN__ _ELIDABLE_INLINE const struct lc_collate_T * __get_collate_locale (struct __locale_t *locale)