mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-23 09:43:32 +08:00
Make uselocale support static linking.
* locale/xlocale.c: Revert changes putting _nl_global_locale here. This file again just defines _nl_C_locobj. (_nl_C_locobj): Use a categories.def iterator in the initializer. * locale/global-locale.c: New file. Define _nl_global_locale here, using all weak references in the initializer. * locale/Makefile (aux): Add global-locale. * locale/localeinfo.h (_nl_global_locale, _NL_CURRENT_LOCALE): Make these unconditional, along with the tsd decl. [!SHARED && HAVE___THREAD && HAVE_WEAK_SYMBOLS] (NL_CURRENT_INDIRECT): Define it under these conditions. [NL_CURRENT_INDIRECT]: Test this instead of [! SHARED]. Don't declare _nl_current. Declare _nl_current_LC_FOO as `extern __thread struct locale_data *const *'. [NL_CURRENT_INDIRECT] (_NL_CURRENT_DATA, _NL_CURRENT, _NL_CURRENT_WSTR): Add indirection. [NL_CURRENT_INDIRECT] (_NL_CURRENT_DEFINE): Rewritten. Define the thread variable _nl_current_LC_FOO and also a special absolute symbol _nl_current_LC_FOO_used. * locale/uselocale.c (__uselocale) [NL_CURRENT_INDIRECT]: Set each _nl_current_LC_FOO symbol to point into the new locale, using weak references to test if _nl_current_LC_FOO_used was linked in. * locale/setlocale.c [! SHARED]: Replace this conditional ... [NL_CURRENT_INDIRECT]: ... with this one. (_nl_current, _nl_C): Variables removed. [NL_CURRENT_INDIRECT] (_nl_current_used): New variable, table of weak references to _nl_current_LC_FOO_used. [NL_CURRENT_INDIRECT] (CATEGORY_USED): Define using that table. (free_category): New function, broken out of ... (free_mem): ... here. Call that. (free_mem) [NL_CURRENT_INDIRECT]: Use a categories.def iterator instead of a loop. __USING_NAMESPACE_C99 depending on _GLIBCPP_USE_NAMESPACES.
This commit is contained in:
parent
d10c64301e
commit
1a0d874ed4
35
ChangeLog
35
ChangeLog
@ -1,5 +1,38 @@
|
||||
2002-08-28 Roland McGrath <roland@redhat.com>
|
||||
|
||||
Make uselocale support static linking.
|
||||
* locale/xlocale.c: Revert changes putting _nl_global_locale here.
|
||||
This file again just defines _nl_C_locobj.
|
||||
(_nl_C_locobj): Use a categories.def iterator in the initializer.
|
||||
* locale/global-locale.c: New file. Define _nl_global_locale here,
|
||||
using all weak references in the initializer.
|
||||
* locale/Makefile (aux): Add global-locale.
|
||||
* locale/localeinfo.h (_nl_global_locale, _NL_CURRENT_LOCALE): Make
|
||||
these unconditional, along with the tsd decl.
|
||||
[!SHARED && HAVE___THREAD && HAVE_WEAK_SYMBOLS] (NL_CURRENT_INDIRECT):
|
||||
Define it under these conditions.
|
||||
[NL_CURRENT_INDIRECT]: Test this instead of [! SHARED].
|
||||
Don't declare _nl_current. Declare _nl_current_LC_FOO as
|
||||
`extern __thread struct locale_data *const *'.
|
||||
[NL_CURRENT_INDIRECT]
|
||||
(_NL_CURRENT_DATA, _NL_CURRENT, _NL_CURRENT_WSTR): Add indirection.
|
||||
[NL_CURRENT_INDIRECT] (_NL_CURRENT_DEFINE): Rewritten. Define
|
||||
the thread variable _nl_current_LC_FOO and also a special absolute
|
||||
symbol _nl_current_LC_FOO_used.
|
||||
* locale/uselocale.c (__uselocale) [NL_CURRENT_INDIRECT]:
|
||||
Set each _nl_current_LC_FOO symbol to point into the new locale,
|
||||
using weak references to test if _nl_current_LC_FOO_used was linked in.
|
||||
* locale/setlocale.c [! SHARED]: Replace this conditional ...
|
||||
[NL_CURRENT_INDIRECT]: ... with this one.
|
||||
(_nl_current, _nl_C): Variables removed.
|
||||
[NL_CURRENT_INDIRECT] (_nl_current_used): New variable, table of
|
||||
weak references to _nl_current_LC_FOO_used.
|
||||
[NL_CURRENT_INDIRECT] (CATEGORY_USED): Define using that table.
|
||||
(free_category): New function, broken out of ...
|
||||
(free_mem): ... here. Call that.
|
||||
(free_mem) [NL_CURRENT_INDIRECT]: Use a categories.def iterator
|
||||
instead of a loop.
|
||||
|
||||
* sysdeps/generic/libc-tls.c (__libc_setup_tls): Don't check for
|
||||
PT_LOAD program headers and don't try to relocate PT_TLS's p_vaddr;
|
||||
it is already absolute.
|
||||
@ -64,7 +97,7 @@
|
||||
|
||||
* misc/sys/cdefs.h: Define __BEGIN_NAMESPACE_STD, __END_NAMESPACE_STD,
|
||||
__USING_NAMESPACE_STD, __BEGIN_NAMESPACE_C99, __END_NAMESPACE_C99, and
|
||||
__USING_NAMESPACE_C99 dependingon _GLIBCPP_USE_NAMESPACES.
|
||||
__USING_NAMESPACE_C99 depending on _GLIBCPP_USE_NAMESPACES.
|
||||
* ctype/ctype.h: Prepare headers for use in ISO C++ compliant
|
||||
implementations.
|
||||
* libio/stdio.h: Likewise.
|
||||
|
@ -42,7 +42,7 @@ 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 localename
|
||||
xlocale localename global-locale
|
||||
others = localedef locale
|
||||
#others-static = localedef locale
|
||||
install-bin = localedef locale
|
||||
|
63
locale/global-locale.c
Normal file
63
locale/global-locale.c
Normal file
@ -0,0 +1,63 @@
|
||||
/* Locale object representing the global locale controlled by setlocale.
|
||||
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 <locale.h>
|
||||
#include "localeinfo.h"
|
||||
|
||||
#define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
extern struct locale_data _nl_C_##category; weak_extern (_nl_C_##category)
|
||||
#include "categories.def"
|
||||
#undef DEFINE_CATEGORY
|
||||
|
||||
/* Defined in locale/C-ctype.c. */
|
||||
extern const char _nl_C_LC_CTYPE_class[] attribute_hidden;
|
||||
extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden;
|
||||
extern const char _nl_C_LC_CTYPE_tolower[] attribute_hidden;
|
||||
weak_extern (_nl_C_LC_CTYPE_class)
|
||||
weak_extern (_nl_C_LC_CTYPE_toupper)
|
||||
weak_extern (_nl_C_LC_CTYPE_tolower)
|
||||
|
||||
/* Here we define the locale object maintained by setlocale.
|
||||
The references in the initializer are weak, so the parts of
|
||||
the structure that are never referred to will be zero. */
|
||||
|
||||
struct __locale_struct _nl_global_locale attribute_hidden =
|
||||
{
|
||||
.__locales =
|
||||
{
|
||||
#define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
[category] = &_nl_C_##category,
|
||||
#include "categories.def"
|
||||
#undef DEFINE_CATEGORY
|
||||
},
|
||||
.__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
|
||||
};
|
||||
|
||||
#include <tls.h>
|
||||
#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)
|
||||
/* This is a bad kludge presuming the variable name used by the macros.
|
||||
Using typeof makes sure to barf if we do not match the macro definition. */
|
||||
__typeof (__libc_tsd_LOCALE_data) __libc_tsd_LOCALE_data = &_nl_global_locale;
|
||||
#endif
|
@ -155,54 +155,81 @@ extern const char _nl_C_codeset[] attribute_hidden;
|
||||
Each is malloc'd unless it is _nl_C_name. */
|
||||
extern const char *_nl_current_names[] attribute_hidden;
|
||||
|
||||
/* This is the internal locale_t object that holds the global locale
|
||||
controlled by calls to setlocale. A thread's TSD locale pointer
|
||||
points to this when `uselocale (LC_GLOBAL_LOCALE)' is in effect. */
|
||||
extern struct __locale_struct _nl_global_locale attribute_hidden;
|
||||
|
||||
#ifndef SHARED
|
||||
/* This fetches the thread-local locale_t pointer, either one set with
|
||||
uselocale or &_nl_global_locale. */
|
||||
#define _NL_CURRENT_LOCALE ((__locale_t) __libc_tsd_get (LOCALE))
|
||||
#include <bits/libc-tsd.h>
|
||||
__libc_tsd_define (extern, LOCALE)
|
||||
|
||||
/* 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? */
|
||||
|
||||
/* For static linking it is desireable to avoid always linking in the code
|
||||
and data for every category when we can tell at link time that they are
|
||||
unused. We can manage this playing some tricks with weak references.
|
||||
But with thread-local locale settings, it becomes quite ungainly unless
|
||||
we can use __thread variables. So only in that case do we attempt this. */
|
||||
#if !defined SHARED && defined HAVE___THREAD && defined HAVE_WEAK_SYMBOLS
|
||||
# include <tls.h>
|
||||
# if USE_TLS
|
||||
# define NL_CURRENT_INDIRECT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef NL_CURRENT_INDIRECT
|
||||
|
||||
/* For each category declare the thread-local variable for the current
|
||||
locale data. This has an extra indirection so it points at the
|
||||
__locales[CATEGORY] element in either _nl_global_locale or the current
|
||||
locale object set by uselocale, which points at the actual data. The
|
||||
reason for having these variables is so that references to particular
|
||||
categories will link in the lc-CATEGORY.c module to define this symbol,
|
||||
and we arrange that linking that module is what brings in all the code
|
||||
associated with this category. */
|
||||
#define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
extern struct locale_data *_nl_current_##category attribute_hidden;
|
||||
extern __thread struct locale_data *const *_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) _nl_current_##category
|
||||
/* Hackety hack, don't talk back. */
|
||||
#define _nl_current_category (*_nl_current[category])
|
||||
#define _NL_CURRENT_DATA(category) (*_nl_current_##category)
|
||||
|
||||
/* Extract the current CATEGORY locale's string for ITEM. */
|
||||
#define _NL_CURRENT(category, item) \
|
||||
(_nl_current_##category->values[_NL_ITEM_INDEX (item)].string)
|
||||
((*_nl_current_##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_##category->values[_NL_ITEM_INDEX (item)].wstr)
|
||||
((wchar_t *) (*_nl_current_##category)->values[_NL_ITEM_INDEX (item)].wstr)
|
||||
|
||||
/* Extract the current CATEGORY locale's word for ITEM. */
|
||||
#define _NL_CURRENT_WORD(category, item) \
|
||||
(_nl_current_##category->values[_NL_ITEM_INDEX (item)].word)
|
||||
((*_nl_current_##category)->values[_NL_ITEM_INDEX (item)].word)
|
||||
|
||||
/* This is used in lc-CATEGORY.c to define _nl_current_CATEGORY. */
|
||||
#define _NL_CURRENT_DEFINE(category) \
|
||||
extern struct locale_data _nl_C_##category attribute_hidden; \
|
||||
struct locale_data *_nl_current_##category = &_nl_C_##category
|
||||
__thread struct locale_data *const *_nl_current_##category \
|
||||
attribute_hidden = &_nl_global_locale.__locales[category]; \
|
||||
asm (_NL_CURRENT_DEFINE_STRINGIFY (ASM_GLOBAL_DIRECTIVE) \
|
||||
" " __SYMBOL_PREFIX "_nl_current_" #category "_used\n" \
|
||||
_NL_CURRENT_DEFINE_ABS (_nl_current_##category##_used, 1));
|
||||
#define _NL_CURRENT_DEFINE_STRINGIFY(x) _NL_CURRENT_DEFINE_STRINGIFY_1 (x)
|
||||
#define _NL_CURRENT_DEFINE_STRINGIFY_1(x) #x
|
||||
#ifdef HAVE_ASM_SET_DIRECTIVE
|
||||
# define _NL_CURRENT_DEFINE_ABS(sym, val) ".set " #sym ", " #val
|
||||
#else
|
||||
# define _NL_CURRENT_DEFINE_ABS(sym, val) #sym " = " #val
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/* All categories are always loaded in the shared library, so there is no
|
||||
point in having lots of separate symbols for linking. */
|
||||
|
||||
# include <bits/libc-tsd.h>
|
||||
|
||||
__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])
|
||||
|
@ -27,55 +27,39 @@
|
||||
|
||||
#include "localeinfo.h"
|
||||
|
||||
#ifndef SHARED
|
||||
#ifdef NL_CURRENT_INDIRECT
|
||||
|
||||
/* 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.
|
||||
extern const struct locale_data _nl_C_CATEGORY;
|
||||
This contains the built-in "C"/"POSIX" locale's data for CATEGORY.
|
||||
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"
|
||||
#undef DEFINE_CATEGORY
|
||||
/* For each category declare a special external symbol
|
||||
_nl_current_CATEGORY_used with a weak reference.
|
||||
This symbol will is defined in lc-CATEGORY.c and will be linked in
|
||||
if anything uses _nl_current_CATEGORY (also defined in that module).
|
||||
Also use a weak reference for the _nl_current_CATEGORY thread variable. */
|
||||
|
||||
/* Array indexed by category of pointers to _nl_current_CATEGORY slots.
|
||||
Elements are zero for categories whose data is never used. */
|
||||
struct locale_data * *const _nl_current[] =
|
||||
# define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
extern char _nl_current_##category##_used; \
|
||||
weak_extern (_nl_current_##category##_used) \
|
||||
weak_extern (_nl_current_##category)
|
||||
# include "categories.def"
|
||||
# undef DEFINE_CATEGORY
|
||||
|
||||
/* Now define a table of flags based on those special weak symbols' values.
|
||||
_nl_current_used[CATEGORY] will be zero if _nl_current_CATEGORY is not
|
||||
linked in. */
|
||||
static char *const _nl_current_used[] =
|
||||
{
|
||||
#define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
[category] = &_nl_current_##category,
|
||||
#include "categories.def"
|
||||
#undef DEFINE_CATEGORY
|
||||
/* We need this additional element to simplify the code. It must
|
||||
simply be != NULL. */
|
||||
[LC_ALL] = (struct locale_data **) ~0ul
|
||||
# define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
[category] = &_nl_current_##category##_used,
|
||||
# include "categories.def"
|
||||
# undef DEFINE_CATEGORY
|
||||
};
|
||||
|
||||
/* Array indexed by category of pointers to _nl_C_CATEGORY slots.
|
||||
Elements are zero for categories whose data is never used. */
|
||||
struct locale_data *const _nl_C[] attribute_hidden =
|
||||
{
|
||||
#define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
[category] = &_nl_C_##category,
|
||||
#include "categories.def"
|
||||
#undef DEFINE_CATEGORY
|
||||
};
|
||||
|
||||
# define CATEGORY_USED(category) (_nl_current[category] != NULL)
|
||||
# define CATEGORY_USED(category) (_nl_current_used[category] != 0)
|
||||
|
||||
#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
|
||||
@ -211,13 +195,7 @@ setdata (int category, struct locale_data *data)
|
||||
{
|
||||
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]) ();
|
||||
}
|
||||
@ -444,38 +422,57 @@ setlocale (int category, const char *locale)
|
||||
}
|
||||
libc_hidden_def (setlocale)
|
||||
|
||||
static void
|
||||
free_category (int category,
|
||||
struct locale_data *here, struct locale_data *c_data)
|
||||
{
|
||||
struct loaded_l10nfile *runp = _nl_locale_file_list[category];
|
||||
|
||||
/* If this category is already "C" don't do anything. */
|
||||
if (here != c_data)
|
||||
{
|
||||
/* We have to be prepared that sometime later we still
|
||||
might need the locale information. */
|
||||
setdata (category, c_data);
|
||||
setname (category, _nl_C_name);
|
||||
}
|
||||
|
||||
while (runp != NULL)
|
||||
{
|
||||
struct loaded_l10nfile *curr = runp;
|
||||
struct locale_data *data = (struct locale_data *) runp->data;
|
||||
|
||||
if (data != NULL && data != c_data)
|
||||
_nl_unload_locale (data);
|
||||
runp = runp->next;
|
||||
free ((char *) curr->filename);
|
||||
free (curr);
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__ ((unused))
|
||||
free_mem (void)
|
||||
{
|
||||
#ifdef NL_CURRENT_INDIRECT
|
||||
/* We don't use the loop because we want to have individual weak
|
||||
symbol references here. */
|
||||
# define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
if (CATEGORY_USED (category)) \
|
||||
{ \
|
||||
extern struct locale_data _nl_C_##category; \
|
||||
weak_extern (_nl_C_##category) \
|
||||
free_category (category, *_nl_current_##category, &_nl_C_##category); \
|
||||
}
|
||||
# include "categories.def"
|
||||
# undef DEFINE_CATEGORY
|
||||
#else
|
||||
int category;
|
||||
|
||||
for (category = 0; category < __LC_LAST; ++category)
|
||||
if (category != LC_ALL)
|
||||
{
|
||||
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. */
|
||||
if (here != _nl_C[category])
|
||||
{
|
||||
/* We have to be prepared that sometime later we still
|
||||
might need the locale information. */
|
||||
setdata (category, _nl_C[category]);
|
||||
setname (category, _nl_C_name);
|
||||
}
|
||||
|
||||
while (runp != NULL)
|
||||
{
|
||||
struct loaded_l10nfile *curr = runp;
|
||||
struct locale_data *data = (struct locale_data *) runp->data;
|
||||
|
||||
if (data != NULL && data != _nl_C[category])
|
||||
_nl_unload_locale (data);
|
||||
runp = runp->next;
|
||||
free ((char *) curr->filename);
|
||||
free (curr);
|
||||
}
|
||||
}
|
||||
free_category (category, _NL_CURRENT_DATA (category),
|
||||
_nl_C_locobj.__locales[category]);
|
||||
#endif
|
||||
|
||||
setname (LC_ALL, _nl_C_name);
|
||||
|
||||
|
@ -20,8 +20,6 @@
|
||||
#include <locale.h>
|
||||
#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
|
||||
@ -35,18 +33,38 @@ __uselocale (locale_t newloc)
|
||||
locale_t loc = __libc_tsd_get (LOCALE);
|
||||
return loc == &_nl_global_locale ? LC_GLOBAL_LOCALE : loc;
|
||||
}
|
||||
if (newloc == LC_GLOBAL_LOCALE)
|
||||
else
|
||||
{
|
||||
__libc_tsd_set (LOCALE, &_nl_global_locale);
|
||||
return LC_GLOBAL_LOCALE;
|
||||
const locale_t locobj
|
||||
= newloc == LC_GLOBAL_LOCALE ? &_nl_global_locale : newloc;
|
||||
__libc_tsd_set (LOCALE, locobj);
|
||||
|
||||
#ifdef NL_CURRENT_INDIRECT
|
||||
/* Now we must update all the per-category thread-local variables to
|
||||
point into the new current locale for this thread. The magic
|
||||
symbols _nl_current_LC_FOO_used are defined to meaningless values
|
||||
if _nl_current_LC_FOO was linked in. By using weak references to
|
||||
both symbols and testing the address of _nl_current_LC_FOO_used,
|
||||
we can avoid accessing the _nl_current_LC_FOO thread-local
|
||||
variable at all when no code referring to it was linked in. We
|
||||
need the special bogus symbol because while TLS symbols can be
|
||||
weak, there is no reasonable way to test for the default-zero
|
||||
value as with a heap symbol (taking the address would just use
|
||||
some bogus offset from our thread pointer). */
|
||||
|
||||
# define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
{ \
|
||||
extern char _nl_current_##category##_used; \
|
||||
weak_extern (_nl_current_##category##_used) \
|
||||
weak_extern (_nl_current_##category) \
|
||||
if (&_nl_current_##category##_used != 0) \
|
||||
_nl_current_##category = &locobj->__locales[category]; \
|
||||
}
|
||||
# include "categories.def"
|
||||
# undef DEFINE_CATEGORY
|
||||
#endif
|
||||
}
|
||||
__libc_tsd_set (LOCALE, newloc);
|
||||
|
||||
return newloc;
|
||||
}
|
||||
weak_alias (__uselocale, uselocale)
|
||||
|
||||
#else
|
||||
|
||||
# warning uselocale not implemented for static linking yet
|
||||
|
||||
#endif
|
||||
|
@ -32,41 +32,16 @@ extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden;
|
||||
extern const char _nl_C_LC_CTYPE_tolower[] attribute_hidden;
|
||||
|
||||
|
||||
#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)
|
||||
/* This is a bad kludge presuming the variable name used by the macros.
|
||||
Using typeof makes sure to barf if we do not match the macro definition. */
|
||||
__typeof (__libc_tsd_LOCALE_data) __libc_tsd_LOCALE_data = &_nl_global_locale;
|
||||
# endif
|
||||
|
||||
#endif
|
||||
struct __locale_struct _nl_C_locobj attribute_hidden =
|
||||
{
|
||||
.__locales =
|
||||
{
|
||||
#define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
[category] = &_nl_C_##category,
|
||||
#include "categories.def"
|
||||
#undef DEFINE_CATEGORY
|
||||
},
|
||||
.__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
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user