* locale/localeinfo.h (struct locale_data): Add private.ctype.
authorRoland McGrath <roland@gnu.org>
Mon, 2 Sep 2002 19:34:39 +0000 (19:34 +0000)
committerRoland McGrath <roland@gnu.org>
Mon, 2 Sep 2002 19:34:39 +0000 (19:34 +0000)
* 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.

16 files changed:
ChangeLog
locale/localeinfo.h
stdlib/mblen.c
stdlib/mbtowc.c
stdlib/wctomb.c
wcsmbs/btowc.c
wcsmbs/mbrtowc.c
wcsmbs/mbsnrtowcs.c
wcsmbs/mbsrtowcs.c
wcsmbs/mbsrtowcs_l.c
wcsmbs/wcrtomb.c
wcsmbs/wcsmbsload.c
wcsmbs/wcsmbsload.h
wcsmbs/wcsnrtombs.c
wcsmbs/wcsrtombs.c
wcsmbs/wctob.c

index 2ce0e28..9f8eded 100644 (file)
--- 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.
index 3ec58f3..28256e9 100644 (file)
@@ -64,6 +64,7 @@ struct locale_data
     {
       void *data;
       struct lc_time_data *time;
+      const struct gconv_fcts *ctype;
     };
   } private;
 
index 782bf51..3cd9cf6 100644 (file)
@@ -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.  */
index 51fd9ab..744b2b6 100644 (file)
@@ -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')
     {
index e681732..49872f5 100644 (file)
@@ -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);
index eaa9d00..ca75e28 100644 (file)
@@ -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
index c25ba51..de79e10 100644 (file)
@@ -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
index 7014aa5..9ac06fe 100644 (file)
@@ -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)
index 097e462..602dd5e 100644 (file)
@@ -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
index 47ba82f..0890803 100644 (file)
 #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"
index 5dba73a..3814479 100644 (file)
@@ -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));
     }
 
index fc846c7..539b02a 100644 (file)
 #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);
index b7594ce..0cf5da4 100644 (file)
@@ -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 */
index 1d40394..bb2ca1d 100644 (file)
@@ -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)
index e0382b4..dda115d 100644 (file)
@@ -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)
index cd44bc6..d053b9a 100644 (file)
@@ -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));