aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-09-02 19:34:39 +0000
committerRoland McGrath <roland@gnu.org>2002-09-02 19:34:39 +0000
commit963102971df9fbcd967a46748efc854d269cee1f (patch)
tree352ea540316cec578b89ff90b8d9915536906870
parent1977e59058a8a5260770cade67676bd93f896fdf (diff)
downloadglibc-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.
-rw-r--r--ChangeLog38
-rw-r--r--locale/localeinfo.h1
-rw-r--r--stdlib/mblen.c10
-rw-r--r--stdlib/mbtowc.c8
-rw-r--r--stdlib/wctomb.c8
-rw-r--r--wcsmbs/btowc.c11
-rw-r--r--wcsmbs/mbrtowc.c9
-rw-r--r--wcsmbs/mbsnrtowcs.c9
-rw-r--r--wcsmbs/mbsrtowcs.c17
-rw-r--r--wcsmbs/mbsrtowcs_l.c30
-rw-r--r--wcsmbs/wcrtomb.c15
-rw-r--r--wcsmbs/wcsmbsload.c167
-rw-r--r--wcsmbs/wcsmbsload.h31
-rw-r--r--wcsmbs/wcsnrtombs.c9
-rw-r--r--wcsmbs/wcsrtombs.c9
-rw-r--r--wcsmbs/wctob.c11
16 files changed, 182 insertions, 201 deletions
diff --git a/ChangeLog b/ChangeLog
index 2ce0e28..9f8eded 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 3ec58f3..28256e9 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 782bf51..3cd9cf6 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 51fd9ab..744b2b6 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 e681732..49872f5 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 eaa9d00..ca75e28 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 c25ba51..de79e10 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 7014aa5..9ac06fe 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 097e462..602dd5e 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 47ba82f..0890803 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 5dba73a..3814479 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 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);
diff --git a/wcsmbs/wcsmbsload.h b/wcsmbs/wcsmbsload.h
index b7594ce..0cf5da4 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 1d40394..bb2ca1d 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 e0382b4..dda115d 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 cd44bc6..d053b9a 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));