1d915a14eSPedro F. Giffuni /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3d915a14eSPedro F. Giffuni *
474f2b975SAlexey Zelkin * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
590423eceSAlexey Zelkin * All rights reserved.
690423eceSAlexey Zelkin *
73c87aa1dSDavid Chisnall * Copyright (c) 2011 The FreeBSD Foundation
85b5fa75aSEd Maste *
93c87aa1dSDavid Chisnall * Portions of this software were developed by David Chisnall
103c87aa1dSDavid Chisnall * under sponsorship from the FreeBSD Foundation.
113c87aa1dSDavid Chisnall *
1290423eceSAlexey Zelkin * Redistribution and use in source and binary forms, with or without
1390423eceSAlexey Zelkin * modification, are permitted provided that the following conditions
1490423eceSAlexey Zelkin * are met:
1590423eceSAlexey Zelkin * 1. Redistributions of source code must retain the above copyright
1690423eceSAlexey Zelkin * notice, this list of conditions and the following disclaimer.
1790423eceSAlexey Zelkin * 2. Redistributions in binary form must reproduce the above copyright
1890423eceSAlexey Zelkin * notice, this list of conditions and the following disclaimer in the
1990423eceSAlexey Zelkin * documentation and/or other materials provided with the distribution.
2090423eceSAlexey Zelkin *
2190423eceSAlexey Zelkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2290423eceSAlexey Zelkin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2390423eceSAlexey Zelkin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2490423eceSAlexey Zelkin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2590423eceSAlexey Zelkin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2690423eceSAlexey Zelkin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2790423eceSAlexey Zelkin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2890423eceSAlexey Zelkin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2990423eceSAlexey Zelkin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3090423eceSAlexey Zelkin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3190423eceSAlexey Zelkin * SUCH DAMAGE.
3290423eceSAlexey Zelkin */
3390423eceSAlexey Zelkin
341bd7723dSAlexey Zelkin #include <limits.h>
35f4da1a75STim J. Robbins #include <stddef.h>
36831e8f61SAndrey A. Chernov #include <stdlib.h>
37683fe113SAlexey Zelkin
3890423eceSAlexey Zelkin #include "ldpart.h"
39683fe113SAlexey Zelkin #include "lmonetary.h"
4090423eceSAlexey Zelkin
411bd7723dSAlexey Zelkin extern const char * __fix_locale_grouping_str(const char *);
4290423eceSAlexey Zelkin
438a093dadSAndrey A. Chernov #define LCMONETARY_SIZE_FULL (sizeof(struct lc_monetary_T) / sizeof(char *))
448a093dadSAndrey A. Chernov #define LCMONETARY_SIZE_MIN \
458a093dadSAndrey A. Chernov (offsetof(struct lc_monetary_T, int_p_cs_precedes) / \
468a093dadSAndrey A. Chernov sizeof(char *))
4790423eceSAlexey Zelkin
4890423eceSAlexey Zelkin static char empty[] = "";
491bd7723dSAlexey Zelkin static char numempty[] = { CHAR_MAX, '\0'};
5090423eceSAlexey Zelkin
5190423eceSAlexey Zelkin static const struct lc_monetary_T _C_monetary_locale = {
5290423eceSAlexey Zelkin empty, /* int_curr_symbol */
5390423eceSAlexey Zelkin empty, /* currency_symbol */
5454e3bc25SAndrey A. Chernov empty, /* mon_decimal_point */
5590423eceSAlexey Zelkin empty, /* mon_thousands_sep */
5690423eceSAlexey Zelkin numempty, /* mon_grouping */
5790423eceSAlexey Zelkin empty, /* positive_sign */
5890423eceSAlexey Zelkin empty, /* negative_sign */
5990423eceSAlexey Zelkin numempty, /* int_frac_digits */
6090423eceSAlexey Zelkin numempty, /* frac_digits */
6190423eceSAlexey Zelkin numempty, /* p_cs_precedes */
6290423eceSAlexey Zelkin numempty, /* p_sep_by_space */
6390423eceSAlexey Zelkin numempty, /* n_cs_precedes */
6490423eceSAlexey Zelkin numempty, /* n_sep_by_space */
6590423eceSAlexey Zelkin numempty, /* p_sign_posn */
66f4da1a75STim J. Robbins numempty, /* n_sign_posn */
67f4da1a75STim J. Robbins numempty, /* int_p_cs_precedes */
68f4da1a75STim J. Robbins numempty, /* int_n_cs_precedes */
69f4da1a75STim J. Robbins numempty, /* int_p_sep_by_space */
70f4da1a75STim J. Robbins numempty, /* int_n_sep_by_space */
71f4da1a75STim J. Robbins numempty, /* int_p_sign_posn */
72f4da1a75STim J. Robbins numempty /* int_n_sign_posn */
7390423eceSAlexey Zelkin };
7490423eceSAlexey Zelkin
753c87aa1dSDavid Chisnall struct xlocale_monetary __xlocale_global_monetary;
7690423eceSAlexey Zelkin
77831e8f61SAndrey A. Chernov static char
cnv(const char * str)78ecc4c620SAndrey A. Chernov cnv(const char *str)
79ecc4c620SAndrey A. Chernov {
80831e8f61SAndrey A. Chernov int i = strtol(str, NULL, 10);
81ecc4c620SAndrey A. Chernov
82831e8f61SAndrey A. Chernov if (i == -1)
83831e8f61SAndrey A. Chernov i = CHAR_MAX;
84ecc4c620SAndrey A. Chernov return ((char)i);
85831e8f61SAndrey A. Chernov }
86831e8f61SAndrey A. Chernov
873c87aa1dSDavid Chisnall static void
destruct_monetary(void * v)883c87aa1dSDavid Chisnall destruct_monetary(void *v)
893c87aa1dSDavid Chisnall {
903c87aa1dSDavid Chisnall struct xlocale_monetary *l = v;
913c87aa1dSDavid Chisnall if (l->buffer)
923c87aa1dSDavid Chisnall free(l->buffer);
933c87aa1dSDavid Chisnall free(l);
943c87aa1dSDavid Chisnall }
953c87aa1dSDavid Chisnall
963c87aa1dSDavid Chisnall static int
monetary_load_locale_l(struct xlocale_monetary * loc,int * using_locale,int * changed,const char * name)973c87aa1dSDavid Chisnall monetary_load_locale_l(struct xlocale_monetary *loc, int *using_locale,
983c87aa1dSDavid Chisnall int *changed, const char *name)
99ecc4c620SAndrey A. Chernov {
10090423eceSAlexey Zelkin int ret;
1013c87aa1dSDavid Chisnall struct lc_monetary_T *l = &loc->locale;
102ecc4c620SAndrey A. Chernov
1033c87aa1dSDavid Chisnall ret = __part_load_locale(name, using_locale,
1043c87aa1dSDavid Chisnall &loc->buffer, "LC_MONETARY",
1058a093dadSAndrey A. Chernov LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN,
1063c87aa1dSDavid Chisnall (const char **)l);
10776692b80SAndrey A. Chernov if (ret == _LDP_LOADED) {
1083c87aa1dSDavid Chisnall l->mon_grouping =
1093c87aa1dSDavid Chisnall __fix_locale_grouping_str(l->mon_grouping);
110831e8f61SAndrey A. Chernov
1113c87aa1dSDavid Chisnall #define M_ASSIGN_CHAR(NAME) (((char *)l->NAME)[0] = \
1123c87aa1dSDavid Chisnall cnv(l->NAME))
113831e8f61SAndrey A. Chernov
114831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(int_frac_digits);
115831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(frac_digits);
116831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(p_cs_precedes);
117831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(p_sep_by_space);
118831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(n_cs_precedes);
119831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(n_sep_by_space);
120831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(p_sign_posn);
121831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(n_sign_posn);
122f4da1a75STim J. Robbins
123f4da1a75STim J. Robbins /*
124f4da1a75STim J. Robbins * The six additional C99 international monetary formatting
125f4da1a75STim J. Robbins * parameters default to the national parameters when
126683fe113SAlexey Zelkin * reading FreeBSD LC_MONETARY data files.
127f4da1a75STim J. Robbins */
128f4da1a75STim J. Robbins #define M_ASSIGN_ICHAR(NAME) \
129f4da1a75STim J. Robbins do { \
1303c87aa1dSDavid Chisnall if (l->int_##NAME == NULL) \
1313c87aa1dSDavid Chisnall l->int_##NAME = \
1323c87aa1dSDavid Chisnall l->NAME; \
133f4da1a75STim J. Robbins else \
134f4da1a75STim J. Robbins M_ASSIGN_CHAR(int_##NAME); \
135f4da1a75STim J. Robbins } while (0)
136f4da1a75STim J. Robbins
137f4da1a75STim J. Robbins M_ASSIGN_ICHAR(p_cs_precedes);
138f4da1a75STim J. Robbins M_ASSIGN_ICHAR(n_cs_precedes);
139f4da1a75STim J. Robbins M_ASSIGN_ICHAR(p_sep_by_space);
140f4da1a75STim J. Robbins M_ASSIGN_ICHAR(n_sep_by_space);
141f4da1a75STim J. Robbins M_ASSIGN_ICHAR(p_sign_posn);
142f4da1a75STim J. Robbins M_ASSIGN_ICHAR(n_sign_posn);
143831e8f61SAndrey A. Chernov }
1447eb138a9SMark Johnston if (ret != _LDP_ERROR)
1457eb138a9SMark Johnston atomic_store_rel_int(changed, 1);
146ecc4c620SAndrey A. Chernov return (ret);
14790423eceSAlexey Zelkin }
1480fed1e6fSKonstantin Belousov
1493c87aa1dSDavid Chisnall int
__monetary_load_locale(const char * name)1503c87aa1dSDavid Chisnall __monetary_load_locale(const char *name)
1513c87aa1dSDavid Chisnall {
1520fed1e6fSKonstantin Belousov return (monetary_load_locale_l(&__xlocale_global_monetary,
1533c87aa1dSDavid Chisnall &__xlocale_global_locale.using_monetary_locale,
1540fed1e6fSKonstantin Belousov &__xlocale_global_locale.monetary_locale_changed, name));
1553c87aa1dSDavid Chisnall }
1563c87aa1dSDavid Chisnall
1570fed1e6fSKonstantin Belousov void *
__monetary_load(const char * name,locale_t l)1580fed1e6fSKonstantin Belousov __monetary_load(const char *name, locale_t l)
1590fed1e6fSKonstantin Belousov {
1600fed1e6fSKonstantin Belousov struct xlocale_monetary *new = calloc(sizeof(struct xlocale_monetary),
1610fed1e6fSKonstantin Belousov 1);
1624d3b84f6SKonstantin Belousov if (new == NULL)
1634d3b84f6SKonstantin Belousov return (NULL);
1640fed1e6fSKonstantin Belousov new->header.header.destructor = destruct_monetary;
1650fed1e6fSKonstantin Belousov if (monetary_load_locale_l(new, &l->using_monetary_locale,
1660fed1e6fSKonstantin Belousov &l->monetary_locale_changed, name) == _LDP_ERROR) {
1670fed1e6fSKonstantin Belousov xlocale_release(new);
1680fed1e6fSKonstantin Belousov return (NULL);
1690fed1e6fSKonstantin Belousov }
1700fed1e6fSKonstantin Belousov return (new);
1710fed1e6fSKonstantin Belousov }
17290423eceSAlexey Zelkin
17390423eceSAlexey Zelkin struct lc_monetary_T *
__get_current_monetary_locale(locale_t loc)1743c87aa1dSDavid Chisnall __get_current_monetary_locale(locale_t loc)
175ecc4c620SAndrey A. Chernov {
1760fed1e6fSKonstantin Belousov return (loc->using_monetary_locale ?
1770fed1e6fSKonstantin Belousov &((struct xlocale_monetary*)loc->components[XLC_MONETARY])->locale :
1780fed1e6fSKonstantin Belousov (struct lc_monetary_T *)&_C_monetary_locale);
17990423eceSAlexey Zelkin }
18090423eceSAlexey Zelkin
18190423eceSAlexey Zelkin #ifdef LOCALE_DEBUG
18290423eceSAlexey Zelkin void
monetdebug(void)1830fed1e6fSKonstantin Belousov monetdebug(void) {
18490423eceSAlexey Zelkin printf( "int_curr_symbol = %s\n"
18590423eceSAlexey Zelkin "currency_symbol = %s\n"
18690423eceSAlexey Zelkin "mon_decimal_point = %s\n"
18790423eceSAlexey Zelkin "mon_thousands_sep = %s\n"
18890423eceSAlexey Zelkin "mon_grouping = %s\n"
18990423eceSAlexey Zelkin "positive_sign = %s\n"
19090423eceSAlexey Zelkin "negative_sign = %s\n"
191831e8f61SAndrey A. Chernov "int_frac_digits = %d\n"
192831e8f61SAndrey A. Chernov "frac_digits = %d\n"
193831e8f61SAndrey A. Chernov "p_cs_precedes = %d\n"
194831e8f61SAndrey A. Chernov "p_sep_by_space = %d\n"
195831e8f61SAndrey A. Chernov "n_cs_precedes = %d\n"
196831e8f61SAndrey A. Chernov "n_sep_by_space = %d\n"
197831e8f61SAndrey A. Chernov "p_sign_posn = %d\n"
1989908eab8SPedro F. Giffuni "n_sign_posn = %d\n"
199683fe113SAlexey Zelkin "int_p_cs_precedes = %d\n"
200683fe113SAlexey Zelkin "int_p_sep_by_space = %d\n"
201683fe113SAlexey Zelkin "int_n_cs_precedes = %d\n"
202683fe113SAlexey Zelkin "int_n_sep_by_space = %d\n"
203683fe113SAlexey Zelkin "int_p_sign_posn = %d\n"
204683fe113SAlexey Zelkin "int_n_sign_posn = %d\n",
20590423eceSAlexey Zelkin _monetary_locale.int_curr_symbol,
20690423eceSAlexey Zelkin _monetary_locale.currency_symbol,
20790423eceSAlexey Zelkin _monetary_locale.mon_decimal_point,
20890423eceSAlexey Zelkin _monetary_locale.mon_thousands_sep,
20990423eceSAlexey Zelkin _monetary_locale.mon_grouping,
21090423eceSAlexey Zelkin _monetary_locale.positive_sign,
21190423eceSAlexey Zelkin _monetary_locale.negative_sign,
212831e8f61SAndrey A. Chernov _monetary_locale.int_frac_digits[0],
213831e8f61SAndrey A. Chernov _monetary_locale.frac_digits[0],
214831e8f61SAndrey A. Chernov _monetary_locale.p_cs_precedes[0],
215831e8f61SAndrey A. Chernov _monetary_locale.p_sep_by_space[0],
216831e8f61SAndrey A. Chernov _monetary_locale.n_cs_precedes[0],
217831e8f61SAndrey A. Chernov _monetary_locale.n_sep_by_space[0],
218831e8f61SAndrey A. Chernov _monetary_locale.p_sign_posn[0],
219683fe113SAlexey Zelkin _monetary_locale.n_sign_posn[0],
220683fe113SAlexey Zelkin _monetary_locale.int_p_cs_precedes[0],
221683fe113SAlexey Zelkin _monetary_locale.int_p_sep_by_space[0],
222683fe113SAlexey Zelkin _monetary_locale.int_n_cs_precedes[0],
223683fe113SAlexey Zelkin _monetary_locale.int_n_sep_by_space[0],
224683fe113SAlexey Zelkin _monetary_locale.int_p_sign_posn[0],
225683fe113SAlexey Zelkin _monetary_locale.int_n_sign_posn[0]
22690423eceSAlexey Zelkin );
22790423eceSAlexey Zelkin }
22890423eceSAlexey Zelkin #endif /* LOCALE_DEBUG */
229