From 1498c79db89ea0e02a49ffa34e71da480e37165e Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 21 Jul 2016 20:49:42 +0200 Subject: [PATCH] Change loadlocale to fill a __locale_t given as parameter Don't use global variables. This allows to call loadlocale from the yet to be created newlocale(). Rename _thr_locale_t to __locale_t (these locales are not restricted to threads so the name is misleading). Along these lines, fix _set_ctype to take a __locale_t as parameter. Signed-off by: Corinna Vinschen --- newlib/libc/ctype/ctype_.c | 17 +++-- newlib/libc/include/locale.h | 6 +- newlib/libc/include/sys/reent.h | 6 +- newlib/libc/locale/lctype.c | 2 +- newlib/libc/locale/lmessages.c | 2 +- newlib/libc/locale/lmonetary.c | 2 +- newlib/libc/locale/lnumeric.c | 2 +- newlib/libc/locale/locale.c | 106 +++++++++++++++----------------- newlib/libc/locale/setlocale.h | 22 +++---- newlib/libc/locale/timelocal.c | 2 +- winsup/cygwin/ctype.cc | 6 +- winsup/cygwin/nlsfuncs.cc | 2 +- 12 files changed, 87 insertions(+), 88 deletions(-) diff --git a/newlib/libc/ctype/ctype_.c b/newlib/libc/ctype/ctype_.c index f6ea63707..8945c5631 100644 --- a/newlib/libc/ctype/ctype_.c +++ b/newlib/libc/ctype/ctype_.c @@ -36,6 +36,7 @@ static char sccsid[] = "@(#)ctype_.c 5.6 (Berkeley) 6/1/90"; #endif /* LIBC_SCCS and not lint */ #include +#include "../locale/setlocale.h" #define _CTYPE_DATA_0_127 \ _C, _C, _C, _C, _C, _C, _C, _C, \ @@ -148,7 +149,7 @@ char *__ctype_ptr__ = (char *) _ctype_; compatibility with applications built under older Cygwin releases. */ #ifndef __CYGWIN__ void -__set_ctype (struct _reent *, const char *charset) +__set_ctype (struct __locale_t *loc, const char *charset) { #if defined(_MB_EXTENDED_CHARSETS_ISO) || defined(_MB_EXTENDED_CHARSETS_WINDOWS) int idx; @@ -184,15 +185,21 @@ __set_ctype (struct _reent *, const char *charset) if (!ctype_ptr) { # if defined(ALLOW_NEGATIVE_CTYPE_INDEX) - ctype_ptr = _ctype_b; + ctype_ptr = _ctype_b; # else - ctype_ptr = _ctype_; + ctype_ptr = _ctype_; # endif } # if defined(ALLOW_NEGATIVE_CTYPE_INDEX) - __ctype_ptr__ = ctype_ptr + 127; + if (loc) + loc->ctype_ptr = ctype_ptr + 127; + else + __ctype_ptr__ = ctype_ptr + 127; # else - __ctype_ptr__ = ctype_ptr; + if (loc) + loc->ctype_ptr = ctype_ptr; + else + __ctype_ptr__ = ctype_ptr; # endif } #endif /* !__CYGWIN__ */ diff --git a/newlib/libc/include/locale.h b/newlib/libc/include/locale.h index c7bfd5996..40e412451 100644 --- a/newlib/libc/include/locale.h +++ b/newlib/libc/include/locale.h @@ -29,10 +29,10 @@ #define LC_TIME_MASK (1 << LC_TIME) #define LC_MESSAGES_MASK (1 << LC_MESSAGES) -#define LC_GLOBAL_LOCALE ((struct _thr_locale_t *) -1) +#define LC_GLOBAL_LOCALE ((struct __locale_t *) -1) -struct _thr_locale_t; -typedef struct _thr_locale_t *locale_t; +struct __locale_t; +typedef struct __locale_t *locale_t; #endif _BEGIN_STD_C diff --git a/newlib/libc/include/sys/reent.h b/newlib/libc/include/sys/reent.h index 16716dd7d..bd32320a6 100644 --- a/newlib/libc/include/sys/reent.h +++ b/newlib/libc/include/sys/reent.h @@ -40,7 +40,7 @@ struct _reent; /* TODO: This structure type isn't defined yet. It's supposed to be used by locale-specific functions in case a per-thread locale per SUSv4 has been specified. */ -struct _thr_locale_t; +struct __locale_t; /* * If _REENT_SMALL is defined, we make struct _reent as small as possible, @@ -391,7 +391,7 @@ struct _reent /* TODO */ int _unspecified_locale_info; /* unused, reserved for locale stuff */ - struct _thr_locale_t *_locale;/* per-thread locale */ + struct __locale_t *_locale;/* per-thread locale */ struct _mprec *_mp; @@ -584,7 +584,7 @@ struct _reent /* TODO */ int _unspecified_locale_info; /* unused, reserved for locale stuff */ - struct _thr_locale_t *_locale;/* per-thread locale */ + struct __locale_t *_locale;/* per-thread locale */ int __sdidinit; /* 1 means stdio has been init'd */ diff --git a/newlib/libc/locale/lctype.c b/newlib/libc/locale/lctype.c index d59ae3734..8f005395c 100644 --- a/newlib/libc/locale/lctype.c +++ b/newlib/libc/locale/lctype.c @@ -52,7 +52,7 @@ static char _ctype_locale_buf[_CTYPE_BUF_SIZE]; /* NULL locale indicates global locale (called from setlocale) */ int -__ctype_load_locale (struct _thr_locale_t *locale, const char *name, +__ctype_load_locale (struct __locale_t *locale, const char *name, void *f_wctomb, const char *charset, int mb_cur_max) { int ret; diff --git a/newlib/libc/locale/lmessages.c b/newlib/libc/locale/lmessages.c index c768e4595..751bf0821 100644 --- a/newlib/libc/locale/lmessages.c +++ b/newlib/libc/locale/lmessages.c @@ -60,7 +60,7 @@ static char *_messages_locale_buf; #endif int -__messages_load_locale (struct _thr_locale_t *locale, const char *name, +__messages_load_locale (struct __locale_t *locale, const char *name, void *f_wctomb, const char *charset) { int ret; diff --git a/newlib/libc/locale/lmonetary.c b/newlib/libc/locale/lmonetary.c index 32e5ee525..fe15c83b3 100644 --- a/newlib/libc/locale/lmonetary.c +++ b/newlib/libc/locale/lmonetary.c @@ -89,7 +89,7 @@ cnv(const char *str) { #endif int -__monetary_load_locale (struct _thr_locale_t *locale, const char *name , +__monetary_load_locale (struct __locale_t *locale, const char *name , void *f_wctomb, const char *charset) { int ret; diff --git a/newlib/libc/locale/lnumeric.c b/newlib/libc/locale/lnumeric.c index 0e56f1662..0de7c236b 100644 --- a/newlib/libc/locale/lnumeric.c +++ b/newlib/libc/locale/lnumeric.c @@ -51,7 +51,7 @@ static char *_numeric_locale_buf; #endif int -__numeric_load_locale (struct _thr_locale_t *locale, const char *name , +__numeric_load_locale (struct __locale_t *locale, const char *name , void *f_wctomb, const char *charset) { int ret; diff --git a/newlib/libc/locale/locale.c b/newlib/libc/locale/locale.c index 0430f1f53..262f6893b 100644 --- a/newlib/libc/locale/locale.c +++ b/newlib/libc/locale/locale.c @@ -226,7 +226,7 @@ static char *categories[_LC_LAST] = { */ char __default_locale[ENCODING_LEN + 1] = DEFAULT_LOCALE; -struct _thr_locale_t __global_locale = +struct __locale_t __global_locale = { { "C", "C", DEFAULT_LOCALE, "C", "C", "C", "C", }, #ifdef __CYGWIN__ @@ -260,19 +260,12 @@ struct _thr_locale_t __global_locale = #endif }; -/* - * The locales we are going to try and load. These are only temporary - * variables and only used in setlocale. - */ -static char new_categories[_LC_LAST][ENCODING_LEN + 1]; -static char saved_categories[_LC_LAST][ENCODING_LEN + 1]; - /* 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)]; -static char *currentlocale(void); -static char *loadlocale(struct _reent *, int); +static char *currentlocale (void); +static char *loadlocale (struct __locale_t *, int, const char *); static const char *__get_locale_env(struct _reent *, int); #endif /* _MB_CAPABLE */ @@ -283,6 +276,9 @@ _DEFUN(_setlocale_r, (p, category, locale), int category _AND _CONST char *locale) { + static char new_categories[_LC_LAST][ENCODING_LEN + 1]; + static char saved_categories[_LC_LAST][ENCODING_LEN + 1]; + #ifndef _MB_CAPABLE if (locale) { @@ -396,21 +392,23 @@ _DEFUN(_setlocale_r, (p, category, locale), } if (category != LC_ALL) - return loadlocale (p, category); + return loadlocale (__get_global_locale (), category, + new_categories[category]); for (i = 1; i < _LC_LAST; ++i) { strcpy (saved_categories[i], __global_locale.categories[i]); - if (loadlocale (p, i) == NULL) + if (loadlocale (__get_global_locale (), i, new_categories[i]) == NULL) { saverr = p->_errno; for (j = 1; j < i; j++) { strcpy (new_categories[j], saved_categories[j]); - if (loadlocale (p, j) == NULL) + if (loadlocale (__get_global_locale (), j, new_categories[j]) + == NULL) { strcpy (new_categories[j], "C"); - loadlocale (p, j); + loadlocale (__get_global_locale (), j, new_categories[j]); } } p->_errno = saverr; @@ -423,7 +421,7 @@ _DEFUN(_setlocale_r, (p, category, locale), #ifdef _MB_CAPABLE static char * -currentlocale() +currentlocale () { int i; @@ -444,10 +442,10 @@ currentlocale() #ifdef _MB_CAPABLE -extern void __set_ctype (struct _reent *, const char *charset); +extern void __set_ctype (struct __locale_t *, const char *charset); static char * -loadlocale(struct _reent *p, int category) +loadlocale (struct __locale_t *loc, int category, const char *new_locale) { /* At this point a full-featured system would just load the locale specific data from the locale files. @@ -467,8 +465,8 @@ loadlocale(struct _reent *p, int category) int cjknarrow = 0; /* Avoid doing everything twice if nothing has changed. */ - if (!strcmp (new_categories[category], __global_locale.categories[category])) - return __global_locale.categories[category]; + if (!strcmp (new_locale, loc->categories[category])) + return loc->categories[category]; #ifdef __CYGWIN__ /* This additional code handles the case that the incoming locale string @@ -485,7 +483,7 @@ loadlocale(struct _reent *p, int category) restart: if (!locale) - locale = new_categories[category]; + locale = new_locale; else if (locale != tmp_locale) { locale = __set_locale_from_locale_alias (locale, tmp_locale); @@ -494,7 +492,7 @@ restart: } # define FAIL goto restart #else - locale = new_categories[category]; + locale = new_locale; # define FAIL return NULL #endif @@ -662,7 +660,7 @@ restart: c += 4; if (*c == '-') ++c; - val = _strtol_r (p, c, &end, 10); + val = strtol (c, &end, 10); if (val < 1 || val > 16 || val == 12 || *end) FAIL; strcpy (charset, "ISO-8859-"); @@ -685,7 +683,7 @@ restart: if (charset[1] != 'P' && charset[1] != 'p') FAIL; strncpy (charset, "CP", 2); - val = _strtol_r (p, charset + 2, &end, 10); + val = strtol (charset + 2, &end, 10); if (*end) FAIL; switch (val) @@ -860,60 +858,54 @@ restart: { case LC_CTYPE: #ifndef __HAVE_LOCALE_INFO__ - strcpy (__global_locale.ctype_codeset, charset); - __global_locale.mb_cur_max[0] = mbc_max; + strcpy (loc->ctype_codeset, charset); + loc->mb_cur_max[0] = mbc_max; #endif #ifdef __CYGWIN__ __mb_cur_max = mbc_max; /* Only for backward compat */ #endif - __global_locale.wctomb = l_wctomb; - __global_locale.mbtowc = l_mbtowc; - __set_ctype (NULL, charset); + loc->wctomb = l_wctomb; + loc->mbtowc = l_mbtowc; + __set_ctype (loc == __get_global_locale () ? NULL : loc, charset); /* Determine the width for the "CJK Ambiguous Width" category of characters. This is used in wcwidth(). Assume single width for single-byte charsets, and double width for multi-byte charsets other than UTF-8. For UTF-8, use double width for the East Asian languages ("ja", "ko", "zh"), and single width for everything else. Single width can also be forced with the "@cjknarrow" modifier. */ - __global_locale.cjk_lang = !cjknarrow - && mbc_max > 1 - && (charset[0] != 'U' - || strncmp (locale, "ja", 2) == 0 - || strncmp (locale, "ko", 2) == 0 - || strncmp (locale, "zh", 2) == 0); + loc->cjk_lang = !cjknarrow && mbc_max > 1 + && (charset[0] != 'U' + || strncmp (locale, "ja", 2) == 0 + || strncmp (locale, "ko", 2) == 0 + || strncmp (locale, "zh", 2) == 0); #ifdef __HAVE_LOCALE_INFO__ - ret = __ctype_load_locale (__get_global_locale (), locale, - (void *) l_wctomb, charset, mbc_max); + ret = __ctype_load_locale (loc, locale, (void *) l_wctomb, charset, + mbc_max); #endif /* __HAVE_LOCALE_INFO__ */ break; case LC_MESSAGES: #ifdef __HAVE_LOCALE_INFO__ - ret = __messages_load_locale (__get_global_locale (), locale, - (void *) l_wctomb, charset); + ret = __messages_load_locale (loc, locale, (void *) l_wctomb, charset); if (!ret) #else - strcpy (__global_locale.message_codeset, charset); + strcpy (loc->message_codeset, charset); #endif /* __HAVE_LOCALE_INFO__ */ break; #ifdef __HAVE_LOCALE_INFO__ #ifdef __CYGWIN__ /* Right now only Cygwin supports a __collate_load_locale function at all. */ case LC_COLLATE: - ret = __collate_load_locale (__get_global_locale (), locale, - (void *) l_mbtowc, charset); + ret = __collate_load_locale (loc, locale, (void *) l_mbtowc, charset); break; #endif case LC_MONETARY: - ret = __monetary_load_locale (__get_global_locale (), locale, - (void *) l_wctomb, charset); + ret = __monetary_load_locale (loc, locale, (void *) l_wctomb, charset); break; case LC_NUMERIC: - ret = __numeric_load_locale (__get_global_locale (), locale, - (void *) l_wctomb, charset); + ret = __numeric_load_locale (loc, locale, (void *) l_wctomb, charset); break; case LC_TIME: - ret = __time_load_locale (__get_global_locale (), locale, - (void *) l_wctomb, charset); + ret = __time_load_locale (loc, locale, (void *) l_wctomb, charset); break; #endif /* __HAVE_LOCALE_INFO__ */ default: @@ -923,11 +915,11 @@ restart: if (ret) FAIL; #endif /* __HAVE_LOCALE_INFO__ */ - return strcpy(__global_locale.categories[category], new_categories[category]); + return strcpy(loc->categories[category], new_locale); } static const char * -__get_locale_env(struct _reent *p, int category) +__get_locale_env (struct _reent *p, int category) { const char *env; @@ -951,7 +943,7 @@ __get_locale_env(struct _reent *p, int category) #endif /* _MB_CAPABLE */ int -_DEFUN_VOID(__locale_mb_cur_max) +_DEFUN_VOID (__locale_mb_cur_max) { #ifdef __HAVE_LOCALE_INFO__ return __get_current_ctype_locale ()->mb_cur_max[0]; @@ -962,7 +954,7 @@ _DEFUN_VOID(__locale_mb_cur_max) #ifdef __HAVE_LOCALE_INFO__ char * -_DEFUN_VOID(__locale_ctype_ptr) +_DEFUN_VOID (__locale_ctype_ptr) { /* Only check if the current thread/reent has a locale. ctype_ptr is unused in __global_locale, rather the global variable __ctype_ptr__ is used. */ @@ -973,8 +965,8 @@ _DEFUN_VOID(__locale_ctype_ptr) #endif struct lconv * -_DEFUN(_localeconv_r, (data), - struct _reent *data) +_DEFUN (_localeconv_r, (data), + struct _reent *data) { #ifdef __HAVE_LOCALE_INFO__ const struct lc_numeric_T *n = __get_current_numeric_locale (); @@ -1020,15 +1012,15 @@ _DEFUN(_localeconv_r, (data), #ifndef _REENT_ONLY char * -_DEFUN(setlocale, (category, locale), - int category _AND - _CONST char *locale) +_DEFUN (setlocale, (category, locale), + int category _AND + _CONST char *locale) { return _setlocale_r (_REENT, category, locale); } struct lconv * -_DEFUN_VOID(localeconv) +_DEFUN_VOID (localeconv) { return _localeconv_r (_REENT); } diff --git a/newlib/libc/locale/setlocale.h b/newlib/libc/locale/setlocale.h index 50797db0c..fe3c5661d 100644 --- a/newlib/libc/locale/setlocale.h +++ b/newlib/libc/locale/setlocale.h @@ -165,7 +165,7 @@ struct lc_collate_T extern const struct lc_collate_T _C_collate_locale; #endif -struct _thr_locale_t +struct __locale_t { char categories[_LC_LAST][ENCODING_LEN + 1]; int (*wctomb) (struct _reent *, char *, wchar_t, @@ -197,18 +197,18 @@ struct _thr_locale_t #endif }; -extern struct _thr_locale_t __global_locale; +extern struct __locale_t __global_locale; /* In POSIX terms the global locale is the process-wide locale. Use this function to always refer to the global locale. */ -_ELIDABLE_INLINE struct _thr_locale_t * +_ELIDABLE_INLINE struct __locale_t * __get_global_locale () { return &__global_locale; } /* Per REENT locale. This is newlib-internal. */ -_ELIDABLE_INLINE struct _thr_locale_t * +_ELIDABLE_INLINE struct __locale_t * __get_locale_r (struct _reent *r) { return r->_locale; @@ -218,7 +218,7 @@ __get_locale_r (struct _reent *r) using locale info without providing a locale as parameter (*_l functions). The current locale is either the locale of the current thread, if the thread called uselocale, or the global locale if not. */ -_ELIDABLE_INLINE struct _thr_locale_t * +_ELIDABLE_INLINE struct __locale_t * __get_current_locale () { return _REENT->_locale ?: &__global_locale; @@ -292,18 +292,18 @@ __locale_cjk_lang (void) #endif } -int __ctype_load_locale (struct _thr_locale_t *, const char *, void *, +int __ctype_load_locale (struct __locale_t *, const char *, void *, const char *, int); -int __monetary_load_locale (struct _thr_locale_t *, const char *, void *, +int __monetary_load_locale (struct __locale_t *, const char *, void *, const char *); -int __numeric_load_locale (struct _thr_locale_t *, const char *, void *, +int __numeric_load_locale (struct __locale_t *, const char *, void *, const char *); -int __time_load_locale (struct _thr_locale_t *, const char *, void *, +int __time_load_locale (struct __locale_t *, const char *, void *, const char *); -int __messages_load_locale (struct _thr_locale_t *, const char *, void *, +int __messages_load_locale (struct __locale_t *, const char *, void *, const char *); #ifdef __CYGWIN__ -int __collate_load_locale (struct _thr_locale_t *, const char *, void *, +int __collate_load_locale (struct __locale_t *, const char *, void *, const char *); extern void __set_charset_from_locale (const char *locale, char *charset); diff --git a/newlib/libc/locale/timelocal.c b/newlib/libc/locale/timelocal.c index 5e64456ab..c94fdf717 100644 --- a/newlib/libc/locale/timelocal.c +++ b/newlib/libc/locale/timelocal.c @@ -152,7 +152,7 @@ static char *time_locale_buf; #endif int -__time_load_locale (struct _thr_locale_t *locale, const char *name, +__time_load_locale (struct __locale_t *locale, const char *name, void *f_wctomb, const char *charset) { int ret; diff --git a/winsup/cygwin/ctype.cc b/winsup/cygwin/ctype.cc index 94de81e6c..a7dc18a5d 100644 --- a/winsup/cygwin/ctype.cc +++ b/winsup/cygwin/ctype.cc @@ -19,7 +19,7 @@ extern const char __ctype_cp[22][128 + 256]; /* Newlib */ extern const char __ctype_iso[15][128 + 256]; /* Newlib */ void -__set_ctype (struct _reent *reent, const char *charset) +__set_ctype (struct __locale_t *loc, const char *charset) { int idx; char *ctype_ptr = NULL; @@ -63,8 +63,8 @@ __set_ctype (struct _reent *reent, const char *charset) } ctype_ptr = (char *) _ctype_b; } - if (reent) - __get_locale_r (reent)->ctype_ptr = ctype_ptr + 127; + if (loc) + loc->ctype_ptr = ctype_ptr + 127; else __ctype_ptr__ = ctype_ptr + 127; } diff --git a/winsup/cygwin/nlsfuncs.cc b/winsup/cygwin/nlsfuncs.cc index 2ba9f3244..021af44cb 100644 --- a/winsup/cygwin/nlsfuncs.cc +++ b/winsup/cygwin/nlsfuncs.cc @@ -1070,7 +1070,7 @@ __set_lc_messages_from_win (const char *name, LC_COLLATE locale information. This is subsequently accessed by the below functions strcoll, strxfrm, wcscoll, wcsxfrm. */ extern "C" int -__collate_load_locale (struct _thr_locale_t *locale, const char *name, +__collate_load_locale (struct __locale_t *locale, const char *name, void *f_mbtowc, const char *charset) { const struct lc_collate_T *ccop;