2002-09-01 Roland McGrath <roland@redhat.com>
authorroland <roland>
Mon, 2 Sep 2002 07:08:53 +0000 (07:08 +0000)
committerroland <roland>
Mon, 2 Sep 2002 07:08:53 +0000 (07:08 +0000)
* ctype/ctype.h (__ctype_b, __ctype_toupper, __ctype_tolower):
Variable declarations removed.
(__ctype_b_loc, __ctype_toupper_loc, __ctype_tolower_loc): Declare
these functions to replace them.
(__isctype, tolower, toupper, _tolower, _toupper): Use those accessor
functions plus an indirection rather than the old global variables.
* include/ctype.h (__isctype, tolower, _tolower, toupper, _toupper):
Macros removed.
(__ctype_b_loc, __ctype_toupper_loc, __ctype_tolower_loc): New extern
inline functions.
* ctype/ctype-info.c: Revert last reversion back the other way.
Define tsd vars CTYPE_B, CTYPE_TOLOWER, CTYPE_TOUPPER.
Define real function versions of include/ctype.h inlines here.
* ctype/Versions (libc: GLIBC_2.3): Add __ctype_b_loc,
__ctype_tolower_loc, __ctype_toupper_loc.
* locale/lc-ctype.c: Revert last reversion back the other way.
(_nl_postload_ctype): If current thread uses the global locale,
update its tsd vars.
* locale/uselocale.c (__uselocale): Update tsd vars from new locale.
* hurd/hurd/threadvar.h (enum __hurd_threadvar_index): Add CTYPE_B,
CTYPE_TOLOWER, CTYPE_TOUPPER.

ctype/Versions
ctype/ctype-info.c
ctype/ctype.h
hurd/hurd/threadvar.h
include/ctype.h
locale/lc-ctype.c
locale/uselocale.c

index f77b5be..8cf0338 100644 (file)
@@ -17,5 +17,8 @@ libc {
   }
   GLIBC_2.3 {
     isctype; __isctype;
+
+    # functions used by optimized macros in ctype.h
+    __ctype_b_loc; __ctype_tolower_loc; __ctype_toupper_loc;
   }
 }
index d29edb7..30c6d55 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,92,95,96,97,99,2000,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991,92,95,96,97,99,2000,02 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
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#define CTYPE_EXTERN_INLINE /* Define real functions for accessors.  */
 #include <ctype.h>
 #include <locale/localeinfo.h>
 
+__libc_tsd_define (, CTYPE_B)
+__libc_tsd_define (, CTYPE_TOLOWER)
+__libc_tsd_define (, CTYPE_TOUPPER)
+
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
+
 /* Defined in locale/C-ctype.c.  */
 extern const char _nl_C_LC_CTYPE_class[] attribute_hidden;
 extern const char _nl_C_LC_CTYPE_class32[] attribute_hidden;
@@ -36,36 +45,21 @@ extern const char _nl_C_LC_CTYPE_class_blank[] attribute_hidden;
 extern const char _nl_C_LC_CTYPE_class_cntrl[] attribute_hidden;
 extern const char _nl_C_LC_CTYPE_class_punct[] attribute_hidden;
 extern const char _nl_C_LC_CTYPE_class_alnum[] attribute_hidden;
-extern const char _nl_C_LC_CTYPE_map_toupper[] attribute_hidden;
-extern const char _nl_C_LC_CTYPE_map_tolower[] attribute_hidden;
-extern const char _nl_C_LC_CTYPE_width[] attribute_hidden;
 
 #define b(t,x,o) (((const t *) _nl_C_LC_CTYPE_##x) + o)
 
-const unsigned short int *__ctype_b = b (unsigned short int, class, 128);
-const __uint32_t *__ctype32_b = b (__uint32_t, class32, 0);
-const __int32_t *__ctype_tolower = b (__int32_t, tolower, 128);
-const __int32_t *__ctype_toupper = b (__int32_t, toupper, 128);
-const __uint32_t *__ctype32_tolower = b (__uint32_t, tolower, 128);
-const __uint32_t *__ctype32_toupper = b (__uint32_t, toupper, 128);
-const char *__ctype32_wctype[12] attribute_hidden =
-{
-  b(char, class_upper, 32),
-  b(char, class_lower, 32),
-  b(char, class_alpha, 32),
-  b(char, class_digit, 32),
-  b(char, class_xdigit, 32),
-  b(char, class_space, 32),
-  b(char, class_print, 32),
-  b(char, class_graph, 32),
-  b(char, class_blank, 32),
-  b(char, class_cntrl, 32),
-  b(char, class_punct, 32),
-  b(char, class_alnum, 32)
-};
-const char *__ctype32_wctrans[2] attribute_hidden =
-{
-  b(char, map_toupper, 0),
-  b(char, map_tolower, 0)
-};
-const char *__ctype32_width attribute_hidden = b (char, width, 0);
+const unsigned short int *__ctype_old_b = b (unsigned short int, class, 128);
+const __uint32_t *__ctype32_old_b = b (__uint32_t, class32, 0);
+const __int32_t *__ctype_old_tolower = b (__int32_t, tolower, 128);
+const __int32_t *__ctype_old_toupper = b (__int32_t, toupper, 128);
+const __uint32_t *__ctype32_old_tolower = b (__uint32_t, tolower, 128);
+const __uint32_t *__ctype32_old_toupper = b (__uint32_t, toupper, 128);
+
+compat_symbol (libc, __ctype_old_b, __ctype_b, GLIBC_2_0);
+compat_symbol (libc, __ctype_old_tolower, __ctype_tolower, GLIBC_2_0);
+compat_symbol (libc, __ctype_old_toupper, __ctype_toupper, GLIBC_2_0);
+compat_symbol (libc, __ctype32_old_b, __ctype32_b, GLIBC_2_0);
+compat_symbol (libc, __ctype32_old_tolower, __ctype32_tolower, GLIBC_2_2);
+compat_symbol (libc, __ctype32_old_toupper, __ctype32_toupper, GLIBC_2_2);
+
+#endif
index 28aec6b..c7290ed 100644 (file)
@@ -65,6 +65,11 @@ enum
 /* These are defined in ctype-info.c.
    The declarations here must match those in localeinfo.h.
 
+   In the thread-specific locale model (see `uselocale' in <locale.h>)
+   we cannot use global variables for these as was done in the past.
+   Instead, the following accessor functions return the address of
+   each variable, which is local to the current thread if multithreaded.
+
    These point into arrays of 384, so they can be indexed by any `unsigned
    char' value [0,255]; by EOF (-1); or by any `signed char' value
    [-128,-1).  ISO C requires that the ctype functions work for `unsigned
@@ -73,12 +78,15 @@ enum
    rather than `unsigned char's because tolower (EOF) must be EOF, which
    doesn't fit into an `unsigned char'.  But today more important is that
    the arrays are also used for multi-byte character sets.  */
-extern __const unsigned short int *__ctype_b;  /* Characteristics.  */
-extern __const __int32_t *__ctype_tolower;     /* Case conversions.  */
-extern __const __int32_t *__ctype_toupper;     /* Case conversions.  */
+extern __const unsigned short int **__ctype_b_loc (void)
+     __attribute__ ((__const));
+extern __const __int32_t **__ctype_tolower_loc (void)
+     __attribute__ ((__const));
+extern __const __int32_t **__ctype_toupper_loc (void)
+     __attribute__ ((__const));
 
 #define __isctype(c, type) \
-  (__ctype_b[(int) (c)] & (unsigned short int) type)
+  ((*__ctype_b_loc ())[(int) (c)] & (unsigned short int) type)
 
 #define        __isascii(c)    (((c) & ~0x7f) == 0)    /* If C is a 7 bit value.  */
 #define        __toascii(c)    ((c) & 0x7f)            /* Mask off high bits.  */
@@ -182,27 +190,27 @@ __exctype (_tolower);
 extern __inline int
 tolower (int __c) __THROW
 {
-  return __c >= -128 && __c < 256 ? __ctype_tolower[__c] : __c;
+  return __c >= -128 && __c < 256 ? (*__ctype_tolower_loc ())[__c] : __c;
 }
 
 extern __inline int
 toupper (int __c) __THROW
 {
-  return __c >= -128 && __c < 256 ? __ctype_toupper[__c] : __c;
+  return __c >= -128 && __c < 256 ? (*__ctype_toupper_loc ())[__c] : __c;
 }
 # endif
 
 # if __GNUC__ >= 2 && defined __OPTIMIZE__ && !defined __cplusplus
-#  define tolower(c)   __tobody (c, tolower, __ctype_tolower, (c))
-#  define toupper(c)   __tobody (c, toupper, __ctype_toupper, (c))
+#  define tolower(c)   __tobody (c, tolower, *__ctype_tolower_loc (), (c))
+#  define toupper(c)   __tobody (c, toupper, *__ctype_toupper_loc (), (c))
 # endif /* Optimizing gcc */
 
 # if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN
 #  define isascii(c)   __isascii (c)
 #  define toascii(c)   __toascii (c)
 
-#  define _tolower(c)  ((int) __ctype_tolower[(int) (c)])
-#  define _toupper(c)  ((int) __ctype_toupper[(int) (c)])
+#  define _tolower(c)  ((int) (*__ctype_tolower_loc ())[(int) (c)])
+#  define _toupper(c)  ((int) (*__ctype_toupper_loc ())[(int) (c)])
 # endif
 
 #endif /* Not __NO_CTYPE.  */
index bf36872..5e7441f 100644 (file)
@@ -65,7 +65,10 @@ enum __hurd_threadvar_index
     _HURD_THREADVAR_MALLOC,    /* For use of malloc.  */
     _HURD_THREADVAR_DL_ERROR,  /* For use of -ldl and dynamic linker.  */
     _HURD_THREADVAR_RPC_VARS,  /* For state of RPC functions.  */
-    _HURD_THREADVAR_LOCALE,    /* For thread-locale locale setting.  */
+    _HURD_THREADVAR_LOCALE,    /* For thread-local locale setting.  */
+    _HURD_THREADVAR_CTYPE_B,   /* Cache of thread-local locale data.  */
+    _HURD_THREADVAR_CTYPE_TOLOWER, /* Cache of thread-local locale data.  */
+    _HURD_THREADVAR_CTYPE_TOUPPER, /* Cache of thread-local locale data.  */
     _HURD_THREADVAR_MAX                /* Default value for __hurd_threadvar_max.  */
   };
 
index b58306d..ca3c3dd 100644 (file)
@@ -2,39 +2,58 @@
 
 extern int __isctype (int __c, int __mask);
 
-# include <ctype/ctype.h>
-
 # ifndef NOT_IN_libc
 
-/* The optimized macros are not defined for users because they can't see
-   the thread-local locale state.  For inside libc, define them using the
-   _NL_CURRENT accessors.  We don't use _NL_CURRENT_LOCALE->__ctype_b here
-   because we want to cause a link-time ref to _nl_current_LC_CTYPE under
+/* These accessors are used by the optimized macros to find the
+   thread-local cache of ctype information from the current thread's
+   locale.  For inside libc, define them as inlines using the _NL_CURRENT
+   accessors.  We don't use _NL_CURRENT_LOCALE->__ctype_b here because we
+   want to cause a link-time ref to _nl_current_LC_CTYPE under
    NL_CURRENT_INDIRECT.  */
 
 #  include "../locale/localeinfo.h"
-#  ifndef __NO_CTYPE
-#   undef __isctype
-#   define __isctype(c, type) \
-     (((uint16_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS) + 128) \
-      [(int) (c)] & (uint16_t) type)
-
-#   undef tolower
-#   define tolower(c) \
-      __tobody (c, tolower, \
-               (uint32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOLOWER) + 128, \
-               (c))
-#   undef _tolower
-#   define _tolower(c) tolower (c)
-#   undef toupper
-#   define toupper(c) \
-      __tobody (c, toupper, \
-               (uint32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOUPPER) + 128, \
-               (c))
-#   undef _toupper
-#   define _toupper(c) toupper (c)
-
-#  endif /* Not __NO_CTYPE.  */
-# endif        /* _LIBC_REENTRANT.  */
+#  include <bits/libc-tsd.h>
+
+#  ifndef CTYPE_EXTERN_INLINE  /* Used by ctype/ctype-info.c, which see.  */
+#   define CTYPE_EXTERN_INLINE extern inline
+#  endif
+
+__libc_tsd_define (extern, CTYPE_B)
+__libc_tsd_define (extern, CTYPE_TOUPPER)
+__libc_tsd_define (extern, CTYPE_TOLOWER)
+
+CTYPE_EXTERN_INLINE const uint16_t ** __attribute__ ((const))
+__ctype_b_loc (void)
+{
+  const uint16_t **tablep =
+    (const uint16_t **) __libc_tsd_address (CTYPE_B);
+  if (__builtin_expect (*tablep == NULL, 0))
+    *tablep = (const uint16_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS) + 128;
+  return tablep;
+}
+
+CTYPE_EXTERN_INLINE const int32_t ** __attribute__ ((const))
+__ctype_toupper_loc (void)
+{
+  const int32_t **tablep =
+    (const int32_t **) __libc_tsd_address (CTYPE_TOUPPER);
+  if (__builtin_expect (*tablep == NULL, 0))
+    *tablep = ((int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOUPPER) + 128);
+  return tablep;
+}
+
+CTYPE_EXTERN_INLINE const int32_t ** __attribute__ ((const))
+__ctype_tolower_loc (void)
+{
+  const int32_t **tablep =
+    (const int32_t **) __libc_tsd_address (CTYPE_TOLOWER);
+  if (__builtin_expect (*tablep == NULL, 0))
+    *tablep = ((int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOLOWER) + 128);
+  return tablep;
+}
+
+# endif        /* Not NOT_IN_libc.  */
+
+# include <ctype/ctype.h>
 
 #endif /* ctype.h */
index 59ff701..3011f4e 100644 (file)
 _NL_CURRENT_DEFINE (LC_CTYPE);
 
 /* We are called after loading LC_CTYPE data to load it into
-   the variables used by the ctype.h macros.
-
-   There are three arrays of short ints which need to be indexable
-   from -128 to 255 inclusive.  Stored in the locale data file are
-   a copy of each for each byte order.  */
+   the variables used by the ctype.h macros.  */
 
 void
 _nl_postload_ctype (void)
 {
-  const struct locale_data *data = _NL_CURRENT_DATA (LC_CTYPE);
-
-#define paste(a,b) paste1(a,b)
-#define paste1(a,b) a##b
-
 #define current(type,x,offset) \
-  ((const type *) _NL_CURRENT (LC_CTYPE, paste(_NL_CTYPE_,x)) + offset)
-
-  extern const uint32_t *__ctype32_b;
-  extern const uint32_t *__ctype32_toupper;
-  extern const uint32_t *__ctype32_tolower;
-  extern const char *__ctype32_wctype[12] attribute_hidden;
-  extern const char *__ctype32_wctrans[2] attribute_hidden;
-  extern const char *__ctype32_width attribute_hidden;
-
-  size_t offset, cnt;
-
-  __ctype_b = current (uint16_t, CLASS, 128);
-  __ctype_toupper = current (uint32_t, TOUPPER, 128);
-  __ctype_tolower = current (uint32_t, TOLOWER, 128);
-  __ctype32_b = current (uint32_t, CLASS32, 0);
-  __ctype32_toupper = current (uint32_t, TOUPPER32, 0);
-  __ctype32_tolower = current (uint32_t, TOLOWER32, 0);
-
-  offset = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_CLASS_OFFSET);
-  for (cnt = 0; cnt < 12; cnt++)
-    __ctype32_wctype[cnt] = data->values[offset + cnt].string;
-
-  offset = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_OFFSET);
-  for (cnt = 0; cnt < 2; cnt++)
-    __ctype32_wctrans[cnt] = data->values[offset + cnt].string;
-
-  __ctype32_width = current (char, WIDTH, 0);
+  ((const type *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_##x) + offset)
+
+/* These are defined in ctype-info.c.
+   The declarations here must match those in localeinfo.h.
+
+   These point into arrays of 384, so they can be indexed by any `unsigned
+   char' value [0,255]; by EOF (-1); or by any `signed char' value
+   [-128,-1).  ISO C requires that the ctype functions work for `unsigned
+   char' values and for EOF; we also support negative `signed char' values
+   for broken old programs.  The case conversion arrays are of `int's
+   rather than `unsigned char's because tolower (EOF) must be EOF, which
+   doesn't fit into an `unsigned char'.  But today more important is that
+   the arrays are also used for multi-byte character sets.  */
+
+  if (_NL_CURRENT_LOCALE == &_nl_global_locale)
+    {
+      __libc_tsd_set (CTYPE_B, (void *) current (uint16_t, CLASS, 128));
+      __libc_tsd_set (CTYPE_TOUPPER, (void *) current (int32_t, TOUPPER, 128));
+      __libc_tsd_set (CTYPE_TOLOWER, (void *) current (int32_t, TOLOWER, 128));
+    }
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
+  extern __const unsigned short int *__ctype_old_b; /* Characteristics.  */
+  extern __const __int32_t *__ctype_old_tolower; /* Case conversions.  */
+  extern __const __int32_t *__ctype_old_toupper; /* Case conversions.  */
+
+  extern const uint32_t *__ctype32_old_b;
+  extern const uint32_t *__ctype32_old_toupper;
+  extern const uint32_t *__ctype32_old_tolower;
+
+  __ctype_old_b = current (uint16_t, CLASS, 128);
+  __ctype_old_toupper = current (uint32_t, TOUPPER, 128);
+  __ctype_old_tolower = current (uint32_t, TOLOWER, 128);
+  __ctype32_old_b = current (uint32_t, CLASS32, 0);
+  __ctype32_old_toupper = current (uint32_t, TOUPPER32, 0);
+  __ctype32_old_tolower = current (uint32_t, TOLOWER32, 0);
+#endif
 }
index d19ae50..e2f38c1 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <locale.h>
 #include "localeinfo.h"
+#include <ctype.h>
 
 /* Switch the current thread's locale to DATASET.
    If DATASET is null, instead just return the current setting.
@@ -60,6 +61,11 @@ __uselocale (locale_t newloc)
 # include "categories.def"
 # undef        DEFINE_CATEGORY
 #endif
+
+      /* Update the special tsd cache of some locale data.  */
+      __libc_tsd_set (CTYPE_B, (void *) locobj->__ctype_b);
+      __libc_tsd_set (CTYPE_TOLOWER, (void *) locobj->__ctype_tolower);
+      __libc_tsd_set (CTYPE_TOUPPER, (void *) locobj->__ctype_toupper);
     }
 
   return oldloc == &_nl_global_locale ? LC_GLOBAL_LOCALE : oldloc;