Deleted Added
full compact
xlocale.c (231673) xlocale.c (231714)
1/*-
2 * Copyright (c) 2011 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by David Chisnall under sponsorship from
6 * the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
1/*-
2 * Copyright (c) 2011 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by David Chisnall under sponsorship from
6 * the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
9 * modification, are permitted provided that the following conditions * are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15 *
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
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
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
26 * SUCH DAMAGE.
27 *
29 * $FreeBSD: head/lib/libc/locale/xlocale.c 231673 2012-02-14 12:03:23Z theraven $
28 * $FreeBSD: head/lib/libc/locale/xlocale.c 231714 2012-02-14 21:48:46Z dim $
30 */
31
32#include <pthread.h>
33#include <stdio.h>
34#include <string.h>
29 */
30
31#include <pthread.h>
32#include <stdio.h>
33#include <string.h>
35#include <runetype.h>
36#include "libc_private.h"
37#include "xlocale_private.h"
38
39/**
40 * Each locale loader declares a global component. This is used by setlocale()
41 * and also by xlocale with LC_GLOBAL_LOCALE..
42 */
43extern struct xlocale_component __xlocale_global_collate;
44extern struct xlocale_component __xlocale_global_ctype;
45extern struct xlocale_component __xlocale_global_monetary;
46extern struct xlocale_component __xlocale_global_numeric;
47extern struct xlocale_component __xlocale_global_time;
48extern struct xlocale_component __xlocale_global_messages;
49/*
50 * And another version for the statically-allocated C locale. We only have
51 * components for the parts that are expected to be sensible.
52 */
53extern struct xlocale_component __xlocale_C_collate;
54extern struct xlocale_component __xlocale_C_ctype;
34#include "libc_private.h"
35#include "xlocale_private.h"
36
37/**
38 * Each locale loader declares a global component. This is used by setlocale()
39 * and also by xlocale with LC_GLOBAL_LOCALE..
40 */
41extern struct xlocale_component __xlocale_global_collate;
42extern struct xlocale_component __xlocale_global_ctype;
43extern struct xlocale_component __xlocale_global_monetary;
44extern struct xlocale_component __xlocale_global_numeric;
45extern struct xlocale_component __xlocale_global_time;
46extern struct xlocale_component __xlocale_global_messages;
47/*
48 * And another version for the statically-allocated C locale. We only have
49 * components for the parts that are expected to be sensible.
50 */
51extern struct xlocale_component __xlocale_C_collate;
52extern struct xlocale_component __xlocale_C_ctype;
55
56#ifndef __NO_TLS
57/*
53/*
58 * The locale for this thread.
59 */
60_Thread_local locale_t __thread_locale;
61#endif
62/*
63 * Flag indicating that one or more per-thread locales exist.
64 */
65int __has_thread_locale;
66/*
67 * Private functions in setlocale.c.
68 */
69const char *
70__get_locale_env(int category);
71int
72__detect_path_locale(void);
73
74struct _xlocale __xlocale_global_locale = {

--- 36 unchanged lines hidden (view full) ---

111};
112
113static pthread_key_t locale_info_key;
114static int fake_tls;
115static locale_t thread_local_locale;
116
117static void init_key(void)
118{
54 * Private functions in setlocale.c.
55 */
56const char *
57__get_locale_env(int category);
58int
59__detect_path_locale(void);
60
61struct _xlocale __xlocale_global_locale = {

--- 36 unchanged lines hidden (view full) ---

98};
99
100static pthread_key_t locale_info_key;
101static int fake_tls;
102static locale_t thread_local_locale;
103
104static void init_key(void)
105{
119
120 pthread_key_create(&locale_info_key, xlocale_release);
121 pthread_setspecific(locale_info_key, (void*)42);
122 if (pthread_getspecific(locale_info_key) == (void*)42) {
123 pthread_setspecific(locale_info_key, 0);
124 } else {
125 fake_tls = 1;
126 }
106 pthread_key_create(&locale_info_key, xlocale_release);
107 pthread_setspecific(locale_info_key, (void*)42);
108 if (pthread_getspecific(locale_info_key) == (void*)42) {
109 pthread_setspecific(locale_info_key, 0);
110 } else {
111 fake_tls = 1;
112 }
127 /* At least one per-thread locale has now been set. */
128 __has_thread_locale = 1;
129 __detect_path_locale();
130}
131
132static pthread_once_t once_control = PTHREAD_ONCE_INIT;
133
134static locale_t
135get_thread_locale(void)
136{
113 __detect_path_locale();
114}
115
116static pthread_once_t once_control = PTHREAD_ONCE_INIT;
117
118static locale_t
119get_thread_locale(void)
120{
137
138 _once(&once_control, init_key);
139
140 return (fake_tls ? thread_local_locale :
141 pthread_getspecific(locale_info_key));
142}
143
121 _once(&once_control, init_key);
122
123 return (fake_tls ? thread_local_locale :
124 pthread_getspecific(locale_info_key));
125}
126
144#ifdef __NO_TLS
145locale_t
146__get_locale(void)
147{
148 locale_t l = get_thread_locale();
149 return (l ? l : &__xlocale_global_locale);
150
151}
127locale_t
128__get_locale(void)
129{
130 locale_t l = get_thread_locale();
131 return (l ? l : &__xlocale_global_locale);
132
133}
152#endif
153
154static void
155set_thread_locale(locale_t loc)
156{
134
135static void
136set_thread_locale(locale_t loc)
137{
157
158 _once(&once_control, init_key);
138 pthread_once(&once_control, init_key);
159
160 if (NULL != loc) {
161 xlocale_retain((struct xlocale_refcounted*)loc);
162 }
163 locale_t old = pthread_getspecific(locale_info_key);
164 if ((NULL != old) && (loc != old)) {
165 xlocale_release((struct xlocale_refcounted*)old);
166 }
167 if (fake_tls) {
168 thread_local_locale = loc;
169 } else {
170 pthread_setspecific(locale_info_key, loc);
171 }
139
140 if (NULL != loc) {
141 xlocale_retain((struct xlocale_refcounted*)loc);
142 }
143 locale_t old = pthread_getspecific(locale_info_key);
144 if ((NULL != old) && (loc != old)) {
145 xlocale_release((struct xlocale_refcounted*)old);
146 }
147 if (fake_tls) {
148 thread_local_locale = loc;
149 } else {
150 pthread_setspecific(locale_info_key, loc);
151 }
172#ifndef __NO_TLS
173 __thread_locale = loc;
174 __set_thread_rune_locale(loc);
175#endif
176}
177
178/**
179 * Clean up a locale, once its reference count reaches zero. This function is
180 * called by xlocale_release(), it should not be called directly.
181 */
182static void
183destruct_locale(void *l)
184{
185 locale_t loc = l;
152}
153
154/**
155 * Clean up a locale, once its reference count reaches zero. This function is
156 * called by xlocale_release(), it should not be called directly.
157 */
158static void
159destruct_locale(void *l)
160{
161 locale_t loc = l;
186
187 for (int type=0 ; type<XLC_LAST ; type++) {
188 if (loc->components[type]) {
189 xlocale_release(loc->components[type]);
190 }
191 }
192 if (loc->csym) {
193 free(loc->csym);
194 }
195 free(l);
196}
197
198/**
199 * Allocates a new, uninitialised, locale.
200 */
201static locale_t
202alloc_locale(void)
203{
204 locale_t new = calloc(sizeof(struct _xlocale), 1);
162 for (int type=0 ; type<XLC_LAST ; type++) {
163 if (loc->components[type]) {
164 xlocale_release(loc->components[type]);
165 }
166 }
167 if (loc->csym) {
168 free(loc->csym);
169 }
170 free(l);
171}
172
173/**
174 * Allocates a new, uninitialised, locale.
175 */
176static locale_t
177alloc_locale(void)
178{
179 locale_t new = calloc(sizeof(struct _xlocale), 1);
205
206 new->header.destructor = destruct_locale;
207 new->monetary_locale_changed = 1;
208 new->numeric_locale_changed = 1;
209 return (new);
210}
211static void
212copyflags(locale_t new, locale_t old)
213{
214 new->using_monetary_locale = old->using_monetary_locale;
215 new->using_numeric_locale = old->using_numeric_locale;
216 new->using_time_locale = old->using_time_locale;
217 new->using_messages_locale = old->using_messages_locale;
218}
219
220static int dupcomponent(int type, locale_t base, locale_t new)
221{
180 new->header.destructor = destruct_locale;
181 new->monetary_locale_changed = 1;
182 new->numeric_locale_changed = 1;
183 return (new);
184}
185static void
186copyflags(locale_t new, locale_t old)
187{
188 new->using_monetary_locale = old->using_monetary_locale;
189 new->using_numeric_locale = old->using_numeric_locale;
190 new->using_time_locale = old->using_time_locale;
191 new->using_messages_locale = old->using_messages_locale;
192}
193
194static int dupcomponent(int type, locale_t base, locale_t new)
195{
222 /* Always copy from the global locale, since it has mutable components.
223 */
196 /* Always copy from the global locale, since it has mutable components. */
224 struct xlocale_component *src = base->components[type];
197 struct xlocale_component *src = base->components[type];
225
226 if (&__xlocale_global_locale == base) {
227 new->components[type] = constructors[type](src->locale, new);
228 if (new->components[type]) {
198 if (&__xlocale_global_locale == base) {
199 new->components[type] = constructors[type](src->locale, new);
200 if (new->components[type]) {
229 strncpy(new->components[type]->locale, src->locale,
230 ENCODING_LEN);
201 strncpy(new->components[type]->locale, src->locale, ENCODING_LEN);
231 }
232 } else if (base->components[type]) {
233 new->components[type] = xlocale_retain(base->components[type]);
234 } else {
202 }
203 } else if (base->components[type]) {
204 new->components[type] = xlocale_retain(base->components[type]);
205 } else {
235 /* If the component was NULL, return success - if base is a
236 * valid locale then the flag indicating that this isn't
237 * present should be set. If it isn't a valid locale, then
238 * we're stuck anyway. */
206 /* If the component was NULL, return success - if base is a valid
207 * locale then the flag indicating that this isn't present should be
208 * set. If it isn't a valid locale, then we're stuck anyway. */
239 return 1;
240 }
241 return (0 != new->components[type]);
242}
243
244/*
245 * Public interfaces. These are the five public functions described by the
246 * xlocale interface.

--- 22 unchanged lines hidden (view full) ---

269 useenv = 1;
270 }
271
272 for (type=0 ; type<XLC_LAST ; type++) {
273 if (mask & 1) {
274 if (useenv) {
275 realLocale = __get_locale_env(type);
276 }
209 return 1;
210 }
211 return (0 != new->components[type]);
212}
213
214/*
215 * Public interfaces. These are the five public functions described by the
216 * xlocale interface.

--- 22 unchanged lines hidden (view full) ---

239 useenv = 1;
240 }
241
242 for (type=0 ; type<XLC_LAST ; type++) {
243 if (mask & 1) {
244 if (useenv) {
245 realLocale = __get_locale_env(type);
246 }
277 new->components[type] =
278 constructors[type](realLocale, new);
247 new->components[type] = constructors[type](realLocale, new);
279 if (new->components[type]) {
248 if (new->components[type]) {
280 strncpy(new->components[type]->locale,
281 realLocale, ENCODING_LEN);
249 strncpy(new->components[type]->locale, realLocale, ENCODING_LEN);
282 } else {
283 success = 0;
284 break;
285 }
286 } else {
287 if (!dupcomponent(type, base, new)) {
288 success = 0;
289 break;

--- 56 unchanged lines hidden (view full) ---

346const char *querylocale(int mask, locale_t loc)
347{
348 int type = ffs(mask) - 1;
349 FIX_LOCALE(loc);
350 if (type >= XLC_LAST)
351 return (NULL);
352 if (loc->components[type])
353 return (loc->components[type]->locale);
250 } else {
251 success = 0;
252 break;
253 }
254 } else {
255 if (!dupcomponent(type, base, new)) {
256 success = 0;
257 break;

--- 56 unchanged lines hidden (view full) ---

314const char *querylocale(int mask, locale_t loc)
315{
316 int type = ffs(mask) - 1;
317 FIX_LOCALE(loc);
318 if (type >= XLC_LAST)
319 return (NULL);
320 if (loc->components[type])
321 return (loc->components[type]->locale);
354 return ("C");
322 return "C";
355}
356
357/*
358 * Installs the specified locale_t as this thread's locale.
359 */
360locale_t uselocale(locale_t loc)
361{
362 locale_t old = get_thread_locale();
363 if (NULL != loc) {
364 if (LC_GLOBAL_LOCALE == loc) {
365 loc = NULL;
366 }
367 set_thread_locale(loc);
368 }
369 return (old ? old : LC_GLOBAL_LOCALE);
370}
371
323}
324
325/*
326 * Installs the specified locale_t as this thread's locale.
327 */
328locale_t uselocale(locale_t loc)
329{
330 locale_t old = get_thread_locale();
331 if (NULL != loc) {
332 if (LC_GLOBAL_LOCALE == loc) {
333 loc = NULL;
334 }
335 set_thread_locale(loc);
336 }
337 return (old ? old : LC_GLOBAL_LOCALE);
338}
339