diff --git a/ChangeLog b/ChangeLog index e69a58930c..3025aeab19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,53 @@ 2002-08-03 Roland McGrath + * locale/setlocale.c (_nl_current_names): Variable moved ... + * locale/localename.c (_nl_current_names): ... here, new file. + Make it global, with attribute_hidden. + * locale/localeinfo.h: Declare it. + * locale/Makefile (aux): Add localename. + * locale/localename.c (__current_locale_name): New function. + * include/locale.h (__current_locale_name): Declare it. + * intl/dcigettext.c (guess_category_value): Use that instead of + calling setlocale. + + * locale/locale.h [__USE_GNU] (locale_t): New type alias of __locale_t. + [__USE_GNU] (newlocale, duplocale, freelocale, uselocale): New decls. + [__USE_GNU] (LC_GLOBAL_LOCALE): New macro. + * locale/newlocale.c: Add alias to __ name. + * locale/duplocale.c: Likewise. + * locale/freelocale.c: Likewise. + * locale/uselocale.c: New file. + * locale/Makefile (routines): Add it. + * locale/Versions (libc: GLIBC_2.3): New set. + Add newlocale, duplocale, freelocale, uselocale. + (libc: GLIBC_PRIVATE): Add __uselocale. + + * locale/localeinfo.h [SHARED] + (_NL_CURRENT_LOCALE): New macro, defined to fetch a tsd value. + (_NL_CURRENT_DATA): Define using that. + (_NL_CURRENT, _NL_CURRENT_WSTR, _NL_CURRENT_WORD): Define using that. + (_NL_CURRENT_DEFINE): Define to empty. + [! SHARED]: Decls of _nl_current_CATEGORY and _nl_current + conditionalized on this. + * locale/xlocale.c (NL_C_INTIIALIZER): New macro, + taking initializer of _nl_C_locobj. + [SHARED] (_nl_global_locale): New variable, using that initializer. + (_nl_C_locobj): Use new macro for initialzier. + * locale/setlocale.c [! SHARED] (_nl_current): Conditionalize on this. + [! SHARED] (CATEGORY_USED): New macro. + [SHARED] (CATEGORY_USED, _nl_C): New macros. + (setdata, setlocale): Use that macro instead of examining _nl_current. + (setdata): Set the slot in _nl_global_locale. + Conditionalize setting of _nl_current on [! SHARED]. + * locale/findlocale.c [SHARED] (_nl_C): Define as a macro instead of + declaration as an extern. + * locale/newlocale.c (__newlocale): Use _nl_C_locobj instead of _nl_C. + + * include/locale.h: Use libc_hidden_proto for setlocale. + * locale/setlocale.c: Add libc_hidden_def. + + * locale/setlocale.c (free_mem): Use _NL_CURRENT_DATA. + * include/search.h: Use libc_hidden_proto for hsearch_r, lfind. * misc/hsearch_r.c: Add libc_hidden_def. * misc/lsearch.c: Likewise. diff --git a/include/locale.h b/include/locale.h index a79888139b..b339953a93 100644 --- a/include/locale.h +++ b/include/locale.h @@ -1,6 +1,8 @@ #ifndef _LOCALE_H #include +libc_hidden_proto (setlocale) + /* This has to be changed whenever a new locale is defined. */ #define __LC_LAST 13 @@ -12,4 +14,7 @@ extern struct __locale_struct _nl_C_locobj attribute_hidden; /* Now define the internal interfaces. */ extern struct lconv *__localeconv (void); +/* Fetch the name of the current locale set in the given category. */ +extern const char *__current_locale_name (int category) attribute_hidden; + #endif diff --git a/intl/dcigettext.c b/intl/dcigettext.c index eb74ac2704..344736e9de 100644 --- a/intl/dcigettext.c +++ b/intl/dcigettext.c @@ -1059,7 +1059,7 @@ guess_category_value (category, categoryname) `LC_xxx', and `LANG'. On some systems this can be done by the `setlocale' function itself. */ #ifdef _LIBC - retval = setlocale (category, NULL); + retval = __current_locale_name (category); #else retval = _nl_locale_name (category, categoryname); #endif diff --git a/locale/Makefile b/locale/Makefile index 3b3af99171..ebcf7bd668 100644 --- a/locale/Makefile +++ b/locale/Makefile @@ -37,12 +37,12 @@ distribute = localeinfo.h categories.def iso-639.def iso-3166.def \ 3level.h charmap-dir.h locarchive.c) routines = setlocale findlocale loadlocale localeconv nl_langinfo \ nl_langinfo_l mb_cur_max \ - newlocale duplocale freelocale + newlocale duplocale freelocale uselocale tests = tst-C-locale categories = ctype messages monetary numeric time paper name \ address telephone measurement identification collate aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \ - xlocale + xlocale localename others = localedef locale #others-static = localedef locale install-bin = localedef locale diff --git a/locale/Versions b/locale/Versions index 094a392fac..bb875f84a4 100644 --- a/locale/Versions +++ b/locale/Versions @@ -46,9 +46,16 @@ libc { # missing function from the experimental locale implementation __nl_langinfo_l; } + GLIBC_2.3 { + # the new "experimental" interface is now public + newlocale; duplocale; freelocale; uselocale; + } GLIBC_PRIVATE { # global variables __collate_element_hash; __collate_element_strings; __collate_symbol_classes; __collate_symbol_hash; __collate_symbol_strings; + + # this internal name is used by libpthread + __uselocale; } } diff --git a/locale/duplocale.c b/locale/duplocale.c index efbacbb724..f8e8e7299e 100644 --- a/locale/duplocale.c +++ b/locale/duplocale.c @@ -61,3 +61,4 @@ __duplocale (__locale_t dataset) return result; } +weak_alias (__duplocale, duplocale) diff --git a/locale/findlocale.c b/locale/findlocale.c index 004f93b725..75784bab9f 100644 --- a/locale/findlocale.c +++ b/locale/findlocale.c @@ -30,8 +30,12 @@ #include "../iconv/gconv_charset.h" +#ifndef SHARED /* Constant data defined in setlocale.c. */ extern struct locale_data *const _nl_C[] attribute_hidden; +#else +# define _nl_C (_nl_C_locobj.__locales) +#endif /* For each category we keep a list of records for the locale files diff --git a/locale/freelocale.c b/locale/freelocale.c index 282d83853a..de7e554c84 100644 --- a/locale/freelocale.c +++ b/locale/freelocale.c @@ -48,3 +48,4 @@ __freelocale (__locale_t dataset) /* It's done. */ __libc_lock_unlock (__libc_setlocale_lock); } +weak_alias (__freelocale, freelocale) diff --git a/locale/locale.h b/locale/locale.h index 9133038178..34463fd55e 100644 --- a/locale/locale.h +++ b/locale/locale.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,92,1995-1999,2000,2001 Free Software Foundation, Inc. +/* Copyright (C) 1991,92,95-99,2000,01,02 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -140,6 +140,8 @@ extern struct lconv *localeconv (void) __THROW; /* Get locale datatype definition. */ # include +typedef __locale_t locale_t; + /* Return a reference to a data structure representing a set of locale datasets. Unlike for the CATEGORY parameter for `setlocale' the CATEGORY_MASK parameter here uses a single bit for each category. @@ -148,14 +150,31 @@ extern struct lconv *localeconv (void) __THROW; record is replaced. */ extern __locale_t __newlocale (int __category_mask, __const char *__locale, __locale_t __base) __THROW; +extern __locale_t newlocale (int __category_mask, __const char *__locale, + __locale_t __base) __THROW; /* Return a duplicate of the set of locale in DATASET. All usage counters are increased if necessary. */ extern __locale_t __duplocale (__locale_t __dataset) __THROW; +extern __locale_t duplocale (__locale_t __dataset) __THROW; /* Free the data associated with a locale dataset previously returned by a call to `setlocale_r'. */ extern void __freelocale (__locale_t __dataset) __THROW; +extern void freelocale (__locale_t __dataset) __THROW; + +/* Switch the current thread's locale to DATASET. + If DATASET is null, instead just return the current setting. + The special value LC_GLOBAL_LOCALE is the initial setting + for all threads and can also be installed any time, meaning + the thread uses the global settings controlled by `setlocale'. */ +extern __locale_t __uselocale (__locale_t __dataset) __THROW; +extern __locale_t uselocale (__locale_t __dataset) __THROW; + +/* This value can be passed to `uselocale' and may be returned by it. + Passing this value to any other function has undefined behavior. */ +# define LC_GLOBAL_LOCALE ((__locale_t) -1L) + #endif __END_DECLS diff --git a/locale/localeinfo.h b/locale/localeinfo.h index 3a43469c84..97471e9be5 100644 --- a/locale/localeinfo.h +++ b/locale/localeinfo.h @@ -138,18 +138,8 @@ enum #define _ISCTYPE(c, desc) \ (((((const uint32_t *) (desc)) - 8)[(c) >> 5] >> ((c) & 0x1f)) & 1) - -/* For each category declare the variable for the current locale data. */ -/* XXX _nl_current_LC_CTYPE and _nl_current_LC_COLLATE were exported - but where are they used? */ -#define DEFINE_CATEGORY(category, category_name, items, a) \ -extern struct locale_data *_nl_current_##category attribute_hidden; -#include "categories.def" -#undef DEFINE_CATEGORY - extern const char *const _nl_category_names[__LC_LAST] attribute_hidden; extern const size_t _nl_category_name_sizes[__LC_LAST] attribute_hidden; -extern struct locale_data * *const _nl_current[__LC_LAST] attribute_hidden; /* Name of the standard locales. */ extern const char _nl_C_name[] attribute_hidden; @@ -158,9 +148,25 @@ extern const char _nl_POSIX_name[] attribute_hidden; /* The standard codeset. */ extern const char _nl_C_codeset[] attribute_hidden; +/* Name of current locale for each individual category. + Each is malloc'd unless it is _nl_C_name. */ +extern const char *_nl_current_names[] attribute_hidden; + +#ifndef SHARED + +/* For each category declare the variable for the current locale data. */ +/* XXX _nl_current_LC_CTYPE and _nl_current_LC_COLLATE were exported + but where are they used? */ +#define DEFINE_CATEGORY(category, category_name, items, a) \ +extern struct locale_data *_nl_current_##category attribute_hidden; +#include "categories.def" +#undef DEFINE_CATEGORY +extern struct locale_data * *const _nl_current[__LC_LAST] attribute_hidden; + /* Return a pointer to the current `struct locale_data' for CATEGORY. */ -#define _NL_CURRENT_DATA(category) \ - ((const struct locale_data *) _nl_current_##category) +#define _NL_CURRENT_DATA(category) _nl_current_##category +/* Hackety hack, don't talk back. */ +#define _nl_current_category (*_nl_current[category]) /* Extract the current CATEGORY locale's string for ITEM. */ #define _NL_CURRENT(category, item) \ @@ -179,6 +185,43 @@ extern const char _nl_C_codeset[] attribute_hidden; extern struct locale_data _nl_C_##category attribute_hidden; \ struct locale_data *_nl_current_##category = &_nl_C_##category +#else + +/* All categories are always loaded in the shared library, so there is no + point in having lots of separate symbols for linking. */ + +# include + +__libc_tsd_define (extern, LOCALE) + +extern struct __locale_struct _nl_global_locale attribute_hidden; + +# define _NL_CURRENT_LOCALE \ + ((__locale_t) __libc_tsd_get (LOCALE)) + +/* Return a pointer to the current `struct locale_data' for CATEGORY. */ +# define _NL_CURRENT_DATA(category) \ + (_NL_CURRENT_LOCALE->__locales[category]) + +/* Extract the current CATEGORY locale's string for ITEM. */ +# define _NL_CURRENT(category, item) \ + (_NL_CURRENT_DATA (category)->values[_NL_ITEM_INDEX (item)].string) + +/* Extract the current CATEGORY locale's string for ITEM. */ +# define _NL_CURRENT_WSTR(category, item) \ + ((wchar_t *) _NL_CURRENT_DATA (category)->values[_NL_ITEM_INDEX (item)].wstr) + +/* Extract the current CATEGORY locale's word for ITEM. */ +# define _NL_CURRENT_WORD(category, item) \ + (_NL_CURRENT_DATA (category)->values[_NL_ITEM_INDEX (item)].word) + +/* This is used in lc-CATEGORY.c to define _nl_current_CATEGORY. */ +# define _NL_CURRENT_DEFINE(category) \ + /* No per-category variable here. */ + +#endif + + /* Load the locale data for CATEGORY from the file specified by *NAME. If *NAME is "", use environment variables as specified by POSIX, and fill in *NAME with the actual name used. The directories diff --git a/locale/localename.c b/locale/localename.c new file mode 100644 index 0000000000..045cc712d2 --- /dev/null +++ b/locale/localename.c @@ -0,0 +1,42 @@ +/* current locale setting names + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "localeinfo.h" + +/* Name of current locale for each individual category. + Each is malloc'd unless it is _nl_C_name. */ +const char *_nl_current_names[] attribute_hidden = + { +#define DEFINE_CATEGORY(category, category_name, items, a) \ + [category] = _nl_C_name, +#include "categories.def" +#undef DEFINE_CATEGORY + [LC_ALL] = _nl_C_name /* For LC_ALL. */ + }; + +const char * +attribute_hidden +__current_locale_name (int category) +{ +#if 0 + return _NL_CURRENT_DATA (category)->name; +#else + return _nl_current_names[category]; +#endif +} diff --git a/locale/newlocale.c b/locale/newlocale.c index 6306ba2a8a..1442f86e81 100644 --- a/locale/newlocale.c +++ b/locale/newlocale.c @@ -26,9 +26,6 @@ #include "localeinfo.h" -/* Constant data defined in setlocale.c. */ -extern struct locale_data *const _nl_C[] attribute_hidden; - /* Use this when we come along an error. */ #define ERROR_RETURN \ do { \ @@ -65,12 +62,8 @@ __newlocale (int category_mask, const char *locale, __locale_t base) if (base != NULL) result = *base; else - { - /* Fill with pointers to C locale data. */ - for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) - result.__locales[cnt] = _nl_C[cnt]; - } + /* Fill with pointers to C locale data. */ + result = _nl_C_locobj; /* If no category is to be set we return BASE if available or a dataset using the C locale data. */ @@ -184,3 +177,4 @@ __newlocale (int category_mask, const char *locale, __locale_t base) return result_ptr; } +weak_alias (__newlocale, newlocale) diff --git a/locale/setlocale.c b/locale/setlocale.c index 87573024d3..50963d152c 100644 --- a/locale/setlocale.c +++ b/locale/setlocale.c @@ -27,6 +27,8 @@ #include "localeinfo.h" +#ifndef SHARED + /* For each category declare two external variables (with weak references): extern const struct locale_data *_nl_current_CATEGORY; This points to the current locale's in-core data for CATEGORY. @@ -35,6 +37,8 @@ Both are weak references; if &_nl_current_CATEGORY is zero, then nothing is using the locale data. */ #define DEFINE_CATEGORY(category, category_name, items, a) \ +weak_extern (_nl_current_##category) \ +weak_extern (_nl_C_##category) \ extern struct locale_data *_nl_current_##category; \ extern struct locale_data _nl_C_##category; #include "categories.def" @@ -63,6 +67,19 @@ struct locale_data *const _nl_C[] attribute_hidden = #undef DEFINE_CATEGORY }; +# define CATEGORY_USED(category) (_nl_current[category] != NULL) + +#else + +/* The shared library always loads all the categories, + and the current global settings are kept in _nl_global_locale. */ + +# define _nl_C (_nl_C_locobj.__locales) + +# define CATEGORY_USED(category) (1) + +#endif + /* Define an array of category names (also the environment variable names), indexed by integral category. */ @@ -105,18 +122,6 @@ static void (*const _nl_category_postload[]) (void) = }; -/* Name of current locale for each individual category. - Each is malloc'd unless it is nl_C_name. */ -static const char *_nl_current_names[] = - { -#define DEFINE_CATEGORY(category, category_name, items, a) \ - [category] = _nl_C_name, -#include "categories.def" -#undef DEFINE_CATEGORY - [LC_ALL] = _nl_C_name /* For LC_ALL. */ - }; - - /* Lock for protecting global data. */ __libc_lock_define_initialized (, __libc_setlocale_lock attribute_hidden) @@ -200,20 +205,24 @@ setname (int category, const char *name) _nl_current_names[category] = name; } - /* Put DATA in *_nl_current[CATEGORY]. */ static inline void setdata (int category, struct locale_data *data) { - if (_nl_current[category] != NULL) + if (CATEGORY_USED (category)) { +#ifdef SHARED + _nl_global_locale.__locales[category] = data; +#endif +#ifndef SHARED +# warning when uselocale exists it will need the line above too *_nl_current[category] = data; +#endif if (_nl_category_postload[category]) (*_nl_category_postload[category]) (); } } - char * setlocale (int category, const char *locale) { @@ -371,7 +380,7 @@ setlocale (int category, const char *locale) /* Protect global data. */ __libc_lock_lock (__libc_setlocale_lock); - if (_nl_current[category] != NULL) + if (CATEGORY_USED (category)) { /* Only actually load the data if anything will use it. */ newdata = _nl_find_locale (locale_path, locale_path_len, category, @@ -409,7 +418,7 @@ setlocale (int category, const char *locale) } else { - if (_nl_current[category] != NULL) + if (CATEGORY_USED (category)) setdata (category, newdata); setname (category, newname[0]); @@ -429,6 +438,7 @@ setlocale (int category, const char *locale) return (char *) newname[0]; } } +libc_hidden_def (setlocale) static void __attribute__ ((unused)) free_mem (void) @@ -438,7 +448,7 @@ free_mem (void) for (category = 0; category < __LC_LAST; ++category) if (category != LC_ALL) { - struct locale_data *here = *_nl_current[category]; + struct locale_data *here = _NL_CURRENT_DATA (category); struct loaded_l10nfile *runp = _nl_locale_file_list[category]; /* If this category is already "C" don't do anything. */ diff --git a/locale/uselocale.c b/locale/uselocale.c new file mode 100644 index 0000000000..1e819381de --- /dev/null +++ b/locale/uselocale.c @@ -0,0 +1,52 @@ +/* uselocale -- fetch and set the current per-thread locale + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "localeinfo.h" + +#ifdef SHARED + +/* Switch the current thread's locale to DATASET. + If DATASET is null, instead just return the current setting. + The special value LC_GLOBAL_LOCALE is the initial setting + for all threads, and means the thread uses the global + setting controlled by `setlocale'. */ +locale_t +__uselocale (locale_t newloc) +{ + if (newloc == NULL) + { + locale_t loc = __libc_tsd_get (LOCALE); + return loc == &_nl_global_locale ? LC_GLOBAL_LOCALE : loc; + } + if (newloc == LC_GLOBAL_LOCALE) + { + __libc_tsd_set (LOCALE, &_nl_global_locale); + return LC_GLOBAL_LOCALE; + } + __libc_tsd_set (LOCALE, newloc); + return newloc; +} +weak_alias (__uselocale, uselocale) + +#else + +# warning uselocale not implemented for static linking yet + +#endif diff --git a/locale/xlocale.c b/locale/xlocale.c index 79ec548473..daea563ff1 100644 --- a/locale/xlocale.c +++ b/locale/xlocale.c @@ -32,24 +32,39 @@ extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden; extern const char _nl_C_LC_CTYPE_tolower[] attribute_hidden; -struct __locale_struct _nl_C_locobj attribute_hidden = - { - .__locales = - { - [LC_CTYPE] = &_nl_C_LC_CTYPE, - [LC_NUMERIC] = &_nl_C_LC_NUMERIC, - [LC_TIME] = &_nl_C_LC_TIME, - [LC_COLLATE] = &_nl_C_LC_COLLATE, - [LC_MONETARY] = &_nl_C_LC_MONETARY, - [LC_MESSAGES] = &_nl_C_LC_MESSAGES, - [LC_PAPER] = &_nl_C_LC_PAPER, - [LC_NAME] = &_nl_C_LC_NAME, - [LC_ADDRESS] = &_nl_C_LC_ADDRESS, - [LC_TELEPHONE] = &_nl_C_LC_TELEPHONE, - [LC_MEASUREMENT] = &_nl_C_LC_MEASUREMENT, - [LC_IDENTIFICATION] = &_nl_C_LC_IDENTIFICATION - }, - .__ctype_b = (const unsigned short int *) _nl_C_LC_CTYPE_class + 128, - .__ctype_tolower = (const int *) _nl_C_LC_CTYPE_tolower + 128, - .__ctype_toupper = (const int *) _nl_C_LC_CTYPE_toupper + 128 - }; +#define NL_C_INITIALIZER \ + { \ + .__locales = \ + { \ + [LC_CTYPE] = &_nl_C_LC_CTYPE, \ + [LC_NUMERIC] = &_nl_C_LC_NUMERIC, \ + [LC_TIME] = &_nl_C_LC_TIME, \ + [LC_COLLATE] = &_nl_C_LC_COLLATE, \ + [LC_MONETARY] = &_nl_C_LC_MONETARY, \ + [LC_MESSAGES] = &_nl_C_LC_MESSAGES, \ + [LC_PAPER] = &_nl_C_LC_PAPER, \ + [LC_NAME] = &_nl_C_LC_NAME, \ + [LC_ADDRESS] = &_nl_C_LC_ADDRESS, \ + [LC_TELEPHONE] = &_nl_C_LC_TELEPHONE, \ + [LC_MEASUREMENT] = &_nl_C_LC_MEASUREMENT, \ + [LC_IDENTIFICATION] = &_nl_C_LC_IDENTIFICATION \ + }, \ + .__ctype_b = (const unsigned short int *) _nl_C_LC_CTYPE_class + 128, \ + .__ctype_tolower = (const int *) _nl_C_LC_CTYPE_tolower + 128, \ + .__ctype_toupper = (const int *) _nl_C_LC_CTYPE_toupper + 128 \ + } + +struct __locale_struct _nl_C_locobj attribute_hidden = NL_C_INITIALIZER; + +#ifdef SHARED +struct __locale_struct _nl_global_locale attribute_hidden = NL_C_INITIALIZER; + +# if USE_TLS && HAVE___THREAD +/* The tsd macros don't permit an initializer. */ +__thread void *__libc_tsd_LOCALE = &_nl_global_locale; +# else +__libc_tsd_define (, LOCALE) +void *__libc_tsd_LOCALE_data = &_nl_global_locale; +# endif + +#endif