1 /* $NetBSD: setlocale.c,v 1.58 2010/06/07 13:52:30 tnozaki Exp $ */
4 * Copyright (c)2008 Citrus Project,
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 #if defined(LIBC_SCCS) && !defined(lint)
31 __RCSID("$NetBSD: setlocale.c,v 1.58 2010/06/07 13:52:30 tnozaki Exp $");
32 #endif /* LIBC_SCCS and not lint */
34 #include <sys/types.h>
42 #include "setlocale_local.h"
44 const char *_PathLocale
= NULL
;
46 __link_set_decl(all_categories
, _locale_category_t
);
48 extern const _locale_category_t _generic_LC_ALL_desc
;
49 extern const _locale_category_t _dummy_LC_COLLATE_desc
;
51 extern const _locale_category_t _citrus_LC_CTYPE_desc
;
52 extern const _locale_category_t _citrus_LC_MONETARY_desc
;
53 extern const _locale_category_t _citrus_LC_NUMERIC_desc
;
54 extern const _locale_category_t _citrus_LC_TIME_desc
;
55 extern const _locale_category_t _citrus_LC_MESSAGES_desc
;
57 extern const _locale_category_t _localeio_LC_CTYPE_desc
;
58 extern const _locale_category_t _localeio_LC_MONETARY_desc
;
59 extern const _locale_category_t _localeio_LC_NUMERIC_desc
;
60 extern const _locale_category_t _localeio_LC_TIME_desc
;
61 extern const _locale_category_t _localeio_LC_MESSAGES_desc
;
65 /* GNU binutils 2.x a.out support is rotten and link sets are not
66 supported. Workaround this by explicitely creating the structure
67 the linker was supposed to create. */
71 _locale_category_t
*__ls_items
[7];
72 } __link_set_all_categories
= {
75 [0] = __UNCONST(&_generic_LC_ALL_desc
),
76 [1] = __UNCONST(&_dummy_LC_COLLATE_desc
),
78 [2] = __UNCONST(&_citrus_LC_CTYPE_desc
),
79 [3] = __UNCONST(&_citrus_LC_MONETARY_desc
),
80 [4] = __UNCONST(&_citrus_LC_NUMERIC_desc
),
81 [5] = __UNCONST(&_citrus_LC_TIME_desc
),
82 [6] = __UNCONST(&_citrus_LC_MESSAGES_desc
),
84 [2] = __UNCONST(&_localeio_LC_CTYPE_desc
),
85 [3] = __UNCONST(&_localeio_LC_MONETARY_desc
),
86 [4] = __UNCONST(&_localeio_LC_NUMERIC_desc
),
87 [5] = __UNCONST(&_localeio_LC_TIME_desc
),
88 [6] = __UNCONST(&_localeio_LC_MESSAGES_desc
),
96 __link_set_add_data(all_categories
, _generic_LC_ALL_desc
);
97 __link_set_add_data(all_categories
, _dummy_LC_COLLATE_desc
);
99 __link_set_add_data(all_categories
, _citrus_LC_CTYPE_desc
);
100 __link_set_add_data(all_categories
, _citrus_LC_MONETARY_desc
);
101 __link_set_add_data(all_categories
, _citrus_LC_NUMERIC_desc
);
102 __link_set_add_data(all_categories
, _citrus_LC_TIME_desc
);
103 __link_set_add_data(all_categories
, _citrus_LC_MESSAGES_desc
);
105 __link_set_add_data(all_categories
, _localeio_LC_CTYPE_desc
);
106 __link_set_add_data(all_categories
, _localeio_LC_MONETARY_desc
);
107 __link_set_add_data(all_categories
, _localeio_LC_NUMERIC_desc
);
108 __link_set_add_data(all_categories
, _localeio_LC_TIME_desc
);
109 __link_set_add_data(all_categories
, _localeio_LC_MESSAGES_desc
);
113 _find_category(int category
)
115 _locale_category_t
* const *p
;
117 __link_set_foreach(p
, all_categories
) {
118 if ((*p
)->category
== category
)
125 _get_locale_env(const char *category
)
129 /* 1. check LC_ALL */
130 name
= (const char *)getenv("LC_ALL");
131 if (name
== NULL
|| *name
== '\0') {
133 name
= (const char *)getenv(category
);
134 if (name
== NULL
|| *name
== '\0') {
136 name
= getenv("LANG");
139 if (name
== NULL
|| *name
== '\0' || strchr(name
, '/'))
140 /* 4. if none is set, fall to "C" */
146 __setlocale(int category
, const char *name
)
148 _locale_category_t
*l
;
149 struct _locale_impl_t
*impl
;
151 if (category
>= LC_ALL
&& category
< _LC_LAST
) {
152 l
= _find_category(category
);
154 if (issetugid() || ((_PathLocale
== NULL
&&
155 (_PathLocale
= getenv("PATH_LOCALE")) == NULL
) ||
156 *_PathLocale
== '\0'))
157 _PathLocale
= _PATH_LOCALE
;
158 impl
= *_current_locale();
159 return __UNCONST((*l
->setlocale
)(name
, impl
));
166 setlocale(int category
, const char *locale
)
169 /* locale may be NULL */
171 __mb_len_max_runtime
= MB_LEN_MAX
;
172 return __setlocale(category
, locale
);