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$");
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