1/* 2 * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org> 3 * Copyright (c) 1991, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 4. Neither the name of the University nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31#if defined(LIBC_SCCS) && !defined(lint) 32static char sccsid[] = "@(#)localeconv.c 8.1 (Berkeley) 6/4/93"; 33#endif /* LIBC_SCCS and not lint */ 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD: src/lib/libc/locale/localeconv.c,v 1.14 2007/12/12 07:43:23 phantom Exp $"); 36 37#include "xlocale_private.h" 38 39#include <limits.h> 40#include <locale.h> 41 42#include "lmonetary.h" 43#include "lnumeric.h" 44 45#ifdef __APPLE_PR3417676_HACK__ 46/*------------------------------------------------------------------------ 47 * PR-3417676: We need to provide a way to force "C" locale style number 48 * formatting independent of the locale setting. We provide private 49 * routines to get and set a flag that tells localeconv() to either return 50 * a "C" struct lconv, or the one dependent on the actual locale. 51 *------------------------------------------------------------------------*/ 52static char empty[] = ""; 53static char numempty[] = { CHAR_MAX, '\0' }; 54 55/* 56 * Default (C) locale conversion. 57 */ 58static struct lconv _C_lconv = { 59 ".", /* decimal_point */ 60 empty, /* thousands_sep */ 61 numempty, /* grouping */ 62 empty, /* int_curr_symbol */ 63 empty, /* currency_symbol */ 64 empty, /* mon_decimal_point */ 65 empty, /* mon_thousands_sep */ 66 numempty, /* mon_grouping */ 67 empty, /* positive_sign */ 68 empty, /* negative_sign */ 69 CHAR_MAX, /* int_frac_digits */ 70 CHAR_MAX, /* frac_digits */ 71 CHAR_MAX, /* p_cs_precedes */ 72 CHAR_MAX, /* p_sep_by_space */ 73 CHAR_MAX, /* n_cs_precedes */ 74 CHAR_MAX, /* n_sep_by_space */ 75 CHAR_MAX, /* p_sign_posn */ 76 CHAR_MAX, /* n_sign_posn */ 77 CHAR_MAX, /* int_p_cs_precedes */ 78 CHAR_MAX, /* int_n_cs_precedes */ 79 CHAR_MAX, /* int_p_sep_by_space */ 80 CHAR_MAX, /* int_n_sep_by_space */ 81 CHAR_MAX, /* int_p_sign_posn */ 82 CHAR_MAX, /* int_n_sign_posn */ 83}; 84static int _onlyClocaleconv = 0; 85 86int 87__getonlyClocaleconv(void) 88{ 89 return _onlyClocaleconv; 90} 91 92int 93__setonlyClocaleconv(int val) 94{ 95 int prev = _onlyClocaleconv; 96 97 _onlyClocaleconv = val; 98 return prev; 99} 100#endif /* __APPLE_PR3417676_HACK__ */ 101 102/* 103 * The localeconv() function constructs a struct lconv from the current 104 * monetary and numeric locales. 105 * 106 * Because localeconv() may be called many times (especially by library 107 * routines like printf() & strtod()), the approprate members of the 108 * lconv structure are computed only when the monetary or numeric 109 * locale has been changed. 110 */ 111 112/* 113 * Return the current locale conversion. 114 */ 115struct lconv * 116localeconv_l(locale_t loc) 117{ 118 NORMALIZE_LOCALE(loc); 119 120 if (loc->__mlocale_changed) { 121 XL_LOCK(loc); 122 if (loc->__mlocale_changed) { 123 /* LC_MONETARY part */ 124 struct lc_monetary_T * mptr; 125 struct lconv *lc = &loc->__lc_localeconv; 126 127#define M_ASSIGN_STR(NAME) (lc->NAME = (char*)mptr->NAME) 128#define M_ASSIGN_CHAR(NAME) (lc->NAME = mptr->NAME[0]) 129 130 mptr = __get_current_monetary_locale(loc); 131 M_ASSIGN_STR(int_curr_symbol); 132 M_ASSIGN_STR(currency_symbol); 133 M_ASSIGN_STR(mon_decimal_point); 134 M_ASSIGN_STR(mon_thousands_sep); 135 M_ASSIGN_STR(mon_grouping); 136 M_ASSIGN_STR(positive_sign); 137 M_ASSIGN_STR(negative_sign); 138 M_ASSIGN_CHAR(int_frac_digits); 139 M_ASSIGN_CHAR(frac_digits); 140 M_ASSIGN_CHAR(p_cs_precedes); 141 M_ASSIGN_CHAR(p_sep_by_space); 142 M_ASSIGN_CHAR(n_cs_precedes); 143 M_ASSIGN_CHAR(n_sep_by_space); 144 M_ASSIGN_CHAR(p_sign_posn); 145 M_ASSIGN_CHAR(n_sign_posn); 146 M_ASSIGN_CHAR(int_p_cs_precedes); 147 M_ASSIGN_CHAR(int_n_cs_precedes); 148 M_ASSIGN_CHAR(int_p_sep_by_space); 149 M_ASSIGN_CHAR(int_n_sep_by_space); 150 M_ASSIGN_CHAR(int_p_sign_posn); 151 M_ASSIGN_CHAR(int_n_sign_posn); 152 loc->__mlocale_changed = 0; 153 } 154 XL_UNLOCK(loc); 155 } 156 157 if (loc->__nlocale_changed) { 158 XL_LOCK(loc); 159 if (loc->__nlocale_changed) { 160 /* LC_NUMERIC part */ 161 struct lc_numeric_T * nptr; 162 struct lconv *lc = &loc->__lc_localeconv; 163 164#define N_ASSIGN_STR(NAME) (lc->NAME = (char*)nptr->NAME) 165 166 nptr = __get_current_numeric_locale(loc); 167 N_ASSIGN_STR(decimal_point); 168 N_ASSIGN_STR(thousands_sep); 169 N_ASSIGN_STR(grouping); 170 loc->__nlocale_changed = 0; 171 } 172 XL_UNLOCK(loc); 173 } 174 175 return &loc->__lc_localeconv; 176} 177 178/* 179 * Return the current locale conversion. 180 */ 181struct lconv * 182localeconv() 183{ 184#ifdef __APPLE_PR3417676_HACK__ 185 /*-------------------------------------------------------------------- 186 * If _onlyClocaleconv is non-zero, just return __lconv, which is a "C" 187 * struct lconv *. Otherwise, do the normal thing. 188 *--------------------------------------------------------------------*/ 189 if (_onlyClocaleconv) 190 return &_C_lconv; 191#endif /* __APPLE_PR3417676_HACK__ */ 192 return localeconv_l(__current_locale()); 193} 194