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 | |
parent | * sysdeps/mach/hurd/Versions (ld: GLIBC_2.0): Add __fxstat64. (diff) | |
download | glibc-963102971df9fbcd967a46748efc854d269cee1f.tar.gz glibc-963102971df9fbcd967a46748efc854d269cee1f.tar.bz2 glibc-963102971df9fbcd967a46748efc854d269cee1f.zip |
* 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.
-rw-r--r-- | ChangeLog | 38 | ||||
-rw-r--r-- | locale/localeinfo.h | 1 | ||||
-rw-r--r-- | stdlib/mblen.c | 10 | ||||
-rw-r--r-- | stdlib/mbtowc.c | 8 | ||||
-rw-r--r-- | stdlib/wctomb.c | 8 | ||||
-rw-r--r-- | wcsmbs/btowc.c | 11 | ||||
-rw-r--r-- | wcsmbs/mbrtowc.c | 9 | ||||
-rw-r--r-- | wcsmbs/mbsnrtowcs.c | 9 | ||||
-rw-r--r-- | wcsmbs/mbsrtowcs.c | 17 | ||||
-rw-r--r-- | wcsmbs/mbsrtowcs_l.c | 30 | ||||
-rw-r--r-- | wcsmbs/wcrtomb.c | 15 | ||||
-rw-r--r-- | wcsmbs/wcsmbsload.c | 167 | ||||
-rw-r--r-- | wcsmbs/wcsmbsload.h | 31 | ||||
-rw-r--r-- | wcsmbs/wcsnrtombs.c | 9 | ||||
-rw-r--r-- | wcsmbs/wcsrtombs.c | 9 | ||||
-rw-r--r-- | wcsmbs/wctob.c | 11 |
16 files changed, 182 insertions, 201 deletions
@@ -1,3 +1,41 @@ +2002-09-02 Jakub Jelinek <jakub@redhat.com> + + * 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. + 2002-09-02 Roland McGrath <roland@frob.com> * sysdeps/mach/hurd/Versions (ld: GLIBC_2.0): Add __fxstat64. diff --git a/locale/localeinfo.h b/locale/localeinfo.h index 3ec58f3b21..28256e9a2b 100644 --- a/locale/localeinfo.h +++ b/locale/localeinfo.h @@ -64,6 +64,7 @@ struct locale_data { void *data; struct lc_time_data *time; + const struct gconv_fcts *ctype; }; } private; diff --git a/stdlib/mblen.c b/stdlib/mblen.c index 782bf51081..3cd9cf6909 100644 --- a/stdlib/mblen.c +++ b/stdlib/mblen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1991,1997,1998,1999,2000,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 @@ -40,13 +40,15 @@ mblen (const char *s, size_t n) not. */ if (s == NULL) { - /* Make sure we use the correct value. */ - update_conversion_ptrs (); + const struct gconv_fcts *fcts; + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); /* Reset the state. */ memset (&state, '\0', sizeof state); - result = __wcsmbs_gconv_fcts.towc->__stateful; + result = fcts->towc->__stateful; } else if (*s == '\0') /* According to the ISO C 89 standard this is the expected behaviour. */ diff --git a/stdlib/mbtowc.c b/stdlib/mbtowc.c index 51fd9ab8f2..744b2b6c0b 100644 --- a/stdlib/mbtowc.c +++ b/stdlib/mbtowc.c @@ -44,14 +44,16 @@ mbtowc (wchar_t *pwc, const char *s, size_t n) not. */ if (s == NULL) { - /* Make sure we use the correct value. */ - update_conversion_ptrs (); + const struct gconv_fcts *fcts; + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); /* This is an extension in the Unix standard which does not directly violate ISO C. */ memset (&__no_r_state, '\0', sizeof __no_r_state); - result = __wcsmbs_gconv_fcts.towc->__stateful; + result = fcts->towc->__stateful; } else if (*s == '\0') { diff --git a/stdlib/wctomb.c b/stdlib/wctomb.c index e6817320ae..49872f5c6b 100644 --- a/stdlib/wctomb.c +++ b/stdlib/wctomb.c @@ -40,14 +40,16 @@ wctomb (char *s, wchar_t wchar) not. */ if (s == NULL) { - /* Make sure we use the correct value. */ - update_conversion_ptrs (); + const struct gconv_fcts *fcts; + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); /* This is an extension in the Unix standard which does not directly violate ISO C. */ memset (&__no_r_state, '\0', sizeof __no_r_state); - return __wcsmbs_gconv_fcts.tomb->__stateful; + return fcts->tomb->__stateful; } return __wcrtomb (s, wchar, &__no_r_state); diff --git a/wcsmbs/btowc.c b/wcsmbs/btowc.c index eaa9d003e7..ca75e281e6 100644 --- a/wcsmbs/btowc.c +++ b/wcsmbs/btowc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@gnu.org>, 1996. @@ -36,6 +36,7 @@ __btowc (c) const unsigned char *inptr = inbuf; size_t dummy; int status; + const struct gconv_fcts *fcts; /* If the parameter does not fit into one byte or it is the EOF value we can give the answer now. */ @@ -54,14 +55,14 @@ __btowc (c) /* Make sure we start in the initial state. */ memset (&data.__state, '\0', sizeof (mbstate_t)); - /* Make sure we use the correct function. */ - update_conversion_ptrs (); + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); /* Create the input string. */ inbuf[0] = c; - status = DL_CALL_FCT (__wcsmbs_gconv_fcts.towc->__fct, - (__wcsmbs_gconv_fcts.towc, &data, &inptr, inptr + 1, + status = DL_CALL_FCT (fcts->towc->__fct, + (fcts->towc, &data, &inptr, inptr + 1, NULL, &dummy, 0, 1)); /* The conversion failed. */ if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT diff --git a/wcsmbs/mbrtowc.c b/wcsmbs/mbrtowc.c index c25ba51d4b..de79e10e5d 100644 --- a/wcsmbs/mbrtowc.c +++ b/wcsmbs/mbrtowc.c @@ -42,6 +42,7 @@ __mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) size_t dummy; const unsigned char *inbuf; char *outbuf = (char *) (pwc ?: buf); + const struct gconv_fcts *fcts; /* Set information for this step. */ data.__invocation_counter = 0; @@ -63,13 +64,13 @@ __mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) data.__outbuf = outbuf; data.__outbufend = outbuf + sizeof (wchar_t); - /* Make sure we use the correct function. */ - update_conversion_ptrs (); + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); /* Do a normal conversion. */ inbuf = (const unsigned char *) s; - status = DL_CALL_FCT (__wcsmbs_gconv_fcts.towc->__fct, - (__wcsmbs_gconv_fcts.towc, &data, &inbuf, inbuf + n, + status = DL_CALL_FCT (fcts->towc->__fct, + (fcts->towc, &data, &inbuf, inbuf + n, NULL, &dummy, 0, 1)); /* There must not be any problems with the conversion but illegal input diff --git a/wcsmbs/mbsnrtowcs.c b/wcsmbs/mbsnrtowcs.c index 7014aa52a2..9ac06fe6c2 100644 --- a/wcsmbs/mbsnrtowcs.c +++ b/wcsmbs/mbsnrtowcs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@gnu.org>, 1996. @@ -51,6 +51,7 @@ __mbsnrtowcs (dst, src, nmc, len, ps) int status; struct __gconv_step *towc; size_t dummy; + const struct gconv_fcts *fcts; /* Tell where we want the result. */ data.__invocation_counter = 0; @@ -63,11 +64,11 @@ __mbsnrtowcs (dst, src, nmc, len, ps) return 0; srcend = *src + __strnlen (*src, nmc - 1) + 1; - /* Make sure we use the correct function. */ - update_conversion_ptrs (); + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); /* Get the structure with the function pointers. */ - towc = __wcsmbs_gconv_fcts.towc; + towc = fcts->towc; /* We have to handle DST == NULL special. */ if (dst == NULL) diff --git a/wcsmbs/mbsrtowcs.c b/wcsmbs/mbsrtowcs.c index 097e462110..602dd5e64c 100644 --- a/wcsmbs/mbsrtowcs.c +++ b/wcsmbs/mbsrtowcs.c @@ -58,6 +58,7 @@ __mbsrtowcs (dst, src, len, ps) int status; struct __gconv_step *towc; size_t non_reversible; + const struct gconv_fcts *fcts; /* Tell where we want the result. */ data.__invocation_counter = 0; @@ -70,16 +71,15 @@ __mbsrtowcs (dst, src, len, ps) #endif data.__trans = NULL; + /* Get the conversion functions. */ #ifdef USE_IN_EXTENDED_LOCALE_MODEL - /* Get the conversion function matching the locale. */ - towc = wcsmbs_get_towc_func (l); + fcts = get_gconv_fcts (l->__locales[LC_CTYPE]); #else - /* Make sure we use the correct function. */ - update_conversion_ptrs (); + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); +#endif /* Get the structure with the function pointers. */ - towc = __wcsmbs_gconv_fcts.towc; -#endif + towc = fcts->towc; /* We have to handle DST == NULL special. */ if (dst == NULL) @@ -160,11 +160,6 @@ __mbsrtowcs (dst, src, len, ps) __set_errno (EILSEQ); } -#ifdef USE_IN_EXTENDED_LOCALE_MODEL - /* Free the conversion function data structures. */ - wcsmbs_free_funcs (towc); -#endif - return result; } #ifndef USE_IN_EXTENDED_LOCALE_MODEL diff --git a/wcsmbs/mbsrtowcs_l.c b/wcsmbs/mbsrtowcs_l.c index 47ba82fecf..0890803b59 100644 --- a/wcsmbs/mbsrtowcs_l.c +++ b/wcsmbs/mbsrtowcs_l.c @@ -21,35 +21,5 @@ #include <string.h> #include "wcsmbsload.h" - -static inline struct __gconv_step * -wcsmbs_get_towc_func (__locale_t l) -{ - const char *charset; - int use_translit; - char *norm; - size_t nsteps; - - charset = l->__locales[LC_CTYPE]->values[_NL_ITEM_INDEX(CODESET)].string; - - /* Transliteration requested? */ - use_translit = l->__locales[LC_CTYPE]->use_translit; - - /* Normalize the name. */ - norm = norm_add_slashes (charset, use_translit ? "TRANSLIT" : NULL); - - return __wcsmbs_getfct ("INTERNAL", charset, &nsteps) ?: &__wcsmbs_to_wc; -} - - -static inline void -wcsmbs_free_funcs (struct __gconv_step *step) -{ - if (step != &__wcsmbs_to_wc) - /* There is only one step. */ - __gconv_close_transform (step, 1); -} - - #define USE_IN_EXTENDED_LOCALE_MODEL 1 #include "mbsrtowcs.c" diff --git a/wcsmbs/wcrtomb.c b/wcsmbs/wcrtomb.c index 5dba73acc3..38144796f8 100644 --- a/wcsmbs/wcrtomb.c +++ b/wcsmbs/wcrtomb.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1996,1997,1998,2000,2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -42,6 +42,7 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps) int status; size_t result; size_t dummy; + const struct gconv_fcts *fcts; /* Set information for this step. */ data.__invocation_counter = 0; @@ -62,16 +63,16 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps) data.__outbuf = s; data.__outbufend = s + MB_CUR_MAX; - /* Make sure we use the correct function. */ - update_conversion_ptrs (); + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); /* If WC is the NUL character we write into the output buffer the byte sequence necessary for PS to get into the initial state, followed by a NUL byte. */ if (wc == L'\0') { - status = DL_CALL_FCT (__wcsmbs_gconv_fcts.tomb->__fct, - (__wcsmbs_gconv_fcts.tomb, &data, NULL, NULL, + status = DL_CALL_FCT (fcts->tomb->__fct, + (fcts->tomb, &data, NULL, NULL, NULL, &dummy, 1, 1)); if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT) @@ -82,8 +83,8 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps) /* Do a normal conversion. */ const unsigned char *inbuf = (const unsigned char *) &wc; - status = DL_CALL_FCT (__wcsmbs_gconv_fcts.tomb->__fct, - (__wcsmbs_gconv_fcts.tomb, &data, &inbuf, + status = DL_CALL_FCT (fcts->tomb->__fct, + (fcts->tomb, &data, &inbuf, inbuf + sizeof (wchar_t), NULL, &dummy, 0, 1)); } diff --git a/wcsmbs/wcsmbsload.c b/wcsmbs/wcsmbsload.c index fc846c7237..539b02ae59 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); diff --git a/wcsmbs/wcsmbsload.h b/wcsmbs/wcsmbsload.h index b7594ce5e9..0cf5da4f88 100644 --- a/wcsmbs/wcsmbsload.h +++ b/wcsmbs/wcsmbsload.h @@ -35,15 +35,10 @@ struct gconv_fcts }; /* Set of currently active conversion functions. */ -extern struct gconv_fcts __wcsmbs_gconv_fcts attribute_hidden; - - -/* Last loaded locale for LC_CTYPE. */ -extern const struct locale_data *__wcsmbs_last_locale attribute_hidden; - +extern const struct gconv_fcts __wcsmbs_gconv_fcts_c attribute_hidden; /* Load conversion functions for the currently selected locale. */ -extern void __wcsmbs_load_conv (const struct locale_data *new_category) +extern void __wcsmbs_load_conv (struct locale_data *new_category) internal_function; /* Clone the current `__wcsmbs_load_conv' value. */ @@ -54,12 +49,12 @@ extern void __wcsmbs_clone_conv (struct gconv_fcts *copy) extern int __wcsmbs_named_conv (struct gconv_fcts *copy, const char *name) internal_function; - -#include <iconv/gconv_int.h> +/* Function used for the `private.cleanup' hook. */ +extern void _nl_cleanup_ctype (struct locale_data *) + internal_function attribute_hidden; -/* Variable for conversion from ASCII to wchar_t. */ -extern struct __gconv_step __wcsmbs_to_wc attribute_hidden; +#include <iconv/gconv_int.h> /* Load the function implementation if necessary. */ @@ -67,14 +62,20 @@ extern struct __gconv_step *__wcsmbs_getfct (const char *to, const char *from, size_t *nstepsp) attribute_hidden; +extern const struct locale_data _nl_C_LC_CTYPE attribute_hidden; /* Check whether the LC_CTYPE locale changed since the last call. Update the pointers appropriately. */ -static inline void -update_conversion_ptrs (void) +static inline const struct gconv_fcts * +get_gconv_fcts (struct locale_data *data) { - if (__wcsmbs_last_locale != _NL_CURRENT_DATA (LC_CTYPE)) - __wcsmbs_load_conv (_NL_CURRENT_DATA (LC_CTYPE)); + if (__builtin_expect (data->private.ctype == NULL, 0)) + { + if (__builtin_expect (data == &_nl_C_LC_CTYPE, 0)) + return &__wcsmbs_gconv_fcts_c; + __wcsmbs_load_conv (data); + } + return data->private.ctype; } #endif /* wcsmbsload.h */ diff --git a/wcsmbs/wcsnrtombs.c b/wcsmbs/wcsnrtombs.c index 1d403940bc..bb2ca1d08b 100644 --- a/wcsmbs/wcsnrtombs.c +++ b/wcsmbs/wcsnrtombs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@gnu.org>, 1996. @@ -49,6 +49,7 @@ __wcsnrtombs (dst, src, nwc, len, ps) int status; size_t result; struct __gconv_step *tomb; + const struct gconv_fcts *fcts; /* Tell where we want the result. */ data.__invocation_counter = 0; @@ -61,11 +62,11 @@ __wcsnrtombs (dst, src, nwc, len, ps) return 0; srcend = *src + __wcsnlen (*src, nwc - 1) + 1; - /* Make sure we use the correct function. */ - update_conversion_ptrs (); + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); /* Get the structure with the function pointers. */ - tomb = __wcsmbs_gconv_fcts.tomb; + tomb = fcts->tomb; /* We have to handle DST == NULL special. */ if (dst == NULL) diff --git a/wcsmbs/wcsrtombs.c b/wcsmbs/wcsrtombs.c index e0382b4bb9..dda115dfd3 100644 --- a/wcsmbs/wcsrtombs.c +++ b/wcsmbs/wcsrtombs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@gnu.org>, 1996. @@ -45,6 +45,7 @@ __wcsrtombs (dst, src, len, ps) int status; size_t result; struct __gconv_step *tomb; + const struct gconv_fcts *fcts; /* Tell where we want the result. */ data.__invocation_counter = 0; @@ -53,11 +54,11 @@ __wcsrtombs (dst, src, len, ps) data.__statep = ps ?: &state; data.__trans = NULL; - /* Make sure we use the correct function. */ - update_conversion_ptrs (); + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); /* Get the structure with the function pointers. */ - tomb = __wcsmbs_gconv_fcts.tomb; + tomb = fcts->tomb; /* We have to handle DST == NULL special. */ if (dst == NULL) diff --git a/wcsmbs/wctob.c b/wcsmbs/wctob.c index cd44bc6b32..d053b9a28f 100644 --- a/wcsmbs/wctob.c +++ b/wcsmbs/wctob.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996. @@ -35,6 +35,7 @@ wctob (c) wchar_t *inptr = inbuf; size_t dummy; int status; + const struct gconv_fcts *fcts; if (c == WEOF) return EOF; @@ -51,14 +52,14 @@ wctob (c) /* Make sure we start in the initial state. */ memset (&data.__state, '\0', sizeof (mbstate_t)); - /* Make sure we use the correct function. */ - update_conversion_ptrs (); + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); /* Create the input string. */ inbuf[0] = c; - status = DL_CALL_FCT (__wcsmbs_gconv_fcts.tomb->__fct, - (__wcsmbs_gconv_fcts.tomb, &data, + status = DL_CALL_FCT (fcts->tomb->__fct, + (fcts->tomb, &data, (const unsigned char **) &inptr, (const unsigned char *) &inbuf[1], NULL, &dummy, 0, 1)); |