172165Sphantom/*
287658Sphantom * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
372165Sphantom * All rights reserved.
472165Sphantom *
5235785Stheraven * Copyright (c) 2011 The FreeBSD Foundation
6235785Stheraven * All rights reserved.
7235785Stheraven * Portions of this software were developed by David Chisnall
8235785Stheraven * under sponsorship from the FreeBSD Foundation.
9235785Stheraven *
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$");
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
76235785Stheravenstruct 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
88235785Stheravenstatic void
89235785Stheravendestruct_monetary(void *v)
90101470Sache{
91235785Stheraven	struct xlocale_monetary *l = v;
92235785Stheraven	if (l->buffer)
93235785Stheraven		free(l->buffer);
94235785Stheraven	free(l);
95235785Stheraven}
96235785Stheraven
97235785Stheravenstatic int
98235785Stheravenmonetary_load_locale_l(struct xlocale_monetary *loc, int *using_locale,
99235785Stheraven		int *changed, const char *name)
100235785Stheraven{
101101470Sache	int ret;
102235785Stheraven	struct lc_monetary_T *l = &loc->locale;
10372165Sphantom
104235785Stheraven	ret = __part_load_locale(name, using_locale,
105235785Stheraven		&loc->buffer, "LC_MONETARY",
106104982Sache		LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN,
107235785Stheraven		(const char **)l);
108101498Sache	if (ret != _LDP_ERROR)
109235785Stheraven		*changed = 1;
110101498Sache	if (ret == _LDP_LOADED) {
111235785Stheraven		l->mon_grouping =
112235785Stheraven		     __fix_locale_grouping_str(l->mon_grouping);
11389907Sache
114235785Stheraven#define M_ASSIGN_CHAR(NAME) (((char *)l->NAME)[0] = \
115235785Stheraven			     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 {							\
133235785Stheraven			if (l->int_##NAME == NULL)	\
134235785Stheraven				l->int_##NAME =		\
135235785Stheraven				    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}
149235785Stheravenint
150235785Stheraven__monetary_load_locale(const char *name)
151235785Stheraven{
152235785Stheraven	return monetary_load_locale_l(&__xlocale_global_monetary,
153235785Stheraven			&__xlocale_global_locale.using_monetary_locale,
154235785Stheraven			&__xlocale_global_locale.monetary_locale_changed, name);
155235785Stheraven}
156235785Stheravenvoid* __monetary_load(const char *name, locale_t l)
157235785Stheraven{
158235785Stheraven	struct xlocale_monetary *new = calloc(sizeof(struct xlocale_monetary), 1);
159235785Stheraven	new->header.header.destructor = destruct_monetary;
160235785Stheraven	if (monetary_load_locale_l(new, &l->using_monetary_locale,
161235785Stheraven				&l->monetary_locale_changed, name) == _LDP_ERROR)
162235785Stheraven	{
163235785Stheraven		xlocale_release(new);
164235785Stheraven		return NULL;
165235785Stheraven	}
166235785Stheraven	return new;
167235785Stheraven}
16872165Sphantom
169235785Stheraven
17072165Sphantomstruct lc_monetary_T *
171235785Stheraven__get_current_monetary_locale(locale_t loc)
172101470Sache{
173235785Stheraven	return (loc->using_monetary_locale
174235785Stheraven		? &((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