1d915a14eSPedro F. Giffuni /*- 2d915a14eSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 83c87aa1dSDavid Chisnall * All rights reserved. 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 34333fc21eSDavid E. O'Brien #include <sys/cdefs.h> 35333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 36333fc21eSDavid E. O'Brien 371bd7723dSAlexey Zelkin #include <limits.h> 38f4da1a75STim J. Robbins #include <stddef.h> 39831e8f61SAndrey A. Chernov #include <stdlib.h> 40683fe113SAlexey Zelkin 4190423eceSAlexey Zelkin #include "ldpart.h" 42683fe113SAlexey Zelkin #include "lmonetary.h" 4390423eceSAlexey Zelkin 441bd7723dSAlexey Zelkin extern const char * __fix_locale_grouping_str(const char *); 4590423eceSAlexey Zelkin 468a093dadSAndrey A. Chernov #define LCMONETARY_SIZE_FULL (sizeof(struct lc_monetary_T) / sizeof(char *)) 478a093dadSAndrey A. Chernov #define LCMONETARY_SIZE_MIN \ 488a093dadSAndrey A. Chernov (offsetof(struct lc_monetary_T, int_p_cs_precedes) / \ 498a093dadSAndrey A. Chernov sizeof(char *)) 5090423eceSAlexey Zelkin 5190423eceSAlexey Zelkin static char empty[] = ""; 521bd7723dSAlexey Zelkin static char numempty[] = { CHAR_MAX, '\0'}; 5390423eceSAlexey Zelkin 5490423eceSAlexey Zelkin static const struct lc_monetary_T _C_monetary_locale = { 5590423eceSAlexey Zelkin empty, /* int_curr_symbol */ 5690423eceSAlexey Zelkin empty, /* currency_symbol */ 5754e3bc25SAndrey A. Chernov empty, /* mon_decimal_point */ 5890423eceSAlexey Zelkin empty, /* mon_thousands_sep */ 5990423eceSAlexey Zelkin numempty, /* mon_grouping */ 6090423eceSAlexey Zelkin empty, /* positive_sign */ 6190423eceSAlexey Zelkin empty, /* negative_sign */ 6290423eceSAlexey Zelkin numempty, /* int_frac_digits */ 6390423eceSAlexey Zelkin numempty, /* frac_digits */ 6490423eceSAlexey Zelkin numempty, /* p_cs_precedes */ 6590423eceSAlexey Zelkin numempty, /* p_sep_by_space */ 6690423eceSAlexey Zelkin numempty, /* n_cs_precedes */ 6790423eceSAlexey Zelkin numempty, /* n_sep_by_space */ 6890423eceSAlexey Zelkin numempty, /* p_sign_posn */ 69f4da1a75STim J. Robbins numempty, /* n_sign_posn */ 70f4da1a75STim J. Robbins numempty, /* int_p_cs_precedes */ 71f4da1a75STim J. Robbins numempty, /* int_n_cs_precedes */ 72f4da1a75STim J. Robbins numempty, /* int_p_sep_by_space */ 73f4da1a75STim J. Robbins numempty, /* int_n_sep_by_space */ 74f4da1a75STim J. Robbins numempty, /* int_p_sign_posn */ 75f4da1a75STim J. Robbins numempty /* int_n_sign_posn */ 7690423eceSAlexey Zelkin }; 7790423eceSAlexey Zelkin 783c87aa1dSDavid Chisnall struct xlocale_monetary __xlocale_global_monetary; 7990423eceSAlexey Zelkin 80831e8f61SAndrey A. Chernov static char 81ecc4c620SAndrey A. Chernov cnv(const char *str) 82ecc4c620SAndrey A. Chernov { 83831e8f61SAndrey A. Chernov int i = strtol(str, NULL, 10); 84ecc4c620SAndrey A. Chernov 85831e8f61SAndrey A. Chernov if (i == -1) 86831e8f61SAndrey A. Chernov i = CHAR_MAX; 87ecc4c620SAndrey A. Chernov return ((char)i); 88831e8f61SAndrey A. Chernov } 89831e8f61SAndrey A. Chernov 903c87aa1dSDavid Chisnall static void 913c87aa1dSDavid Chisnall destruct_monetary(void *v) 923c87aa1dSDavid Chisnall { 933c87aa1dSDavid Chisnall struct xlocale_monetary *l = v; 943c87aa1dSDavid Chisnall if (l->buffer) 953c87aa1dSDavid Chisnall free(l->buffer); 963c87aa1dSDavid Chisnall free(l); 973c87aa1dSDavid Chisnall } 983c87aa1dSDavid Chisnall 993c87aa1dSDavid Chisnall static int 1003c87aa1dSDavid Chisnall monetary_load_locale_l(struct xlocale_monetary *loc, int *using_locale, 1013c87aa1dSDavid Chisnall int *changed, const char *name) 102ecc4c620SAndrey A. Chernov { 10390423eceSAlexey Zelkin int ret; 1043c87aa1dSDavid Chisnall struct lc_monetary_T *l = &loc->locale; 105ecc4c620SAndrey A. Chernov 1063c87aa1dSDavid Chisnall ret = __part_load_locale(name, using_locale, 1073c87aa1dSDavid Chisnall &loc->buffer, "LC_MONETARY", 1088a093dadSAndrey A. Chernov LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN, 1093c87aa1dSDavid Chisnall (const char **)l); 11076692b80SAndrey A. Chernov if (ret == _LDP_LOADED) { 1113c87aa1dSDavid Chisnall l->mon_grouping = 1123c87aa1dSDavid Chisnall __fix_locale_grouping_str(l->mon_grouping); 113831e8f61SAndrey A. Chernov 1143c87aa1dSDavid Chisnall #define M_ASSIGN_CHAR(NAME) (((char *)l->NAME)[0] = \ 1153c87aa1dSDavid Chisnall cnv(l->NAME)) 116831e8f61SAndrey A. Chernov 117831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(int_frac_digits); 118831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(frac_digits); 119831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(p_cs_precedes); 120831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(p_sep_by_space); 121831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(n_cs_precedes); 122831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(n_sep_by_space); 123831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(p_sign_posn); 124831e8f61SAndrey A. Chernov M_ASSIGN_CHAR(n_sign_posn); 125f4da1a75STim J. Robbins 126f4da1a75STim J. Robbins /* 127f4da1a75STim J. Robbins * The six additional C99 international monetary formatting 128f4da1a75STim J. Robbins * parameters default to the national parameters when 129683fe113SAlexey Zelkin * reading FreeBSD LC_MONETARY data files. 130f4da1a75STim J. Robbins */ 131f4da1a75STim J. Robbins #define M_ASSIGN_ICHAR(NAME) \ 132f4da1a75STim J. Robbins do { \ 1333c87aa1dSDavid Chisnall if (l->int_##NAME == NULL) \ 1343c87aa1dSDavid Chisnall l->int_##NAME = \ 1353c87aa1dSDavid Chisnall l->NAME; \ 136f4da1a75STim J. Robbins else \ 137f4da1a75STim J. Robbins M_ASSIGN_CHAR(int_##NAME); \ 138f4da1a75STim J. Robbins } while (0) 139f4da1a75STim J. Robbins 140f4da1a75STim J. Robbins M_ASSIGN_ICHAR(p_cs_precedes); 141f4da1a75STim J. Robbins M_ASSIGN_ICHAR(n_cs_precedes); 142f4da1a75STim J. Robbins M_ASSIGN_ICHAR(p_sep_by_space); 143f4da1a75STim J. Robbins M_ASSIGN_ICHAR(n_sep_by_space); 144f4da1a75STim J. Robbins M_ASSIGN_ICHAR(p_sign_posn); 145f4da1a75STim J. Robbins M_ASSIGN_ICHAR(n_sign_posn); 146831e8f61SAndrey A. Chernov } 147*7eb138a9SMark Johnston if (ret != _LDP_ERROR) 148*7eb138a9SMark Johnston atomic_store_rel_int(changed, 1); 149ecc4c620SAndrey A. Chernov return (ret); 15090423eceSAlexey Zelkin } 1513c87aa1dSDavid Chisnall int 1523c87aa1dSDavid Chisnall __monetary_load_locale(const char *name) 1533c87aa1dSDavid Chisnall { 1543c87aa1dSDavid Chisnall return monetary_load_locale_l(&__xlocale_global_monetary, 1553c87aa1dSDavid Chisnall &__xlocale_global_locale.using_monetary_locale, 1563c87aa1dSDavid Chisnall &__xlocale_global_locale.monetary_locale_changed, name); 1573c87aa1dSDavid Chisnall } 1583c87aa1dSDavid Chisnall void* __monetary_load(const char *name, locale_t l) 1593c87aa1dSDavid Chisnall { 1603c87aa1dSDavid Chisnall struct xlocale_monetary *new = calloc(sizeof(struct xlocale_monetary), 1); 1613c87aa1dSDavid Chisnall new->header.header.destructor = destruct_monetary; 1623c87aa1dSDavid Chisnall if (monetary_load_locale_l(new, &l->using_monetary_locale, 1633c87aa1dSDavid Chisnall &l->monetary_locale_changed, name) == _LDP_ERROR) 1643c87aa1dSDavid Chisnall { 1653c87aa1dSDavid Chisnall xlocale_release(new); 1663c87aa1dSDavid Chisnall return NULL; 1673c87aa1dSDavid Chisnall } 1683c87aa1dSDavid Chisnall return new; 1693c87aa1dSDavid Chisnall } 1703c87aa1dSDavid Chisnall 17190423eceSAlexey Zelkin 17290423eceSAlexey Zelkin struct lc_monetary_T * 1733c87aa1dSDavid Chisnall __get_current_monetary_locale(locale_t loc) 174ecc4c620SAndrey A. Chernov { 1753c87aa1dSDavid Chisnall return (loc->using_monetary_locale 1763c87aa1dSDavid Chisnall ? &((struct xlocale_monetary*)loc->components[XLC_MONETARY])->locale 17790423eceSAlexey Zelkin : (struct lc_monetary_T *)&_C_monetary_locale); 17890423eceSAlexey Zelkin } 17990423eceSAlexey Zelkin 18090423eceSAlexey Zelkin #ifdef LOCALE_DEBUG 18190423eceSAlexey Zelkin void 18290423eceSAlexey Zelkin monetdebug() { 18390423eceSAlexey Zelkin printf( "int_curr_symbol = %s\n" 18490423eceSAlexey Zelkin "currency_symbol = %s\n" 18590423eceSAlexey Zelkin "mon_decimal_point = %s\n" 18690423eceSAlexey Zelkin "mon_thousands_sep = %s\n" 18790423eceSAlexey Zelkin "mon_grouping = %s\n" 18890423eceSAlexey Zelkin "positive_sign = %s\n" 18990423eceSAlexey Zelkin "negative_sign = %s\n" 190831e8f61SAndrey A. Chernov "int_frac_digits = %d\n" 191831e8f61SAndrey A. Chernov "frac_digits = %d\n" 192831e8f61SAndrey A. Chernov "p_cs_precedes = %d\n" 193831e8f61SAndrey A. Chernov "p_sep_by_space = %d\n" 194831e8f61SAndrey A. Chernov "n_cs_precedes = %d\n" 195831e8f61SAndrey A. Chernov "n_sep_by_space = %d\n" 196831e8f61SAndrey A. Chernov "p_sign_posn = %d\n" 1979908eab8SPedro F. Giffuni "n_sign_posn = %d\n" 198683fe113SAlexey Zelkin "int_p_cs_precedes = %d\n" 199683fe113SAlexey Zelkin "int_p_sep_by_space = %d\n" 200683fe113SAlexey Zelkin "int_n_cs_precedes = %d\n" 201683fe113SAlexey Zelkin "int_n_sep_by_space = %d\n" 202683fe113SAlexey Zelkin "int_p_sign_posn = %d\n" 203683fe113SAlexey Zelkin "int_n_sign_posn = %d\n", 20490423eceSAlexey Zelkin _monetary_locale.int_curr_symbol, 20590423eceSAlexey Zelkin _monetary_locale.currency_symbol, 20690423eceSAlexey Zelkin _monetary_locale.mon_decimal_point, 20790423eceSAlexey Zelkin _monetary_locale.mon_thousands_sep, 20890423eceSAlexey Zelkin _monetary_locale.mon_grouping, 20990423eceSAlexey Zelkin _monetary_locale.positive_sign, 21090423eceSAlexey Zelkin _monetary_locale.negative_sign, 211831e8f61SAndrey A. Chernov _monetary_locale.int_frac_digits[0], 212831e8f61SAndrey A. Chernov _monetary_locale.frac_digits[0], 213831e8f61SAndrey A. Chernov _monetary_locale.p_cs_precedes[0], 214831e8f61SAndrey A. Chernov _monetary_locale.p_sep_by_space[0], 215831e8f61SAndrey A. Chernov _monetary_locale.n_cs_precedes[0], 216831e8f61SAndrey A. Chernov _monetary_locale.n_sep_by_space[0], 217831e8f61SAndrey A. Chernov _monetary_locale.p_sign_posn[0], 218683fe113SAlexey Zelkin _monetary_locale.n_sign_posn[0], 219683fe113SAlexey Zelkin _monetary_locale.int_p_cs_precedes[0], 220683fe113SAlexey Zelkin _monetary_locale.int_p_sep_by_space[0], 221683fe113SAlexey Zelkin _monetary_locale.int_n_cs_precedes[0], 222683fe113SAlexey Zelkin _monetary_locale.int_n_sep_by_space[0], 223683fe113SAlexey Zelkin _monetary_locale.int_p_sign_posn[0], 224683fe113SAlexey Zelkin _monetary_locale.int_n_sign_posn[0] 22590423eceSAlexey Zelkin ); 22690423eceSAlexey Zelkin } 22790423eceSAlexey Zelkin #endif /* LOCALE_DEBUG */ 228