xref: /dragonfly/lib/libc/locale/lmonetary.c (revision e07f19b6)
10d5acd74SJohn Marino /*
20d5acd74SJohn Marino  * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
30d5acd74SJohn Marino  * All rights reserved.
40d5acd74SJohn Marino  *
50d5acd74SJohn Marino  * Copyright (c) 2011 The FreeBSD Foundation
60d5acd74SJohn Marino  * All rights reserved.
70d5acd74SJohn Marino  * Portions of this software were developed by David Chisnall
80d5acd74SJohn Marino  * under sponsorship from the FreeBSD Foundation.
90d5acd74SJohn Marino  *
100d5acd74SJohn Marino  * Redistribution and use in source and binary forms, with or without
110d5acd74SJohn Marino  * modification, are permitted provided that the following conditions
120d5acd74SJohn Marino  * are met:
130d5acd74SJohn Marino  * 1. Redistributions of source code must retain the above copyright
140d5acd74SJohn Marino  *    notice, this list of conditions and the following disclaimer.
150d5acd74SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
160d5acd74SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
170d5acd74SJohn Marino  *    documentation and/or other materials provided with the distribution.
180d5acd74SJohn Marino  *
190d5acd74SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
200d5acd74SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
210d5acd74SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
220d5acd74SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
230d5acd74SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
240d5acd74SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
250d5acd74SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
260d5acd74SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
270d5acd74SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
280d5acd74SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
290d5acd74SJohn Marino  * SUCH DAMAGE.
300d5acd74SJohn Marino  *
310d5acd74SJohn Marino  * $FreeBSD: head/lib/libc/locale/lmonetary.c 227753 2011-11-20 14:45:42Z theraven $
320d5acd74SJohn Marino  */
330d5acd74SJohn Marino 
340d5acd74SJohn Marino 
350d5acd74SJohn Marino #include <limits.h>
360d5acd74SJohn Marino #include <stddef.h>
370d5acd74SJohn Marino #include <stdlib.h>
380d5acd74SJohn Marino 
390d5acd74SJohn Marino #include "ldpart.h"
400d5acd74SJohn Marino #include "lmonetary.h"
410d5acd74SJohn Marino 
420d5acd74SJohn Marino extern const char * __fix_locale_grouping_str(const char *);
430d5acd74SJohn Marino 
440d5acd74SJohn Marino #define LCMONETARY_SIZE_FULL (sizeof(struct lc_monetary_T) / sizeof(char *))
450d5acd74SJohn Marino #define LCMONETARY_SIZE_MIN \
460d5acd74SJohn Marino 		(offsetof(struct lc_monetary_T, int_p_cs_precedes) / \
470d5acd74SJohn Marino 		    sizeof(char *))
480d5acd74SJohn Marino 
490d5acd74SJohn Marino static char	empty[] = "";
500d5acd74SJohn Marino static char	numempty[] = { CHAR_MAX, '\0'};
510d5acd74SJohn Marino 
520d5acd74SJohn Marino static const struct lc_monetary_T _C_monetary_locale = {
530d5acd74SJohn Marino 	empty,		/* int_curr_symbol */
540d5acd74SJohn Marino 	empty,		/* currency_symbol */
550d5acd74SJohn Marino 	empty,		/* mon_decimal_point */
560d5acd74SJohn Marino 	empty,		/* mon_thousands_sep */
570d5acd74SJohn Marino 	numempty,	/* mon_grouping */
580d5acd74SJohn Marino 	empty,		/* positive_sign */
590d5acd74SJohn Marino 	empty,		/* negative_sign */
600d5acd74SJohn Marino 	numempty,	/* int_frac_digits */
610d5acd74SJohn Marino 	numempty,	/* frac_digits */
620d5acd74SJohn Marino 	numempty,	/* p_cs_precedes */
630d5acd74SJohn Marino 	numempty,	/* p_sep_by_space */
640d5acd74SJohn Marino 	numempty,	/* n_cs_precedes */
650d5acd74SJohn Marino 	numempty,	/* n_sep_by_space */
660d5acd74SJohn Marino 	numempty,	/* p_sign_posn */
670d5acd74SJohn Marino 	numempty,	/* n_sign_posn */
680d5acd74SJohn Marino 	numempty,	/* int_p_cs_precedes */
690d5acd74SJohn Marino 	numempty,	/* int_n_cs_precedes */
700d5acd74SJohn Marino 	numempty,	/* int_p_sep_by_space */
710d5acd74SJohn Marino 	numempty,	/* int_n_sep_by_space */
720d5acd74SJohn Marino 	numempty,	/* int_p_sign_posn */
730d5acd74SJohn Marino 	numempty	/* int_n_sign_posn */
740d5acd74SJohn Marino };
750d5acd74SJohn Marino 
760d5acd74SJohn Marino struct xlocale_monetary __xlocale_global_monetary;
770d5acd74SJohn Marino 
780d5acd74SJohn Marino static char
cnv(const char * str)790d5acd74SJohn Marino cnv(const char *str)
800d5acd74SJohn Marino {
810d5acd74SJohn Marino 	int i = strtol(str, NULL, 10);
820d5acd74SJohn Marino 
830d5acd74SJohn Marino 	if (i == -1)
840d5acd74SJohn Marino 		i = CHAR_MAX;
850d5acd74SJohn Marino 	return ((char)i);
860d5acd74SJohn Marino }
870d5acd74SJohn Marino 
880d5acd74SJohn Marino static void
destruct_monetary(void * v)890d5acd74SJohn Marino destruct_monetary(void *v)
900d5acd74SJohn Marino {
910d5acd74SJohn Marino 	struct xlocale_monetary *l = v;
920d5acd74SJohn Marino 	if (l->buffer)
930d5acd74SJohn Marino 		free(l->buffer);
940d5acd74SJohn Marino 	free(l);
950d5acd74SJohn Marino }
960d5acd74SJohn Marino 
970d5acd74SJohn Marino static int
monetary_load_locale_l(struct xlocale_monetary * loc,int * using_locale,int * changed,const char * name)980d5acd74SJohn Marino monetary_load_locale_l(struct xlocale_monetary *loc, int *using_locale,
990d5acd74SJohn Marino 		int *changed, const char *name)
1000d5acd74SJohn Marino {
1010d5acd74SJohn Marino 	int ret;
1020d5acd74SJohn Marino 	struct lc_monetary_T *l = &loc->locale;
1030d5acd74SJohn Marino 
1040d5acd74SJohn Marino 	ret = __part_load_locale(name, using_locale,
1050d5acd74SJohn Marino 		&loc->buffer, "LC_MONETARY",
1060d5acd74SJohn Marino 		LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN,
1070d5acd74SJohn Marino 		(const char **)l);
1080d5acd74SJohn Marino 	if (ret != _LDP_ERROR)
1090d5acd74SJohn Marino 		*changed = 1;
1100d5acd74SJohn Marino 	if (ret == _LDP_LOADED) {
1110d5acd74SJohn Marino 		l->mon_grouping =
1120d5acd74SJohn Marino 		     __fix_locale_grouping_str(l->mon_grouping);
1130d5acd74SJohn Marino 
1140d5acd74SJohn Marino #define M_ASSIGN_CHAR(NAME) (((char *)l->NAME)[0] = \
1150d5acd74SJohn Marino 			     cnv(l->NAME))
1160d5acd74SJohn Marino 
1170d5acd74SJohn Marino 		M_ASSIGN_CHAR(int_frac_digits);
1180d5acd74SJohn Marino 		M_ASSIGN_CHAR(frac_digits);
1190d5acd74SJohn Marino 		M_ASSIGN_CHAR(p_cs_precedes);
1200d5acd74SJohn Marino 		M_ASSIGN_CHAR(p_sep_by_space);
1210d5acd74SJohn Marino 		M_ASSIGN_CHAR(n_cs_precedes);
1220d5acd74SJohn Marino 		M_ASSIGN_CHAR(n_sep_by_space);
1230d5acd74SJohn Marino 		M_ASSIGN_CHAR(p_sign_posn);
1240d5acd74SJohn Marino 		M_ASSIGN_CHAR(n_sign_posn);
1250d5acd74SJohn Marino 
1260d5acd74SJohn Marino 		/*
1270d5acd74SJohn Marino 		 * The six additional C99 international monetary formatting
1280d5acd74SJohn Marino 		 * parameters default to the national parameters when
1290d5acd74SJohn Marino 		 * reading FreeBSD LC_MONETARY data files.
1300d5acd74SJohn Marino 		 */
1310d5acd74SJohn Marino #define	M_ASSIGN_ICHAR(NAME)						\
1320d5acd74SJohn Marino 		do {							\
1330d5acd74SJohn Marino 			if (l->int_##NAME == NULL)	\
1340d5acd74SJohn Marino 				l->int_##NAME =		\
1350d5acd74SJohn Marino 				    l->NAME;		\
1360d5acd74SJohn Marino 			else						\
1370d5acd74SJohn Marino 				M_ASSIGN_CHAR(int_##NAME);		\
1380d5acd74SJohn Marino 		} while (0)
1390d5acd74SJohn Marino 
1400d5acd74SJohn Marino 		M_ASSIGN_ICHAR(p_cs_precedes);
1410d5acd74SJohn Marino 		M_ASSIGN_ICHAR(n_cs_precedes);
1420d5acd74SJohn Marino 		M_ASSIGN_ICHAR(p_sep_by_space);
1430d5acd74SJohn Marino 		M_ASSIGN_ICHAR(n_sep_by_space);
1440d5acd74SJohn Marino 		M_ASSIGN_ICHAR(p_sign_posn);
1450d5acd74SJohn Marino 		M_ASSIGN_ICHAR(n_sign_posn);
1460d5acd74SJohn Marino 	}
1470d5acd74SJohn Marino 	return (ret);
1480d5acd74SJohn Marino }
1490d5acd74SJohn Marino int
__monetary_load_locale(const char * name)1500d5acd74SJohn Marino __monetary_load_locale(const char *name)
1510d5acd74SJohn Marino {
1520d5acd74SJohn Marino 	return monetary_load_locale_l(&__xlocale_global_monetary,
1530d5acd74SJohn Marino 			&__xlocale_global_locale.using_monetary_locale,
1540d5acd74SJohn Marino 			&__xlocale_global_locale.monetary_locale_changed, name);
1550d5acd74SJohn Marino }
__monetary_load(const char * name,locale_t l)1560d5acd74SJohn Marino void* __monetary_load(const char *name, locale_t l)
1570d5acd74SJohn Marino {
1580d5acd74SJohn Marino 	struct xlocale_monetary *new = calloc(sizeof(struct xlocale_monetary), 1);
1590d5acd74SJohn Marino 	new->header.header.destructor = destruct_monetary;
1600d5acd74SJohn Marino 	if (monetary_load_locale_l(new, &l->using_monetary_locale,
1610d5acd74SJohn Marino 				&l->monetary_locale_changed, name) == _LDP_ERROR)
1620d5acd74SJohn Marino 	{
1630d5acd74SJohn Marino 		xlocale_release(new);
1640d5acd74SJohn Marino 		return NULL;
1650d5acd74SJohn Marino 	}
1660d5acd74SJohn Marino 	return new;
1670d5acd74SJohn Marino }
1680d5acd74SJohn Marino 
1690d5acd74SJohn Marino 
1700d5acd74SJohn Marino struct lc_monetary_T *
__get_current_monetary_locale(locale_t loc)1710d5acd74SJohn Marino __get_current_monetary_locale(locale_t loc)
1720d5acd74SJohn Marino {
1730d5acd74SJohn Marino 	return (loc->using_monetary_locale
1740d5acd74SJohn Marino 		? &((struct xlocale_monetary*)loc->components[XLC_MONETARY])->locale
1750d5acd74SJohn Marino 		: (struct lc_monetary_T *)&_C_monetary_locale);
1760d5acd74SJohn Marino }
1770d5acd74SJohn Marino 
1780d5acd74SJohn Marino #ifdef LOCALE_DEBUG
1790d5acd74SJohn Marino void
monetdebug()1800d5acd74SJohn Marino monetdebug() {
1810d5acd74SJohn Marino printf(	"int_curr_symbol = %s\n"
1820d5acd74SJohn Marino 	"currency_symbol = %s\n"
1830d5acd74SJohn Marino 	"mon_decimal_point = %s\n"
1840d5acd74SJohn Marino 	"mon_thousands_sep = %s\n"
1850d5acd74SJohn Marino 	"mon_grouping = %s\n"
1860d5acd74SJohn Marino 	"positive_sign = %s\n"
1870d5acd74SJohn Marino 	"negative_sign = %s\n"
1880d5acd74SJohn Marino 	"int_frac_digits = %d\n"
1890d5acd74SJohn Marino 	"frac_digits = %d\n"
1900d5acd74SJohn Marino 	"p_cs_precedes = %d\n"
1910d5acd74SJohn Marino 	"p_sep_by_space = %d\n"
1920d5acd74SJohn Marino 	"n_cs_precedes = %d\n"
1930d5acd74SJohn Marino 	"n_sep_by_space = %d\n"
1940d5acd74SJohn Marino 	"p_sign_posn = %d\n"
195*e07f19b6SSascha Wildner 	"n_sign_posn = %d\n"
1960d5acd74SJohn Marino 	"int_p_cs_precedes = %d\n"
1970d5acd74SJohn Marino 	"int_p_sep_by_space = %d\n"
1980d5acd74SJohn Marino 	"int_n_cs_precedes = %d\n"
1990d5acd74SJohn Marino 	"int_n_sep_by_space = %d\n"
2000d5acd74SJohn Marino 	"int_p_sign_posn = %d\n"
2010d5acd74SJohn Marino 	"int_n_sign_posn = %d\n",
2020d5acd74SJohn Marino 	_monetary_locale.int_curr_symbol,
2030d5acd74SJohn Marino 	_monetary_locale.currency_symbol,
2040d5acd74SJohn Marino 	_monetary_locale.mon_decimal_point,
2050d5acd74SJohn Marino 	_monetary_locale.mon_thousands_sep,
2060d5acd74SJohn Marino 	_monetary_locale.mon_grouping,
2070d5acd74SJohn Marino 	_monetary_locale.positive_sign,
2080d5acd74SJohn Marino 	_monetary_locale.negative_sign,
2090d5acd74SJohn Marino 	_monetary_locale.int_frac_digits[0],
2100d5acd74SJohn Marino 	_monetary_locale.frac_digits[0],
2110d5acd74SJohn Marino 	_monetary_locale.p_cs_precedes[0],
2120d5acd74SJohn Marino 	_monetary_locale.p_sep_by_space[0],
2130d5acd74SJohn Marino 	_monetary_locale.n_cs_precedes[0],
2140d5acd74SJohn Marino 	_monetary_locale.n_sep_by_space[0],
2150d5acd74SJohn Marino 	_monetary_locale.p_sign_posn[0],
2160d5acd74SJohn Marino 	_monetary_locale.n_sign_posn[0],
2170d5acd74SJohn Marino 	_monetary_locale.int_p_cs_precedes[0],
2180d5acd74SJohn Marino 	_monetary_locale.int_p_sep_by_space[0],
2190d5acd74SJohn Marino 	_monetary_locale.int_n_cs_precedes[0],
2200d5acd74SJohn Marino 	_monetary_locale.int_n_sep_by_space[0],
2210d5acd74SJohn Marino 	_monetary_locale.int_p_sign_posn[0],
2220d5acd74SJohn Marino 	_monetary_locale.int_n_sign_posn[0]
2230d5acd74SJohn Marino );
2240d5acd74SJohn Marino }
2250d5acd74SJohn Marino #endif /* LOCALE_DEBUG */
226