172165Sphantom/*
287658Sphantom * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
372165Sphantom * All rights reserved.
472165Sphantom *
5227753Stheraven * Copyright (c) 2011 The FreeBSD Foundation
6227753Stheraven * All rights reserved.
7227753Stheraven * Portions of this software were developed by David Chisnall
8227753Stheraven * under sponsorship from the FreeBSD Foundation.
9227753Stheraven *
1072165Sphantom * Redistribution and use in source and binary forms, with or without
1172165Sphantom * modification, are permitted provided that the following conditions
1272165Sphantom * are met:
1372165Sphantom * 1. Redistributions of source code must retain the above copyright
1472165Sphantom *    notice, this list of conditions and the following disclaimer.
1572165Sphantom * 2. Redistributions in binary form must reproduce the above copyright
1672165Sphantom *    notice, this list of conditions and the following disclaimer in the
1772165Sphantom *    documentation and/or other materials provided with the distribution.
1872165Sphantom *
1972165Sphantom * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2072165Sphantom * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2172165Sphantom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2272165Sphantom * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2372165Sphantom * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2472165Sphantom * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2572165Sphantom * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2672165Sphantom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2772165Sphantom * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2872165Sphantom * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2972165Sphantom * SUCH DAMAGE.
3072165Sphantom */
3172165Sphantom
3292986Sobrien#include <sys/cdefs.h>
3392986Sobrien__FBSDID("$FreeBSD: releng/10.3/lib/libc/locale/lmonetary.c 227753 2011-11-20 14:45:42Z theraven $");
3492986Sobrien
3572321Sphantom#include <limits.h>
36104711Stjr#include <stddef.h>
3789907Sache#include <stdlib.h>
38116875Sphantom
39116875Sphantom#include "ldpart.h"
4072165Sphantom#include "lmonetary.h"
4172165Sphantom
4272321Sphantomextern const char * __fix_locale_grouping_str(const char *);
4372165Sphantom
44104982Sache#define LCMONETARY_SIZE_FULL (sizeof(struct lc_monetary_T) / sizeof(char *))
45104982Sache#define LCMONETARY_SIZE_MIN \
46104982Sache		(offsetof(struct lc_monetary_T, int_p_cs_precedes) / \
47104982Sache		    sizeof(char *))
4872165Sphantom
4972165Sphantomstatic char	empty[] = "";
5087658Sphantomstatic char	numempty[] = { CHAR_MAX, '\0'};
5172165Sphantom
5272165Sphantomstatic const struct lc_monetary_T _C_monetary_locale = {
5387658Sphantom	empty,		/* int_curr_symbol */
5487658Sphantom	empty,		/* currency_symbol */
5587658Sphantom	empty,		/* mon_decimal_point */
5687658Sphantom	empty,		/* mon_thousands_sep */
5787658Sphantom	numempty,	/* mon_grouping */
5887658Sphantom	empty,		/* positive_sign */
5987658Sphantom	empty,		/* negative_sign */
6087658Sphantom	numempty,	/* int_frac_digits */
6187658Sphantom	numempty,	/* frac_digits */
6287658Sphantom	numempty,	/* p_cs_precedes */
6387658Sphantom	numempty,	/* p_sep_by_space */
6487658Sphantom	numempty,	/* n_cs_precedes */
6587658Sphantom	numempty,	/* n_sep_by_space */
6687658Sphantom	numempty,	/* p_sign_posn */
67104711Stjr	numempty,	/* n_sign_posn */
68104711Stjr	numempty,	/* int_p_cs_precedes */
69104711Stjr	numempty,	/* int_n_cs_precedes */
70104711Stjr	numempty,	/* int_p_sep_by_space */
71104711Stjr	numempty,	/* int_n_sep_by_space */
72104711Stjr	numempty,	/* int_p_sign_posn */
73104711Stjr	numempty	/* int_n_sign_posn */
7472165Sphantom};
7572165Sphantom
76227753Stheravenstruct xlocale_monetary __xlocale_global_monetary;
7772165Sphantom
7889907Sachestatic char
79101498Sachecnv(const char *str)
80101470Sache{
8189907Sache	int i = strtol(str, NULL, 10);
82101470Sache
8389907Sache	if (i == -1)
8489907Sache		i = CHAR_MAX;
85101470Sache	return ((char)i);
8689907Sache}
8789907Sache
88227753Stheravenstatic void
89227753Stheravendestruct_monetary(void *v)
90101470Sache{
91227753Stheraven	struct xlocale_monetary *l = v;
92227753Stheraven	if (l->buffer)
93227753Stheraven		free(l->buffer);
94227753Stheraven	free(l);
95227753Stheraven}
96227753Stheraven
97227753Stheravenstatic int
98227753Stheravenmonetary_load_locale_l(struct xlocale_monetary *loc, int *using_locale,
99227753Stheraven		int *changed, const char *name)
100227753Stheraven{
101101470Sache	int ret;
102227753Stheraven	struct lc_monetary_T *l = &loc->locale;
10372165Sphantom
104227753Stheraven	ret = __part_load_locale(name, using_locale,
105227753Stheraven		&loc->buffer, "LC_MONETARY",
106104982Sache		LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN,
107227753Stheraven		(const char **)l);
108101498Sache	if (ret != _LDP_ERROR)
109227753Stheraven		*changed = 1;
110101498Sache	if (ret == _LDP_LOADED) {
111227753Stheraven		l->mon_grouping =
112227753Stheraven		     __fix_locale_grouping_str(l->mon_grouping);
11389907Sache
114227753Stheraven#define M_ASSIGN_CHAR(NAME) (((char *)l->NAME)[0] = \
115227753Stheraven			     cnv(l->NAME))
11689907Sache
11789907Sache		M_ASSIGN_CHAR(int_frac_digits);
11889907Sache		M_ASSIGN_CHAR(frac_digits);
11989907Sache		M_ASSIGN_CHAR(p_cs_precedes);
12089907Sache		M_ASSIGN_CHAR(p_sep_by_space);
12189907Sache		M_ASSIGN_CHAR(n_cs_precedes);
12289907Sache		M_ASSIGN_CHAR(n_sep_by_space);
12389907Sache		M_ASSIGN_CHAR(p_sign_posn);
12489907Sache		M_ASSIGN_CHAR(n_sign_posn);
125104711Stjr
126104711Stjr		/*
127104711Stjr		 * The six additional C99 international monetary formatting
128104711Stjr		 * parameters default to the national parameters when
129116875Sphantom		 * reading FreeBSD LC_MONETARY data files.
130104711Stjr		 */
131104711Stjr#define	M_ASSIGN_ICHAR(NAME)						\
132104711Stjr		do {							\
133227753Stheraven			if (l->int_##NAME == NULL)	\
134227753Stheraven				l->int_##NAME =		\
135227753Stheraven				    l->NAME;		\
136104711Stjr			else						\
137104711Stjr				M_ASSIGN_CHAR(int_##NAME);		\
138104711Stjr		} while (0)
139104711Stjr
140104711Stjr		M_ASSIGN_ICHAR(p_cs_precedes);
141104711Stjr		M_ASSIGN_ICHAR(n_cs_precedes);
142104711Stjr		M_ASSIGN_ICHAR(p_sep_by_space);
143104711Stjr		M_ASSIGN_ICHAR(n_sep_by_space);
144104711Stjr		M_ASSIGN_ICHAR(p_sign_posn);
145104711Stjr		M_ASSIGN_ICHAR(n_sign_posn);
14689907Sache	}
147101470Sache	return (ret);
14872165Sphantom}
149227753Stheravenint
150227753Stheraven__monetary_load_locale(const char *name)
151227753Stheraven{
152227753Stheraven	return monetary_load_locale_l(&__xlocale_global_monetary,
153227753Stheraven			&__xlocale_global_locale.using_monetary_locale,
154227753Stheraven			&__xlocale_global_locale.monetary_locale_changed, name);
155227753Stheraven}
156227753Stheravenvoid* __monetary_load(const char *name, locale_t l)
157227753Stheraven{
158227753Stheraven	struct xlocale_monetary *new = calloc(sizeof(struct xlocale_monetary), 1);
159227753Stheraven	new->header.header.destructor = destruct_monetary;
160227753Stheraven	if (monetary_load_locale_l(new, &l->using_monetary_locale,
161227753Stheraven				&l->monetary_locale_changed, name) == _LDP_ERROR)
162227753Stheraven	{
163227753Stheraven		xlocale_release(new);
164227753Stheraven		return NULL;
165227753Stheraven	}
166227753Stheraven	return new;
167227753Stheraven}
16872165Sphantom
169227753Stheraven
17072165Sphantomstruct lc_monetary_T *
171227753Stheraven__get_current_monetary_locale(locale_t loc)
172101470Sache{
173227753Stheraven	return (loc->using_monetary_locale
174227753Stheraven		? &((struct xlocale_monetary*)loc->components[XLC_MONETARY])->locale
17572165Sphantom		: (struct lc_monetary_T *)&_C_monetary_locale);
17672165Sphantom}
17772165Sphantom
17872165Sphantom#ifdef LOCALE_DEBUG
17972165Sphantomvoid
18072165Sphantommonetdebug() {
18172165Sphantomprintf(	"int_curr_symbol = %s\n"
18272165Sphantom	"currency_symbol = %s\n"
18372165Sphantom	"mon_decimal_point = %s\n"
18472165Sphantom	"mon_thousands_sep = %s\n"
18572165Sphantom	"mon_grouping = %s\n"
18672165Sphantom	"positive_sign = %s\n"
18772165Sphantom	"negative_sign = %s\n"
18889907Sache	"int_frac_digits = %d\n"
18989907Sache	"frac_digits = %d\n"
19089907Sache	"p_cs_precedes = %d\n"
19189907Sache	"p_sep_by_space = %d\n"
19289907Sache	"n_cs_precedes = %d\n"
19389907Sache	"n_sep_by_space = %d\n"
19489907Sache	"p_sign_posn = %d\n"
19589907Sache	"n_sign_posn = %d\n",
196116875Sphantom	"int_p_cs_precedes = %d\n"
197116875Sphantom	"int_p_sep_by_space = %d\n"
198116875Sphantom	"int_n_cs_precedes = %d\n"
199116875Sphantom	"int_n_sep_by_space = %d\n"
200116875Sphantom	"int_p_sign_posn = %d\n"
201116875Sphantom	"int_n_sign_posn = %d\n",
20272165Sphantom	_monetary_locale.int_curr_symbol,
20372165Sphantom	_monetary_locale.currency_symbol,
20472165Sphantom	_monetary_locale.mon_decimal_point,
20572165Sphantom	_monetary_locale.mon_thousands_sep,
20672165Sphantom	_monetary_locale.mon_grouping,
20772165Sphantom	_monetary_locale.positive_sign,
20872165Sphantom	_monetary_locale.negative_sign,
20989907Sache	_monetary_locale.int_frac_digits[0],
21089907Sache	_monetary_locale.frac_digits[0],
21189907Sache	_monetary_locale.p_cs_precedes[0],
21289907Sache	_monetary_locale.p_sep_by_space[0],
21389907Sache	_monetary_locale.n_cs_precedes[0],
21489907Sache	_monetary_locale.n_sep_by_space[0],
21589907Sache	_monetary_locale.p_sign_posn[0],
216116875Sphantom	_monetary_locale.n_sign_posn[0],
217116875Sphantom	_monetary_locale.int_p_cs_precedes[0],
218116875Sphantom	_monetary_locale.int_p_sep_by_space[0],
219116875Sphantom	_monetary_locale.int_n_cs_precedes[0],
220116875Sphantom	_monetary_locale.int_n_sep_by_space[0],
221116875Sphantom	_monetary_locale.int_p_sign_posn[0],
222116875Sphantom	_monetary_locale.int_n_sign_posn[0]
22372165Sphantom);
22472165Sphantom}
22572165Sphantom#endif /* LOCALE_DEBUG */
226