Remove the static/global variables from localeconv(3).
- store the cached values inside struct _locale_t (like FreeBSD)
- use flags (member of locale_t) to track changes in lc_monetary or
lc_numeric. Note that currently these categories support only C
locale, so there are no code that change them (as for
__mlocale_changed and __nlocale_changed before).
--
Sebastien Marie
Index: b/lib/libc/locale/localeconv.c
===================================================================
--- a/lib/libc/locale/localeconv.c 2015-07-08 11:56:51.883919979 +0200
+++ b/lib/libc/locale/localeconv.c 2015-07-08 14:49:26.182312619 +0200
@@ -18,8 +18,13 @@
* lconv structure are computed only when the monetary or numeric
* locale has been changed.
*/
-int __mlocale_changed = 1;
-int __nlocale_changed = 1;
+
+/* helpers */
+#define lconvcpy_monetary(_loc, _entry) \
+ (_loc->lconv_cached._entry = _loc->lc_monetary->_entry)
+
+#define lconvcpy_numeric(_loc, _entry) \
+ (_loc->lconv_cached._entry = (char *)_loc->lc_numeric->_entry)
/*
* Return the current locale conversion.
@@ -27,42 +32,43 @@
struct lconv *
localeconv(void)
{
- static struct lconv ret;
- locale_t loc = _current_locale();
+ locale_t loc = _current_locale();
- if (__mlocale_changed) {
/* LC_MONETARY */
- ret.int_curr_symbol = loc->lc_monetary->int_curr_symbol;
- ret.currency_symbol = loc->lc_monetary->currency_symbol;
- ret.mon_decimal_point = loc->lc_monetary->mon_decimal_point;
- ret.mon_thousands_sep = loc->lc_monetary->mon_thousands_sep;
- ret.mon_grouping = loc->lc_monetary->mon_grouping;
- ret.positive_sign = loc->lc_monetary->positive_sign;
- ret.negative_sign = loc->lc_monetary->negative_sign;
- ret.int_frac_digits = loc->lc_monetary->int_frac_digits;
- ret.frac_digits = loc->lc_monetary->frac_digits;
- ret.p_cs_precedes = loc->lc_monetary->p_cs_precedes;
- ret.p_sep_by_space = loc->lc_monetary->p_sep_by_space;
- ret.n_cs_precedes = loc->lc_monetary->n_cs_precedes;
- ret.n_sep_by_space = loc->lc_monetary->n_sep_by_space;
- ret.p_sign_posn = loc->lc_monetary->p_sign_posn;
- ret.n_sign_posn = loc->lc_monetary->n_sign_posn;
- ret.int_p_cs_precedes = loc->lc_monetary->int_p_cs_precedes;
- ret.int_p_sep_by_space = loc->lc_monetary->int_p_sep_by_space;
- ret.int_n_cs_precedes = loc->lc_monetary->int_n_cs_precedes;
- ret.int_n_sep_by_space = loc->lc_monetary->int_n_sep_by_space;
- ret.int_p_sign_posn = loc->lc_monetary->int_p_sign_posn;
- ret.int_n_sign_posn = loc->lc_monetary->int_n_sign_posn;
- __mlocale_changed = 0;
- }
+ if (loc->flags & XLOCALE_MONETARY_CHANGED) {
+ lconvcpy_monetary(loc, int_curr_symbol);
+ lconvcpy_monetary(loc, currency_symbol);
+ lconvcpy_monetary(loc, mon_decimal_point);
+ lconvcpy_monetary(loc, mon_thousands_sep);
+ lconvcpy_monetary(loc, mon_grouping);
+ lconvcpy_monetary(loc, positive_sign);
+ lconvcpy_monetary(loc, negative_sign);
+ lconvcpy_monetary(loc, int_frac_digits);
+ lconvcpy_monetary(loc, frac_digits);
+ lconvcpy_monetary(loc, p_cs_precedes);
+ lconvcpy_monetary(loc, p_sep_by_space);
+ lconvcpy_monetary(loc, n_cs_precedes);
+ lconvcpy_monetary(loc, n_sep_by_space);
+ lconvcpy_monetary(loc, p_sign_posn);
+ lconvcpy_monetary(loc, n_sign_posn);
+ lconvcpy_monetary(loc, int_p_cs_precedes);
+ lconvcpy_monetary(loc, int_p_sep_by_space);
+ lconvcpy_monetary(loc, int_n_cs_precedes);
+ lconvcpy_monetary(loc, int_n_sep_by_space);
+ lconvcpy_monetary(loc, int_p_sign_posn);
+ lconvcpy_monetary(loc, int_n_sign_posn);
+
+ loc->flags &= ~XLOCALE_MONETARY_CHANGED;
+ }
- if (__nlocale_changed) {
/* LC_NUMERIC */
- ret.decimal_point = (char *) loc->lc_numeric->decimal_point;
- ret.thousands_sep = (char *) loc->lc_numeric->thousands_sep;
- ret.grouping = (char *) loc->lc_numeric->grouping;
- __nlocale_changed = 0;
- }
+ if (loc->flags & XLOCALE_NUMERIC_CHANGED) {
+ lconvcpy_numeric(loc, decimal_point);
+ lconvcpy_numeric(loc, thousands_sep);
+ lconvcpy_numeric(loc, grouping);
+
+ loc->flags &= ~XLOCALE_NUMERIC_CHANGED;
+ }
- return (&ret);
+ return (&loc->lconv_cached);
}
Index: b/lib/libc/locale/xlocale.c
===================================================================
--- a/lib/libc/locale/xlocale.c 2015-07-08 11:56:51.883919979 +0200
+++ b/lib/libc/locale/xlocale.c 2015-07-08 14:09:51.275324172 +0200
@@ -25,13 +25,14 @@
* hold the global state
*/
struct _locale_t _lc_global_locale = {
- XLOCALE_INSTALLED,
+ XLOCALE_INSTALLED | XLOCALE_MONETARY_CHANGED | XLOCALE_NUMERIC_CHANGED,
{"C", "C", "C", "C", "C", "C", "C"},
&_DefaultRuneLocale,
&_DefaultMessagesLocale,
&_DefaultMonetaryLocale,
&_DefaultNumericLocale,
- &_DefaultTimeLocale
+ &_DefaultTimeLocale,
+ /* lconv_cached */
};
Index: b/lib/libc/locale/xlocale_private.h
===================================================================
--- a/lib/libc/locale/xlocale_private.h 2015-07-08 11:56:51.883919979 +0200
+++ b/lib/libc/locale/xlocale_private.h 2015-07-08 13:57:41.989861830 +0200
@@ -31,9 +31,13 @@
const _MonetaryLocale *lc_monetary;
const _NumericLocale *lc_numeric;
const _TimeLocale *lc_time;
+
+ struct lconv lconv_cached;
};
#define XLOCALE_INSTALLED (1 << 0)
+#define XLOCALE_MONETARY_CHANGED (1 << 1)
+#define XLOCALE_NUMERIC_CHANGED (1 << 2)
#define xlocale_is_installed(flags) (flags & XLOCALE_INSTALLED)