Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | --- 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 <sys/cdefs.h> __FBSDID("$FreeBSD: src/lib/libc/locale/localeconv.c,v 1.13 2003/06/26 10:46:16 phantom Exp $"); +#include "xlocale_private.h" + +#include <limits.h> #include <locale.h> #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()); } |