Module Name: src Committed By: joerg Date: Fri Sep 13 13:13:32 UTC 2013
Modified Files: src/lib/libc/citrus: citrus_lc_ctype.c src/lib/libc/compat/locale: compat_setlocale1.c src/lib/libc/locale: global_locale.c localeconv.c nb_lc_messages_misc.h nb_lc_monetary_misc.h nb_lc_numeric_misc.h nb_lc_template.h nb_lc_template_decl.h nb_lc_time_misc.h newlocale.c setlocale.c setlocale_local.h Log Message: Redo the locale cache to be constant. It now contains the localeconv() data and which LC_MONETARY and LC_NUMERIC values it is derived from. In newlocale(3) and setlocale(3), check for the existing entries and on miss, create a new entry. This is currently not using a lock for the list as the worst case is a small memory leak. To generate a diff of this commit: cvs rdiff -u -r1.14 -r1.15 src/lib/libc/citrus/citrus_lc_ctype.c cvs rdiff -u -r1.1 -r1.2 src/lib/libc/compat/locale/compat_setlocale1.c cvs rdiff -u -r1.20 -r1.21 src/lib/libc/locale/global_locale.c cvs rdiff -u -r1.21 -r1.22 src/lib/libc/locale/localeconv.c cvs rdiff -u -r1.6 -r1.7 src/lib/libc/locale/nb_lc_messages_misc.h \ src/lib/libc/locale/nb_lc_monetary_misc.h \ src/lib/libc/locale/nb_lc_numeric_misc.h cvs rdiff -u -r1.7 -r1.8 src/lib/libc/locale/nb_lc_template.h \ src/lib/libc/locale/nb_lc_time_misc.h cvs rdiff -u -r1.3 -r1.4 src/lib/libc/locale/nb_lc_template_decl.h cvs rdiff -u -r1.2 -r1.3 src/lib/libc/locale/newlocale.c cvs rdiff -u -r1.63 -r1.64 src/lib/libc/locale/setlocale.c cvs rdiff -u -r1.14 -r1.15 src/lib/libc/locale/setlocale_local.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/citrus/citrus_lc_ctype.c diff -u src/lib/libc/citrus/citrus_lc_ctype.c:1.14 src/lib/libc/citrus/citrus_lc_ctype.c:1.15 --- src/lib/libc/citrus/citrus_lc_ctype.c:1.14 Tue Aug 20 19:58:30 2013 +++ src/lib/libc/citrus/citrus_lc_ctype.c Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_lc_ctype.c,v 1.14 2013/08/20 19:58:30 joerg Exp $ */ +/* $NetBSD: citrus_lc_ctype.c,v 1.15 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)2008 Citrus Project, @@ -28,7 +28,7 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_lc_ctype.c,v 1.14 2013/08/20 19:58:30 joerg Exp $"); +__RCSID("$NetBSD: citrus_lc_ctype.c,v 1.15 2013/09/13 13:13:32 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include "reentrant.h" @@ -96,14 +96,6 @@ _citrus_LC_CTYPE_create_impl(const char } static __inline void -_PREFIX(build_cache)(struct _locale_cache_t * __restrict cache, - _RuneLocale * __restrict data) -{ - _DIAGASSERT(cache != NULL); - _DIAGASSERT(data != NULL); -} - -static __inline void _PREFIX(update_global)(_RuneLocale *data) { _DIAGASSERT(data != NULL); Index: src/lib/libc/compat/locale/compat_setlocale1.c diff -u src/lib/libc/compat/locale/compat_setlocale1.c:1.1 src/lib/libc/compat/locale/compat_setlocale1.c:1.2 --- src/lib/libc/compat/locale/compat_setlocale1.c:1.1 Mon Jun 7 13:52:30 2010 +++ src/lib/libc/compat/locale/compat_setlocale1.c Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: compat_setlocale1.c,v 1.1 2010/06/07 13:52:30 tnozaki Exp $ */ +/* $NetBSD: compat_setlocale1.c,v 1.2 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)1999 Citrus Project, @@ -30,7 +30,7 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: compat_setlocale1.c,v 1.1 2010/06/07 13:52:30 tnozaki Exp $"); +__RCSID("$NetBSD: compat_setlocale1.c,v 1.2 2013/09/13 13:13:32 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> @@ -38,6 +38,8 @@ __RCSID("$NetBSD: compat_setlocale1.c,v #include "setlocale_local.h" +#undef setlocale + __warn_references(setlocale, "warning: reference to compatibility setlocale();" "include <locale.h> for correct reference") @@ -47,7 +49,10 @@ __warn_references(setlocale, * This function will ensure binary compatibility for old executables. */ char * -setlocale(int category, const char *locale) +compat_setlocale(int category, const char *locale) __RENAME(setlocale); + +char * +compat_setlocale(int category, const char *locale) { /* locale may be NULL */ Index: src/lib/libc/locale/global_locale.c diff -u src/lib/libc/locale/global_locale.c:1.20 src/lib/libc/locale/global_locale.c:1.21 --- src/lib/libc/locale/global_locale.c:1.20 Tue Aug 20 19:58:30 2013 +++ src/lib/libc/locale/global_locale.c Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: global_locale.c,v 1.20 2013/08/20 19:58:30 joerg Exp $ */ +/* $NetBSD: global_locale.c,v 1.21 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)2008 Citrus Project, @@ -28,7 +28,7 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: global_locale.c,v 1.20 2013/08/20 19:58:30 joerg Exp $"); +__RCSID("$NetBSD: global_locale.c,v 1.21 2013/09/13 13:13:32 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> @@ -110,7 +110,10 @@ static const _TimeLocale _DefaultTimeLoc "%I:%M:%S %p" }; -static const struct lconv _C_ldata = { +static const char _lc_C_locale_name[] = _C_LOCALE; + +__dso_hidden const struct _locale_cache_t _C_cache = { + .ldata = { .decimal_point = __UNCONST("."), .thousands_sep = __UNCONST(""), .grouping = __UNCONST(""), @@ -135,23 +138,22 @@ static const struct lconv _C_ldata = { .int_n_sep_by_space = NBCHAR_MAX, .int_p_sign_posn = NBCHAR_MAX, .int_n_sign_posn = NBCHAR_MAX, -}; - -static struct _locale_cache_t _global_cache = { - .ldata = __UNCONST(&_C_ldata), + }, + .monetary_name = _lc_C_locale_name, + .numeric_name = _lc_C_locale_name, }; __dso_protected struct _locale _lc_global_locale = { - .cache = &_global_cache, + .cache = &_C_cache, .query = { _C_LOCALE }, .part_name = { - [(size_t)LC_ALL ] = _C_LOCALE, - [(size_t)LC_COLLATE ] = _C_LOCALE, - [(size_t)LC_CTYPE ] = _C_LOCALE, - [(size_t)LC_MONETARY] = _C_LOCALE, - [(size_t)LC_NUMERIC ] = _C_LOCALE, - [(size_t)LC_TIME ] = _C_LOCALE, - [(size_t)LC_MESSAGES] = _C_LOCALE, + [(size_t)LC_ALL ] = _lc_C_locale_name, + [(size_t)LC_COLLATE ] = _lc_C_locale_name, + [(size_t)LC_CTYPE ] = _lc_C_locale_name, + [(size_t)LC_MONETARY] = _lc_C_locale_name, + [(size_t)LC_NUMERIC ] = _lc_C_locale_name, + [(size_t)LC_TIME ] = _lc_C_locale_name, + [(size_t)LC_MESSAGES] = _lc_C_locale_name, }, .part_impl = { [(size_t)LC_ALL ] = (_locale_part_t)NULL, @@ -169,21 +171,17 @@ __dso_protected struct _locale _lc_globa }, }; -static const struct _locale_cache_t _C_cache = { - .ldata = __UNCONST(&_C_ldata), -}; - __dso_protected const struct _locale _lc_C_locale = { - .cache = __UNCONST(&_C_cache), + .cache = &_C_cache, .query = { _C_LOCALE }, .part_name = { - [(size_t)LC_ALL ] = _C_LOCALE, - [(size_t)LC_COLLATE ] = _C_LOCALE, - [(size_t)LC_CTYPE ] = _C_LOCALE, - [(size_t)LC_MONETARY] = _C_LOCALE, - [(size_t)LC_NUMERIC ] = _C_LOCALE, - [(size_t)LC_TIME ] = _C_LOCALE, - [(size_t)LC_MESSAGES] = _C_LOCALE, + [(size_t)LC_ALL ] = _lc_C_locale_name, + [(size_t)LC_COLLATE ] = _lc_C_locale_name, + [(size_t)LC_CTYPE ] = _lc_C_locale_name, + [(size_t)LC_MONETARY] = _lc_C_locale_name, + [(size_t)LC_NUMERIC ] = _lc_C_locale_name, + [(size_t)LC_TIME ] = _lc_C_locale_name, + [(size_t)LC_MESSAGES] = _lc_C_locale_name, }, .part_impl = { [(size_t)LC_ALL ] = (_locale_part_t)NULL, Index: src/lib/libc/locale/localeconv.c diff -u src/lib/libc/locale/localeconv.c:1.21 src/lib/libc/locale/localeconv.c:1.22 --- src/lib/libc/locale/localeconv.c:1.21 Fri May 17 12:55:57 2013 +++ src/lib/libc/locale/localeconv.c Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: localeconv.c,v 1.21 2013/05/17 12:55:57 joerg Exp $ */ +/* $NetBSD: localeconv.c,v 1.22 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)2008 Citrus Project, @@ -28,7 +28,7 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: localeconv.c,v 1.21 2013/05/17 12:55:57 joerg Exp $"); +__RCSID("$NetBSD: localeconv.c,v 1.22 2013/09/13 13:13:32 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> @@ -41,11 +41,11 @@ __RCSID("$NetBSD: localeconv.c,v 1.21 20 struct lconv * localeconv(void) { - return _current_cache()->ldata; + return localeconv_l(_current_locale()); } struct lconv * localeconv_l(locale_t loc) { - return loc->cache->ldata; + return __UNCONST(&loc->cache->ldata); } Index: src/lib/libc/locale/nb_lc_messages_misc.h diff -u src/lib/libc/locale/nb_lc_messages_misc.h:1.6 src/lib/libc/locale/nb_lc_messages_misc.h:1.7 --- src/lib/libc/locale/nb_lc_messages_misc.h:1.6 Tue Aug 20 19:58:30 2013 +++ src/lib/libc/locale/nb_lc_messages_misc.h Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: nb_lc_messages_misc.h,v 1.6 2013/08/20 19:58:30 joerg Exp $ */ +/* $NetBSD: nb_lc_messages_misc.h,v 1.7 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)2008 Citrus Project, @@ -34,14 +34,6 @@ */ #define _CATEGORY_TYPE _MessagesLocale -static __inline void -_PREFIX(build_cache)(struct _locale_cache_t * __restrict cache, - _MessagesLocale * __restrict data) -{ - _DIAGASSERT(cache != NULL); - _DIAGASSERT(data != NULL); -} - /* ARGSUSED */ static __inline void _PREFIX(update_global)(_MessagesLocale *data) Index: src/lib/libc/locale/nb_lc_monetary_misc.h diff -u src/lib/libc/locale/nb_lc_monetary_misc.h:1.6 src/lib/libc/locale/nb_lc_monetary_misc.h:1.7 --- src/lib/libc/locale/nb_lc_monetary_misc.h:1.6 Tue Aug 20 19:58:30 2013 +++ src/lib/libc/locale/nb_lc_monetary_misc.h Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: nb_lc_monetary_misc.h,v 1.6 2013/08/20 19:58:30 joerg Exp $ */ +/* $NetBSD: nb_lc_monetary_misc.h,v 1.7 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)2008 Citrus Project, @@ -34,41 +34,6 @@ */ #define _CATEGORY_TYPE _MonetaryLocale -static __inline void -_PREFIX(build_cache)(struct _locale_cache_t * __restrict cache, - _MonetaryLocale * __restrict data) -{ - struct lconv *ldata; - - _DIAGASSERT(cache != NULL); - _DIAGASSERT(cache->ldata != NULL); - _DIAGASSERT(data != NULL); - - ldata = cache->ldata; - ldata->int_curr_symbol = __UNCONST(data->int_curr_symbol); - ldata->currency_symbol = __UNCONST(data->currency_symbol); - ldata->mon_decimal_point = __UNCONST(data->mon_decimal_point); - ldata->mon_thousands_sep = __UNCONST(data->mon_thousands_sep); - ldata->mon_grouping = __UNCONST(data->mon_grouping); - ldata->positive_sign = __UNCONST(data->positive_sign); - ldata->negative_sign = __UNCONST(data->negative_sign); - - ldata->int_frac_digits = data->int_frac_digits; - ldata->frac_digits = data->frac_digits; - ldata->p_cs_precedes = data->p_cs_precedes; - ldata->p_sep_by_space = data->p_sep_by_space; - ldata->n_cs_precedes = data->n_cs_precedes; - ldata->n_sep_by_space = data->n_sep_by_space; - ldata->p_sign_posn = data->p_sign_posn; - ldata->n_sign_posn = data->n_sign_posn; - ldata->int_p_cs_precedes = data->int_p_cs_precedes; - ldata->int_n_cs_precedes = data->int_n_cs_precedes; - ldata->int_p_sep_by_space = data-> int_p_sep_by_space; - ldata->int_n_sep_by_space = data->int_n_sep_by_space; - ldata->int_p_sign_posn = data->int_p_sign_posn; - ldata->int_n_sign_posn = data->int_n_sign_posn; -} - /* ARGSUSED */ static __inline void _PREFIX(update_global)(_MonetaryLocale *data) Index: src/lib/libc/locale/nb_lc_numeric_misc.h diff -u src/lib/libc/locale/nb_lc_numeric_misc.h:1.6 src/lib/libc/locale/nb_lc_numeric_misc.h:1.7 --- src/lib/libc/locale/nb_lc_numeric_misc.h:1.6 Tue Aug 20 19:58:30 2013 +++ src/lib/libc/locale/nb_lc_numeric_misc.h Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: nb_lc_numeric_misc.h,v 1.6 2013/08/20 19:58:30 joerg Exp $ */ +/* $NetBSD: nb_lc_numeric_misc.h,v 1.7 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)2008 Citrus Project, @@ -34,22 +34,6 @@ */ #define _CATEGORY_TYPE _NumericLocale -static __inline void -_PREFIX(build_cache)(struct _locale_cache_t * __restrict cache, - _NumericLocale * __restrict data) -{ - struct lconv *ldata; - - _DIAGASSERT(cache != NULL); - _DIAGASSERT(cache->ldata != NULL); - _DIAGASSERT(data != NULL); - - ldata = cache->ldata; - ldata->decimal_point = __UNCONST(data->decimal_point); - ldata->thousands_sep = __UNCONST(data->thousands_sep); - ldata->grouping = __UNCONST(data->grouping); -} - /* ARGSUSED */ static __inline void _PREFIX(update_global)(_NumericLocale *data) Index: src/lib/libc/locale/nb_lc_template.h diff -u src/lib/libc/locale/nb_lc_template.h:1.7 src/lib/libc/locale/nb_lc_template.h:1.8 --- src/lib/libc/locale/nb_lc_template.h:1.7 Sun Aug 18 20:03:48 2013 +++ src/lib/libc/locale/nb_lc_template.h Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: nb_lc_template.h,v 1.7 2013/08/18 20:03:48 joerg Exp $ */ +/* $NetBSD: nb_lc_template.h,v 1.8 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)1999, 2008 Citrus Project, @@ -234,7 +234,6 @@ _PREFIX(setlocale)(const char * __restri return NULL; locale->part_name[(size_t)_CATEGORY_ID] = loaded_name; locale->part_impl[(size_t)_CATEGORY_ID] = loaded_impl; - _PREFIX(build_cache)(locale->cache, loaded_impl); if (locale == &_lc_global_locale) _PREFIX(update_global)(loaded_impl); } Index: src/lib/libc/locale/nb_lc_time_misc.h diff -u src/lib/libc/locale/nb_lc_time_misc.h:1.7 src/lib/libc/locale/nb_lc_time_misc.h:1.8 --- src/lib/libc/locale/nb_lc_time_misc.h:1.7 Tue Aug 20 19:58:30 2013 +++ src/lib/libc/locale/nb_lc_time_misc.h Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: nb_lc_time_misc.h,v 1.7 2013/08/20 19:58:30 joerg Exp $ */ +/* $NetBSD: nb_lc_time_misc.h,v 1.8 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)2008 Citrus Project, @@ -40,15 +40,6 @@ #define MON_IDX(idx) ((size_t)idx - (size_t)MON_1) #define AM_PM_IDX(idx) ((size_t)idx - (size_t)AM_STR) -static __inline void -/*ARGSUSED*/ -_PREFIX(build_cache)(struct _locale_cache_t * __restrict cache, - _TimeLocale * __restrict data) -{ - _DIAGASSERT(cache != NULL); - _DIAGASSERT(data != NULL); -} - /* ARGSUSED */ static __inline void _PREFIX(update_global)(_TimeLocale *data) Index: src/lib/libc/locale/nb_lc_template_decl.h diff -u src/lib/libc/locale/nb_lc_template_decl.h:1.3 src/lib/libc/locale/nb_lc_template_decl.h:1.4 --- src/lib/libc/locale/nb_lc_template_decl.h:1.3 Sun Aug 18 20:03:48 2013 +++ src/lib/libc/locale/nb_lc_template_decl.h Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: nb_lc_template_decl.h,v 1.3 2013/08/18 20:03:48 joerg Exp $ */ +/* $NetBSD: nb_lc_template_decl.h,v 1.4 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)2008 Citrus Project, @@ -36,10 +36,6 @@ _PREFIX(create_impl)(const char * __rest const char * __restrict, _CATEGORY_TYPE ** __restrict); static __inline void -_PREFIX(build_cache)(struct _locale_cache_t * __restrict, - _CATEGORY_TYPE * __restrict); - -static __inline void _PREFIX(update_global)(_CATEGORY_TYPE *); #endif /*_NB_LC_TEMPLATE_DECL_H_*/ Index: src/lib/libc/locale/newlocale.c diff -u src/lib/libc/locale/newlocale.c:1.2 src/lib/libc/locale/newlocale.c:1.3 --- src/lib/libc/locale/newlocale.c:1.2 Fri May 17 12:55:57 2013 +++ src/lib/libc/locale/newlocale.c Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: newlocale.c,v 1.2 2013/05/17 12:55:57 joerg Exp $ */ +/* $NetBSD: newlocale.c,v 1.3 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)2008, 2011 Citrus Project, @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: newlocale.c,v 1.2 2013/05/17 12:55:57 joerg Exp $"); +__RCSID("$NetBSD: newlocale.c,v 1.3 2013/09/13 13:13:32 joerg Exp $"); #include "namespace.h" #include <assert.h> @@ -97,5 +97,9 @@ newlocale(int mask, const char *name, lo } } } + if (_setlocale_cache(dst, NULL)) { + free(dst); + return NULL; + } return (locale_t)dst; } Index: src/lib/libc/locale/setlocale.c diff -u src/lib/libc/locale/setlocale.c:1.63 src/lib/libc/locale/setlocale.c:1.64 --- src/lib/libc/locale/setlocale.c:1.63 Fri May 17 12:55:57 2013 +++ src/lib/libc/locale/setlocale.c Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: setlocale.c,v 1.63 2013/05/17 12:55:57 joerg Exp $ */ +/* $NetBSD: setlocale.c,v 1.64 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)2008 Citrus Project, @@ -28,10 +28,11 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: setlocale.c,v 1.63 2013/05/17 12:55:57 joerg Exp $"); +__RCSID("$NetBSD: setlocale.c,v 1.64 2013/09/13 13:13:32 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> +#include <sys/localedef.h> #include <locale.h> #include <limits.h> #include <paths.h> @@ -53,6 +54,76 @@ static _locale_set_t all_categories[_LC_ [LC_MESSAGES] = &_citrus_LC_MESSAGES_setlocale, }; +/* XXX Consider locking the list. Race condition leaks memory. */ +static SLIST_HEAD(, _locale_cache_t) caches = { + __UNCONST(&_C_cache) +}; + +int +_setlocale_cache(locale_t loc, struct _locale_cache_t *cache) +{ + const char *monetary_name = loc->part_name[LC_MONETARY]; + const char *numeric_name = loc->part_name[LC_NUMERIC]; + _NumericLocale *numeric = loc->part_impl[LC_NUMERIC]; + _MonetaryLocale *monetary = loc->part_impl[LC_MONETARY]; + struct lconv *ldata; + + struct _locale_cache_t *old_cache; + + SLIST_FOREACH(old_cache, &caches, cache_link) { + if (monetary_name != old_cache->monetary_name && + strcmp(monetary_name, old_cache->monetary_name) != 0) + continue; + if (numeric_name != old_cache->numeric_name && + strcmp(numeric_name, old_cache->numeric_name) != 0) + continue; + loc->cache = old_cache; + free(cache); + return 0; + } + + if (cache == NULL) { + cache = malloc(sizeof(*cache)); + if (cache == NULL) + return -1; + } + + cache->monetary_name = monetary_name; + cache->numeric_name = numeric_name; + ldata = &cache->ldata; + + ldata->decimal_point = __UNCONST(numeric->decimal_point); + ldata->thousands_sep = __UNCONST(numeric->thousands_sep); + ldata->grouping = __UNCONST(numeric->grouping); + + ldata->int_curr_symbol = __UNCONST(monetary->int_curr_symbol); + ldata->currency_symbol = __UNCONST(monetary->currency_symbol); + ldata->mon_decimal_point = __UNCONST(monetary->mon_decimal_point); + ldata->mon_thousands_sep = __UNCONST(monetary->mon_thousands_sep); + ldata->mon_grouping = __UNCONST(monetary->mon_grouping); + ldata->positive_sign = __UNCONST(monetary->positive_sign); + ldata->negative_sign = __UNCONST(monetary->negative_sign); + + ldata->int_frac_digits = monetary->int_frac_digits; + ldata->frac_digits = monetary->frac_digits; + ldata->p_cs_precedes = monetary->p_cs_precedes; + ldata->p_sep_by_space = monetary->p_sep_by_space; + ldata->n_cs_precedes = monetary->n_cs_precedes; + ldata->n_sep_by_space = monetary->n_sep_by_space; + ldata->p_sign_posn = monetary->p_sign_posn; + ldata->n_sign_posn = monetary->n_sign_posn; + ldata->int_p_cs_precedes = monetary->int_p_cs_precedes; + ldata->int_n_cs_precedes = monetary->int_n_cs_precedes; + ldata->int_p_sep_by_space = monetary-> int_p_sep_by_space; + ldata->int_n_sep_by_space = monetary->int_n_sep_by_space; + ldata->int_p_sign_posn = monetary->int_p_sign_posn; + ldata->int_n_sign_posn = monetary->int_n_sign_posn; + SLIST_INSERT_HEAD(&caches, cache, cache_link); + + loc->cache = cache; + return 0; +} + _locale_set_t _find_category(int category) { @@ -96,13 +167,20 @@ char * __setlocale(int category, const char *name) { _locale_set_t sl; - struct _locale *impl; + locale_t loc; + struct _locale_cache_t *cache; + const char *result; sl = _find_category(category); if (sl == NULL) return NULL; - impl = _current_locale(); - return __UNCONST((*sl)(name, impl)); + cache = malloc(sizeof(*cache)); + if (cache == NULL) + return NULL; + loc = _current_locale(); + result = (*sl)(name, loc); + _setlocale_cache(loc, cache); + return __UNCONST(result); } char * Index: src/lib/libc/locale/setlocale_local.h diff -u src/lib/libc/locale/setlocale_local.h:1.14 src/lib/libc/locale/setlocale_local.h:1.15 --- src/lib/libc/locale/setlocale_local.h:1.14 Tue Aug 20 19:58:30 2013 +++ src/lib/libc/locale/setlocale_local.h Fri Sep 13 13:13:32 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: setlocale_local.h,v 1.14 2013/08/20 19:58:30 joerg Exp $ */ +/* $NetBSD: setlocale_local.h,v 1.15 2013/09/13 13:13:32 joerg Exp $ */ /*- * Copyright (c)2008 Citrus Project, @@ -29,6 +29,9 @@ #ifndef _SETLOCALE_LOCAL_H_ #define _SETLOCALE_LOCAL_H_ +#include <sys/queue.h> +#include <locale.h> + #include "ctype_local.h" #define _LOCALENAME_LEN_MAX 33 @@ -42,11 +45,14 @@ extern const char *_PathLocale; typedef void *_locale_part_t; struct _locale_cache_t { - struct lconv *ldata; + SLIST_ENTRY(_locale_cache_t) cache_link; + const char *monetary_name; + const char *numeric_name; + struct lconv ldata; }; struct _locale { - struct _locale_cache_t *cache; + const struct _locale_cache_t *cache; char query[_LOCALENAME_LEN_MAX * (_LC_LAST - 1)]; const char *part_name[_LC_LAST]; _locale_part_t part_impl[_LC_LAST]; @@ -74,22 +80,19 @@ const char *_citrus_LC_TIME_setlocale( const char * __restrict, struct _locale * __restrict); const char *_citrus_LC_MESSAGES_setlocale( const char * __restrict, struct _locale * __restrict); + +int _setlocale_cache(locale_t, struct _locale_cache_t *); __END_DECLS #ifdef _LIBC extern __dso_protected struct _locale _lc_global_locale; +extern __dso_hidden const struct _locale_cache_t _C_cache; static __inline struct _locale * _current_locale(void) { return &_lc_global_locale; } - -static __inline struct _locale_cache_t * -_current_cache(void) -{ - return _lc_global_locale.cache; -} #endif extern size_t __mb_len_max_runtime;