diff --git a/ChangeLog b/ChangeLog index 4630f17d94..92230daca3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2002-08-28 Ulrich Drepper + + * 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 * 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 , 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 , 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 +#include +#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 , 1998. @@ -26,7 +26,6 @@ #include #include #include -#include /* 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, ©->towc_nsteps); + copy->towc = __wcsmbs_getfct ("INTERNAL", name, ©->towc_nsteps); if (copy->towc != NULL) { - copy->tomb = getfct (name, "INTERNAL", ©->tomb_nsteps); + copy->tomb = __wcsmbs_getfct (name, "INTERNAL", ©->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 #include #include @@ -52,6 +55,19 @@ extern int __wcsmbs_named_conv (struct gconv_fcts *copy, const char *name) internal_function; +#include + + +/* 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 */