summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--include/wchar.h4
-rw-r--r--time/Makefile2
-rw-r--r--time/strftime.c62
-rw-r--r--wcsmbs/Makefile4
-rw-r--r--wcsmbs/mbsrtowcs.c29
-rw-r--r--wcsmbs/mbsrtowcs_l.c55
-rw-r--r--wcsmbs/wcsmbsload.c30
-rw-r--r--wcsmbs/wcsmbsload.h18
9 files changed, 185 insertions, 36 deletions
diff --git a/ChangeLog b/ChangeLog
index 4630f17d94..92230daca3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2002-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* include/wchar.h: Declare __mbsrtowcs_l.
+	* wcsmbs/Makefile (routines): Add mbsrtowcs_l.
+	* wcsmbs/mbsrtowcs.c: Add support for compilation with
+	USE_IN_EXTENDED_LOCALE_MODEL.
+	* wcsmbs/mbsrtowcs_l: New file.
+	* wcsmbs/wcsmbsload.c (__wcsmbs_to_wc): Renamed from to_wc.  Don't
+	define as static.  Change all uses.
+	(__wcsmbs_getfct): Renamed from getfct.  Don't define as static.
+	Change all callers.
+	* wcsmbs/wcsmbsload.h: Declare __wcsmbs_to_wc and __wcsmbs_getfct.
+	* time/strftime.c: When translating for the extended locale model
+	use the _l functions.
+	* time/Makefile (tests): Add tst-ftime_l.
+	* time/tst-ftime_l.c: New file.
+
 2002-08-28  Roland McGrath  <roland@redhat.com>
 
 	* locale/findlocale.c [NL_CURRENT_INDIRECT] (_nl_C): New variable.
diff --git a/include/wchar.h b/include/wchar.h
index 32afcbb6bb..e390f8104f 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -108,5 +108,9 @@ extern int __vfwprintf (__FILE *__restrict __s,
 			__gnuc_va_list __arg)
      /* __attribute__ ((__format__ (__wprintf__, 3, 0))) */;
 
+
+/* Internal functions.  */
+extern size_t __mbsrtowcs_l (wchar_t *dst, const char **src, size_t len,
+			     mbstate_t *ps, __locale_t l) attribute_hidden;
 # endif
 #endif
diff --git a/time/Makefile b/time/Makefile
index da51316069..133c86fb55 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -34,7 +34,7 @@ aux :=	    era alt_digit lc-time-cleanup
 distribute := datemsk
 
 tests	:= test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
-	   tst-getdate tst-mktime
+	   tst-getdate tst-mktime tst-ftime_l
 
 include ../Rules
 
diff --git a/time/strftime.c b/time/strftime.c
index 5215f567f0..e5eabf9d1c 100644
--- a/time/strftime.c
+++ b/time/strftime.c
@@ -283,14 +283,25 @@ static const CHAR_T zeroes[16] = /* "0000000000000000" */
 #define cpy(n, s) \
     add ((n),								      \
 	 if (to_lowcase)						      \
-	   memcpy_lowcase (p, (s), _n);					      \
+	   memcpy_lowcase (p, (s), _n LOCALE_ARG);			      \
 	 else if (to_uppcase)						      \
-	   memcpy_uppcase (p, (s), _n);					      \
+	   memcpy_uppcase (p, (s), _n LOCALE_ARG);			      \
 	 else								      \
 	   MEMCPY ((PTR) p, (const PTR) (s), _n))
 
 #ifdef COMPILE_WIDE
-# define widen(os, ws, l) \
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+#  define widen(os, ws, l) \
+  {									      \
+    mbstate_t __st;							      \
+    const char *__s = os;						      \
+    memset (&__st, '\0', sizeof (__st));				      \
+    l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc);			      \
+    ws = alloca ((l + 1) * sizeof (wchar_t));				      \
+    (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc);			      \
+  }
+# else
+#  define widen(os, ws, l) \
   {									      \
     mbstate_t __st;							      \
     const char *__s = os;						      \
@@ -299,6 +310,7 @@ static const CHAR_T zeroes[16] = /* "0000000000000000" */
     ws = alloca ((l + 1) * sizeof (wchar_t));				      \
     (void) __mbsrtowcs (ws, &__s, l, &__st);				      \
   }
+# endif
 #endif
 
 
@@ -314,10 +326,12 @@ static const CHAR_T zeroes[16] = /* "0000000000000000" */
   (current->values[_NL_ITEM_INDEX (item)].string)
 # define LOCALE_PARAM , loc
 # define LOCALE_ARG , loc
-# define LOCALE_PARAM_DECL __locale_t loc;
-# define HELPER_LOCALE_ARG , current
+# define LOCALE_PARAM_DECL  __locale_t loc;
+# define LOCALE_PARAM_PROTO , __locale_t loc
+# define HELPER_LOCALE_ARG  , current
 #else
 # define LOCALE_PARAM
+# define LOCALE_PARAM_PROTO
 # define LOCALE_ARG
 # define LOCALE_PARAM_DECL
 # ifdef _LIBC
@@ -328,15 +342,25 @@ static const CHAR_T zeroes[16] = /* "0000000000000000" */
 #endif
 
 #ifdef COMPILE_WIDE
-# define TOUPPER(Ch) towupper (Ch)
-# define TOLOWER(Ch) towlower (Ch)
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+#  define TOUPPER(Ch, L) __towupper_l (Ch, L)
+#  define TOLOWER(Ch, L) __towlower_l (Ch, L)
+# else
+#  define TOUPPER(Ch, L) towupper (Ch)
+#  define TOLOWER(Ch, L) towlower (Ch)
+# endif
 #else
 # ifdef _LIBC
-#  define TOUPPER(Ch) toupper (Ch)
-#  define TOLOWER(Ch) tolower (Ch)
+#  ifdef USE_IN_EXTENDED_LOCALE_MODEL
+#   define TOUPPER(Ch, L) __toupper_l (Ch, L)
+#   define TOLOWER(Ch, L) __tolower_l (Ch, L)
+#  else
+#   define TOUPPER(Ch, L) toupper (Ch)
+#   define TOLOWER(Ch, L) tolower (Ch)
+#  endif
 # else
-#  define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
-#  define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+#  define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
+#  define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
 # endif
 #endif
 /* We don't use `isdigit' here since the locale dependent
@@ -346,30 +370,32 @@ static const CHAR_T zeroes[16] = /* "0000000000000000" */
 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
 
 static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
-				    size_t len));
+				    size_t len LOCALE_PARAM_PROTO));
 
 static CHAR_T *
-memcpy_lowcase (dest, src, len)
+memcpy_lowcase (dest, src, len LOCALE_PARAM)
      CHAR_T *dest;
      const CHAR_T *src;
      size_t len;
+     LOCALE_PARAM_DECL
 {
   while (len-- > 0)
-    dest[len] = TOLOWER ((UCHAR_T) src[len]);
+    dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
   return dest;
 }
 
 static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
-				    size_t len));
+				    size_t len LOCALE_PARAM_PROTO));
 
 static CHAR_T *
-memcpy_uppcase (dest, src, len)
+memcpy_uppcase (dest, src, len LOCALE_PARAM)
      CHAR_T *dest;
      const CHAR_T *src;
      size_t len;
+     LOCALE_PARAM_DECL
 {
   while (len-- > 0)
-    dest[len] = TOUPPER ((UCHAR_T) src[len]);
+    dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
   return dest;
 }
 
@@ -844,7 +870,7 @@ my_strftime (s, maxsize, format, tp ut_argument LOCALE_PARAM)
 	    if (to_uppcase)
 	      while (old_start < p)
 		{
-		  *old_start = TOUPPER ((UCHAR_T) *old_start);
+		  *old_start = TOUPPER ((UCHAR_T) *old_start, loc);
 		  ++old_start;
 		}
 	  }
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
index 1b403f3a4c..882084db1e 100644
--- a/wcsmbs/Makefile
+++ b/wcsmbs/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1995,1996,1997,1998,1999,2000 Free Software Foundation, Inc.
+# Copyright (C) 1995-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
@@ -37,7 +37,7 @@ routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
 	    wcwidth wcswidth \
 	    wcscoll_l wcsxfrm_l \
 	    wcscasecmp wcsncase wcscasecmp_l wcsncase_l \
-	    wcsmbsload
+	    wcsmbsload mbsrtowcs_l
 
 tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \
 	 tst-wcrtomb
diff --git a/wcsmbs/mbsrtowcs.c b/wcsmbs/mbsrtowcs.c
index aa93426a5c..097e462110 100644
--- a/wcsmbs/mbsrtowcs.c
+++ b/wcsmbs/mbsrtowcs.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.
 
@@ -32,6 +32,16 @@
 #endif
 
 
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+size_t
+attribute_hidden
+__mbsrtowcs_l (dst, src, len, ps, l)
+     wchar_t *dst;
+     const char **src;
+     size_t len;
+     mbstate_t *ps;
+     __locale_t l;
+#else
 /* This is the private state used if PS is NULL.  */
 static mbstate_t state;
 
@@ -41,6 +51,7 @@ __mbsrtowcs (dst, src, len, ps)
      const char **src;
      size_t len;
      mbstate_t *ps;
+#endif
 {
   struct __gconv_step_data data;
   size_t result;
@@ -52,14 +63,23 @@ __mbsrtowcs (dst, src, len, ps)
   data.__invocation_counter = 0;
   data.__internal_use = 1;
   data.__flags = __GCONV_IS_LAST;
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+  data.__statep = ps;
+#else
   data.__statep = ps ?: &state;
+#endif
   data.__trans = NULL;
 
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+  /* Get the conversion function matching the locale.  */
+  towc = wcsmbs_get_towc_func (l);
+#else
   /* Make sure we use the correct function.  */
   update_conversion_ptrs ();
 
   /* Get the structure with the function pointers.  */
   towc = __wcsmbs_gconv_fcts.towc;
+#endif
 
   /* We have to handle DST == NULL special.  */
   if (dst == NULL)
@@ -140,6 +160,13 @@ __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
 weak_alias (__mbsrtowcs, mbsrtowcs)
+#endif
diff --git a/wcsmbs/mbsrtowcs_l.c b/wcsmbs/mbsrtowcs_l.c
new file mode 100644
index 0000000000..47ba82fecf
--- /dev/null
+++ b/wcsmbs/mbsrtowcs_l.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.org>, 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <ctype.h>
+#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/wcsmbsload.c b/wcsmbs/wcsmbsload.c
index c096804a68..fc846c7237 100644
--- a/wcsmbs/wcsmbsload.c
+++ b/wcsmbs/wcsmbsload.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -26,7 +26,6 @@
 #include <locale/localeinfo.h>
 #include <wcsmbsload.h>
 #include <bits/libc-lock.h>
-#include <iconv/gconv_int.h>
 
 
 /* Last loaded locale for LC_CTYPE.  We initialize for the C locale
@@ -36,7 +35,7 @@ const struct locale_data *__wcsmbs_last_locale = &_nl_C_LC_CTYPE;
 
 
 /* These are the descriptions for the default conversion functions.  */
-static struct __gconv_step to_wc =
+struct __gconv_step __wcsmbs_to_wc attribute_hidden =
 {
   .__shlib_handle = NULL,
   .__modname = NULL,
@@ -76,15 +75,16 @@ 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 =
 {
-  .towc = &to_wc,
+  .towc = &__wcsmbs_to_wc,
   .towc_nsteps = 1,
   .tomb = &to_mb,
   .tomb_nsteps = 1
 };
 
 
-static inline struct __gconv_step *
-getfct (const char *to, const char *from, size_t *nstepsp)
+struct __gconv_step *
+attribute_hidden
+__wcsmbs_getfct (const char *to, const char *from, size_t *nstepsp)
 {
   size_t nsteps;
   struct __gconv_step *result;
@@ -167,7 +167,7 @@ __wcsmbs_load_conv (const struct locale_data *new_category)
       if (new_category->name == _nl_C_name)	/* Yes, pointer comparison.  */
 	{
 	failed:
-	  __wcsmbs_gconv_fcts.towc = &to_wc;
+	  __wcsmbs_gconv_fcts.towc = &__wcsmbs_to_wc;
 	  __wcsmbs_gconv_fcts.tomb = &to_mb;
 	}
       else
@@ -185,7 +185,7 @@ __wcsmbs_load_conv (const struct locale_data *new_category)
 	  if (__wcsmbs_gconv_fcts.tomb != &to_mb)
 	    __gconv_close_transform (__wcsmbs_gconv_fcts.tomb,
 				     __wcsmbs_gconv_fcts.tomb_nsteps);
-	  if (__wcsmbs_gconv_fcts.towc != &to_wc)
+	  if (__wcsmbs_gconv_fcts.towc != &__wcsmbs_to_wc)
 	    __gconv_close_transform (__wcsmbs_gconv_fcts.towc,
 				     __wcsmbs_gconv_fcts.towc_nsteps);
 
@@ -203,9 +203,11 @@ __wcsmbs_load_conv (const struct locale_data *new_category)
 	  /* 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 = getfct ("INTERNAL", complete_name, &new_towc_nsteps);
+	  new_towc = __wcsmbs_getfct ("INTERNAL", complete_name,
+				      &new_towc_nsteps);
 	  new_tomb = (new_towc != NULL
-		      ? getfct (complete_name, "INTERNAL", &new_tomb_nsteps)
+		      ? __wcsmbs_getfct (complete_name, "INTERNAL",
+					 &new_tomb_nsteps)
 		      : NULL);
 
 	  /* If any of the conversion functions is not available we don't
@@ -262,10 +264,10 @@ int
 internal_function
 __wcsmbs_named_conv (struct gconv_fcts *copy, const char *name)
 {
-  copy->towc = getfct ("INTERNAL", name, &copy->towc_nsteps);
+  copy->towc = __wcsmbs_getfct ("INTERNAL", name, &copy->towc_nsteps);
   if (copy->towc != NULL)
     {
-      copy->tomb = getfct (name, "INTERNAL", &copy->tomb_nsteps);
+      copy->tomb = __wcsmbs_getfct (name, "INTERNAL", &copy->tomb_nsteps);
       if (copy->tomb == NULL)
 	__gconv_close_transform (copy->towc, copy->towc_nsteps);
     }
@@ -287,11 +289,11 @@ free_mem (void)
       __gconv_release_cache (old, nold);
     }
 
-  if (__wcsmbs_gconv_fcts.towc != &to_wc)
+  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 = &to_wc;
+      __wcsmbs_gconv_fcts.towc = &__wcsmbs_to_wc;
       __wcsmbs_gconv_fcts.towc_nsteps = 1;
       __gconv_release_cache (old, nold);
     }
diff --git a/wcsmbs/wcsmbsload.h b/wcsmbs/wcsmbsload.h
index 1fcb42c033..b7594ce5e9 100644
--- a/wcsmbs/wcsmbsload.h
+++ b/wcsmbs/wcsmbsload.h
@@ -17,6 +17,9 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#ifndef _WCSMBSLOAD_H
+#define _WCSMBSLOAD_H	1
+
 #include <locale.h>
 #include <wchar.h>
 #include <locale/localeinfo.h>
@@ -52,6 +55,19 @@ extern int __wcsmbs_named_conv (struct gconv_fcts *copy, const char *name)
      internal_function;
 
 
+#include <iconv/gconv_int.h>
+
+
+/* Variable for conversion from ASCII to wchar_t.  */
+extern struct __gconv_step __wcsmbs_to_wc attribute_hidden;
+
+
+/* Load the function implementation if necessary.  */
+extern struct __gconv_step *__wcsmbs_getfct (const char *to, const char *from,
+					     size_t *nstepsp)
+     attribute_hidden;
+
+
 /* Check whether the LC_CTYPE locale changed since the last call.
    Update the pointers appropriately.  */
 static inline void
@@ -60,3 +76,5 @@ update_conversion_ptrs (void)
   if (__wcsmbs_last_locale != _NL_CURRENT_DATA (LC_CTYPE))
     __wcsmbs_load_conv (_NL_CURRENT_DATA (LC_CTYPE));
 }
+
+#endif	/* wcsmbsload.h */