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