diff options
author | Roland McGrath <roland@gnu.org> | 2002-09-02 19:34:39 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2002-09-02 19:34:39 +0000 |
commit | 963102971df9fbcd967a46748efc854d269cee1f (patch) | |
tree | 352ea540316cec578b89ff90b8d9915536906870 /wcsmbs/wcsmbsload.c | |
parent | 1977e59058a8a5260770cade67676bd93f896fdf (diff) | |
download | glibc-963102971df9fbcd967a46748efc854d269cee1f.zip glibc-963102971df9fbcd967a46748efc854d269cee1f.tar.gz glibc-963102971df9fbcd967a46748efc854d269cee1f.tar.bz2 |
* locale/localeinfo.h (struct locale_data): Add private.ctype.
* wcsmbs/wcsmbsload.h (__wcsmbs_gconv_fcts, __wcsmbs_last_locale,
__wcsmbs_to_wc, update_conversion_ptrs): Removed.
(__wcsmbs_gconv_fcts_c, _nl_C_LC_CTYPE): New externs.
(__wcsmbs_load_conv): Remove const from argument.
(_nl_cleanup_ctype): New proto.
(get_gconv_fcts): New function.
* wcsmbs/wcsmbsload.c (__wcsmbs_last_locale): Removed.
(__wcsmbs_to_wc): Rename back to...
(to_wc): ... this.
(__wcsmbs_gconv_fcts): Rename to...
(__wcsmbs_gconv_fcts_c): ... this. Make const. Use to_wc.
(lock): Removed.
(__libc_setlocale_lock): New extern.
(__wcsmbs_load_conv): Remove const from argument.
Initialize new_category->private.ctype instead of a global
variable.
(__wcsmbs_clone_conv): Use get_gconv_fcts instead of
update_function_ptrs. No locking is necessary.
(_nl_cleanup_ctype): New function.
* wcsmbs/btowc.c (__btowc): Use get_gconv_fcts instead of
update_function_ptrs and a global __wcsmbs_gconv_fcts variable.
* wcsmbs/mbrtowc.c (__mbrtowc): Likewise.
* wcsmbs/mbsnrtowcs.c (__mbsnrtowcs): Likewise.
* wcsmbs/wcrtomb.c (__wcrtomb): Likewise.
* wcsmbs/wcsnrtombs.c (__wcsnrtombs): Likewise.
* wcsmbs/wcsrtombs.c (__wcsrtombs): Likewise.
* wcsmbs/wctob.c (wctob): Likewise.
* stdlib/mblen.c (mblen): Likewise.
* stdlib/mbtowc.c (mbtowc): Likewise.
* stdlib/wctomb.c (wctomb): Likewise.
* wcsmbs/mbsrtowcs.c (__mbsrtowcs): Likewise.
Remove calls to wcsmbs_get_towc_func and wcsmbs_free_funcs.
* wcsmbs/mbsrtowcs_l.c (wcsmbs_get_towc_func, wcsmbs_free_funcs):
Removed.
Diffstat (limited to 'wcsmbs/wcsmbsload.c')
-rw-r--r-- | wcsmbs/wcsmbsload.c | 167 |
1 files changed, 65 insertions, 102 deletions
diff --git a/wcsmbs/wcsmbsload.c b/wcsmbs/wcsmbsload.c index fc846c7..539b02a 100644 --- a/wcsmbs/wcsmbsload.c +++ b/wcsmbs/wcsmbsload.c @@ -28,14 +28,8 @@ #include <bits/libc-lock.h> -/* Last loaded locale for LC_CTYPE. We initialize for the C locale - which is enabled at startup. */ -extern const struct locale_data _nl_C_LC_CTYPE; -const struct locale_data *__wcsmbs_last_locale = &_nl_C_LC_CTYPE; - - /* These are the descriptions for the default conversion functions. */ -struct __gconv_step __wcsmbs_to_wc attribute_hidden = +static struct __gconv_step to_wc = { .__shlib_handle = NULL, .__modname = NULL, @@ -73,9 +67,9 @@ static struct __gconv_step to_mb = /* For the default locale we only have to handle ANSI_X3.4-1968. */ -struct gconv_fcts __wcsmbs_gconv_fcts = +const struct gconv_fcts __wcsmbs_gconv_fcts_c = { - .towc = &__wcsmbs_to_wc, + .towc = &to_wc, .towc_nsteps = 1, .tomb = &to_mb, .tomb_nsteps = 1 @@ -148,90 +142,73 @@ __wcsmbs_getfct (const char *to, const char *from, size_t *nstepsp) }) -/* We must modify global data. */ -__libc_lock_define_initialized (static, lock) - +/* Some of the functions here must not be used while setlocale is called. */ +__libc_lock_define (extern, __libc_setlocale_lock attribute_hidden) /* Load conversion functions for the currently selected locale. */ void internal_function -__wcsmbs_load_conv (const struct locale_data *new_category) +__wcsmbs_load_conv (struct locale_data *new_category) { /* Acquire the lock. */ - __libc_lock_lock (lock); + __libc_lock_lock (__libc_setlocale_lock); /* We should repeat the test since while we waited some other thread might have run this function. */ - if (__builtin_expect (__wcsmbs_last_locale != new_category, 1)) + if (__builtin_expect (new_category->private.ctype == NULL, 1)) { - if (new_category->name == _nl_C_name) /* Yes, pointer comparison. */ + /* We must find the real functions. */ + const char *charset_name; + const char *complete_name; + struct gconv_fcts *new_fcts; + int use_translit; + + /* Allocate the gconv_fcts structure. */ + new_fcts = malloc (sizeof *new_fcts); + if (new_fcts == NULL) { failed: - __wcsmbs_gconv_fcts.towc = &__wcsmbs_to_wc; - __wcsmbs_gconv_fcts.tomb = &to_mb; + new_category->private.ctype = &__wcsmbs_gconv_fcts_c; } - else + + /* Get name of charset of the locale. */ + charset_name = new_category->values[_NL_ITEM_INDEX(CODESET)].string; + + /* Does the user want transliteration? */ + use_translit = new_category->use_translit; + + /* Normalize the name and add the slashes necessary for a + complete lookup. */ + complete_name = norm_add_slashes (charset_name, + use_translit ? "TRANSLIT" : NULL); + + /* It is not necessary to use transliteration in this direction + since the internal character set is supposed to be able to + represent all others. */ + new_fcts->towc = __wcsmbs_getfct ("INTERNAL", complete_name, + &new_fcts->towc_nsteps); + new_fcts->tomb = (new_fcts->towc != NULL + ? __wcsmbs_getfct (complete_name, "INTERNAL", + &new_fcts->tomb_nsteps) + : NULL); + + /* If any of the conversion functions is not available we don't + use any since this would mean we cannot convert back and + forth.*/ + if (new_fcts->tomb == NULL) { - /* We must find the real functions. */ - const char *charset_name; - const char *complete_name; - struct __gconv_step *new_towc; - size_t new_towc_nsteps; - struct __gconv_step *new_tomb; - size_t new_tomb_nsteps; - int use_translit; - - /* Free the old conversions. */ - if (__wcsmbs_gconv_fcts.tomb != &to_mb) - __gconv_close_transform (__wcsmbs_gconv_fcts.tomb, - __wcsmbs_gconv_fcts.tomb_nsteps); - if (__wcsmbs_gconv_fcts.towc != &__wcsmbs_to_wc) - __gconv_close_transform (__wcsmbs_gconv_fcts.towc, - __wcsmbs_gconv_fcts.towc_nsteps); - - /* Get name of charset of the locale. */ - charset_name = new_category->values[_NL_ITEM_INDEX(CODESET)].string; - - /* Does the user want transliteration? */ - use_translit = new_category->use_translit; - - /* Normalize the name and add the slashes necessary for a - complete lookup. */ - complete_name = norm_add_slashes (charset_name, - use_translit ? "TRANSLIT" : NULL); - - /* It is not necessary to use transliteration in this direction - since the internal character set is supposed to be able to - represent all others. */ - new_towc = __wcsmbs_getfct ("INTERNAL", complete_name, - &new_towc_nsteps); - new_tomb = (new_towc != NULL - ? __wcsmbs_getfct (complete_name, "INTERNAL", - &new_tomb_nsteps) - : NULL); - - /* If any of the conversion functions is not available we don't - use any since this would mean we cannot convert back and - forth.*/ - if (new_towc == NULL || new_tomb == NULL) - { - if (new_towc != NULL) - __gconv_close_transform (new_towc, 1); - - goto failed; - } - - __wcsmbs_gconv_fcts.tomb = new_tomb; - __wcsmbs_gconv_fcts.tomb_nsteps = new_tomb_nsteps; - __wcsmbs_gconv_fcts.towc = new_towc; - __wcsmbs_gconv_fcts.towc_nsteps = new_towc_nsteps; + if (new_fcts->towc != NULL) + __gconv_close_transform (new_fcts->towc, new_fcts->towc_nsteps); + + free (new_fcts); + goto failed; } - /* Set last-used variable for current locale. */ - __wcsmbs_last_locale = new_category; + new_category->private.ctype = new_fcts; + new_category->private.cleanup = &_nl_cleanup_ctype; } - __libc_lock_unlock (lock); + __libc_lock_unlock (__libc_setlocale_lock); } @@ -240,22 +217,18 @@ void internal_function __wcsmbs_clone_conv (struct gconv_fcts *copy) { - /* First make sure the function table is up-to-date. */ - update_conversion_ptrs (); + const struct gconv_fcts *orig; - /* Make sure the data structures remain the same until we are finished. */ - __libc_lock_lock (lock); + orig = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); /* Copy the data. */ - *copy = __wcsmbs_gconv_fcts; + *copy = *orig; /* Now increment the usage counters. */ if (copy->towc->__shlib_handle != NULL) ++copy->towc->__counter; if (copy->tomb->__shlib_handle != NULL) ++copy->tomb->__counter; - - __libc_lock_unlock (lock); } @@ -275,28 +248,18 @@ __wcsmbs_named_conv (struct gconv_fcts *copy, const char *name) return copy->towc == NULL || copy->tomb == NULL ? 1 : 0; } - -/* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) +void internal_function +_nl_cleanup_ctype (struct locale_data *locale) { - if (__wcsmbs_gconv_fcts.tomb != &to_mb) + const struct gconv_fcts *const data = locale->private.ctype; + if (data != NULL) { - struct __gconv_step *old = __wcsmbs_gconv_fcts.tomb; - size_t nold = __wcsmbs_gconv_fcts.tomb_nsteps; - __wcsmbs_gconv_fcts.tomb = &to_mb; - __wcsmbs_gconv_fcts.tomb_nsteps = 1; - __gconv_release_cache (old, nold); - } + locale->private.ctype = NULL; + locale->private.cleanup = NULL; - if (__wcsmbs_gconv_fcts.towc != &__wcsmbs_to_wc) - { - struct __gconv_step *old = __wcsmbs_gconv_fcts.towc; - size_t nold = __wcsmbs_gconv_fcts.towc_nsteps; - __wcsmbs_gconv_fcts.towc = &__wcsmbs_to_wc; - __wcsmbs_gconv_fcts.towc_nsteps = 1; - __gconv_release_cache (old, nold); + /* Free the old conversions. */ + __gconv_close_transform (data->tomb, data->tomb_nsteps); + __gconv_close_transform (data->towc, data->towc_nsteps); + free ((char *) data); } } - -text_set_element (__libc_subfreeres, free_mem); |