--- localeconv.c.orig 2004-11-25 11:38:18.000000000 -0800 +++ localeconv.c 2005-02-17 23:35:43.000000000 -0800 @@ -38,11 +38,69 @@ #include __FBSDID("$FreeBSD: src/lib/libc/locale/localeconv.c,v 1.13 2003/06/26 10:46:16 phantom Exp $"); +#include "xlocale_private.h" + +#include #include #include "lmonetary.h" #include "lnumeric.h" +/*------------------------------------------------------------------------ + * PR-3417676: We need to provide a way to force "C" locale style number + * formatting independent of the locale setting. We provide private + * routines to get and set a flag that tells localeconv() to either return + * a "C" struct lconv, or the one dependent on the actual locale. + *------------------------------------------------------------------------*/ +static char empty[] = ""; +static char numempty[] = { CHAR_MAX, '\0' }; + +/* + * Default (C) locale conversion. + */ +static struct lconv _C_lconv = { + ".", /* decimal_point */ + empty, /* thousands_sep */ + numempty, /* grouping */ + empty, /* int_curr_symbol */ + empty, /* currency_symbol */ + empty, /* mon_decimal_point */ + empty, /* mon_thousands_sep */ + numempty, /* mon_grouping */ + empty, /* positive_sign */ + empty, /* negative_sign */ + CHAR_MAX, /* int_frac_digits */ + CHAR_MAX, /* frac_digits */ + CHAR_MAX, /* p_cs_precedes */ + CHAR_MAX, /* p_sep_by_space */ + CHAR_MAX, /* n_cs_precedes */ + CHAR_MAX, /* n_sep_by_space */ + CHAR_MAX, /* p_sign_posn */ + CHAR_MAX, /* n_sign_posn */ + CHAR_MAX, /* int_p_cs_precedes */ + CHAR_MAX, /* int_n_cs_precedes */ + CHAR_MAX, /* int_p_sep_by_space */ + CHAR_MAX, /* int_n_sep_by_space */ + CHAR_MAX, /* int_p_sign_posn */ + CHAR_MAX, /* int_n_sign_posn */ +}; +static int _onlyClocaleconv = 0; + +int +__getonlyClocaleconv(void) +{ + return _onlyClocaleconv; +} + +int +__setonlyClocaleconv(int val) +{ + int prev = _onlyClocaleconv; + + _onlyClocaleconv = val; + return prev; +} + /* * The localeconv() function constructs a struct lconv from the current * monetary and numeric locales. @@ -52,25 +110,37 @@ * lconv structure are computed only when the monetary or numeric * locale has been changed. */ -int __mlocale_changed = 1; -int __nlocale_changed = 1; /* * Return the current locale conversion. */ struct lconv * -localeconv() +localeconv_l(locale_t loc) { - static struct lconv ret; + struct __xlocale_st_localeconv *lc; + + NORMALIZE_LOCALE(loc); + if (loc->__lc_localeconv && !loc->__mlocale_changed && !loc->__nlocale_changed) + return &loc->__lc_localeconv->__ret; + + lc = (struct __xlocale_st_localeconv *)malloc(sizeof(struct __xlocale_st_localeconv)); + lc->__refcount = 1; + lc->__free_extra = NULL; + if (loc->__lc_localeconv) + lc->__ret = loc->__lc_localeconv->__ret; + else { + loc->__mlocale_changed = 1; + loc->__nlocale_changed = 1; + } - if (__mlocale_changed) { + if (loc->__mlocale_changed) { /* LC_MONETARY part */ struct lc_monetary_T * mptr; -#define M_ASSIGN_STR(NAME) (ret.NAME = (char*)mptr->NAME) -#define M_ASSIGN_CHAR(NAME) (ret.NAME = mptr->NAME[0]) +#define M_ASSIGN_STR(NAME) (lc->__ret.NAME = (char*)mptr->NAME) +#define M_ASSIGN_CHAR(NAME) (lc->__ret.NAME = mptr->NAME[0]) - mptr = __get_current_monetary_locale(); + mptr = __get_current_monetary_locale(loc); M_ASSIGN_STR(int_curr_symbol); M_ASSIGN_STR(currency_symbol); M_ASSIGN_STR(mon_decimal_point); @@ -92,21 +162,39 @@ M_ASSIGN_CHAR(int_n_sep_by_space); M_ASSIGN_CHAR(int_p_sign_posn); M_ASSIGN_CHAR(int_n_sign_posn); - __mlocale_changed = 0; + loc->__mlocale_changed = 0; } - if (__nlocale_changed) { + if (loc->__nlocale_changed) { /* LC_NUMERIC part */ struct lc_numeric_T * nptr; -#define N_ASSIGN_STR(NAME) (ret.NAME = (char*)nptr->NAME) +#define N_ASSIGN_STR(NAME) (lc->__ret.NAME = (char*)nptr->NAME) - nptr = __get_current_numeric_locale(); + nptr = __get_current_numeric_locale(loc); N_ASSIGN_STR(decimal_point); N_ASSIGN_STR(thousands_sep); N_ASSIGN_STR(grouping); - __nlocale_changed = 0; + loc->__nlocale_changed = 0; } - return (&ret); + XL_RELEASE(loc->__lc_localeconv); + loc->__lc_localeconv = lc; + + return (&lc->__ret); +} + +/* + * Return the current locale conversion. + */ +struct lconv * +localeconv() +{ + /*-------------------------------------------------------------------- + * If _onlyClocaleconv is non-zero, just return __lconv, which is a "C" + * struct lconv *. Otherwise, do the normal thing. + *--------------------------------------------------------------------*/ + if (_onlyClocaleconv) + return &_C_lconv; + return localeconv_l(__current_locale()); }