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/lnumeric.c 227753 2011-11-20 14:45:42Z theraven $"); 3492986Sobrien 3572321Sphantom#include <limits.h> 36116875Sphantom 37116875Sphantom#include "ldpart.h" 3872165Sphantom#include "lnumeric.h" 3972165Sphantom 4087658Sphantomextern const char *__fix_locale_grouping_str(const char *); 4172165Sphantom 4272165Sphantom#define LCNUMERIC_SIZE (sizeof(struct lc_numeric_T) / sizeof(char *)) 4372165Sphantom 4487658Sphantomstatic char numempty[] = { CHAR_MAX, '\0' }; 4572271Sache 4672165Sphantomstatic const struct lc_numeric_T _C_numeric_locale = { 4787658Sphantom ".", /* decimal_point */ 4887658Sphantom "", /* thousands_sep */ 4987658Sphantom numempty /* grouping */ 5072165Sphantom}; 5172165Sphantom 52227753Stheravenstatic void 53227753Stheravendestruct_numeric(void *v) 54227753Stheraven{ 55227753Stheraven struct xlocale_numeric *l = v; 56227753Stheraven if (l->buffer) 57227753Stheraven free(l->buffer); 58227753Stheraven free(l); 59227753Stheraven} 6072165Sphantom 61227753Stheravenstruct xlocale_numeric __xlocale_global_numeric; 62227753Stheraven 63227753Stheravenstatic int 64227753Stheravennumeric_load_locale(struct xlocale_numeric *loc, int *using_locale, int *changed, 65227753Stheraven const char *name) 66101470Sache{ 6772165Sphantom int ret; 68227753Stheraven struct lc_numeric_T *l = &loc->locale; 6972165Sphantom 70227753Stheraven ret = __part_load_locale(name, using_locale, 71227753Stheraven &loc->buffer, "LC_NUMERIC", 7272443Sphantom LCNUMERIC_SIZE, LCNUMERIC_SIZE, 73227753Stheraven (const char**)l); 74101498Sache if (ret != _LDP_ERROR) 75227753Stheraven *changed= 1; 76112425Sache if (ret == _LDP_LOADED) { 77112425Sache /* Can't be empty according to C99 */ 78227753Stheraven if (*l->decimal_point == '\0') 79227753Stheraven l->decimal_point = 80112425Sache _C_numeric_locale.decimal_point; 81227753Stheraven l->grouping = 82227753Stheraven __fix_locale_grouping_str(l->grouping); 83112425Sache } 84101470Sache return (ret); 8572165Sphantom} 8672165Sphantom 87227753Stheravenint 88227753Stheraven__numeric_load_locale(const char *name) 89227753Stheraven{ 90227753Stheraven return numeric_load_locale(&__xlocale_global_numeric, 91227753Stheraven &__xlocale_global_locale.using_numeric_locale, 92227753Stheraven &__xlocale_global_locale.numeric_locale_changed, name); 93227753Stheraven} 94227753Stheravenvoid * 95227753Stheraven__numeric_load(const char *name, locale_t l) 96227753Stheraven{ 97227753Stheraven struct xlocale_numeric *new = calloc(sizeof(struct xlocale_numeric), 1); 98227753Stheraven new->header.header.destructor = destruct_numeric; 99227753Stheraven if (numeric_load_locale(new, &l->using_numeric_locale, 100227753Stheraven &l->numeric_locale_changed, name) == _LDP_ERROR) 101227753Stheraven { 102227753Stheraven xlocale_release(new); 103227753Stheraven return NULL; 104227753Stheraven } 105227753Stheraven return new; 106227753Stheraven} 107227753Stheraven 10872165Sphantomstruct lc_numeric_T * 109227753Stheraven__get_current_numeric_locale(locale_t loc) 110101470Sache{ 111227753Stheraven return (loc->using_numeric_locale 112227753Stheraven ? &((struct xlocale_numeric *)loc->components[XLC_NUMERIC])->locale 11372165Sphantom : (struct lc_numeric_T *)&_C_numeric_locale); 11472165Sphantom} 11572165Sphantom 11672165Sphantom#ifdef LOCALE_DEBUG 11772165Sphantomvoid 11872165Sphantomnumericdebug(void) { 11972165Sphantomprintf( "decimal_point = %s\n" 12072165Sphantom "thousands_sep = %s\n" 12172165Sphantom "grouping = %s\n", 12272165Sphantom _numeric_locale.decimal_point, 12372165Sphantom _numeric_locale.thousands_sep, 12472165Sphantom _numeric_locale.grouping 12572165Sphantom); 12672165Sphantom} 12772165Sphantom#endif /* LOCALE_DEBUG */ 128