xref: /netbsd/lib/libc/locale/nb_lc_template.h (revision 6550d01e)
1 /* $NetBSD: nb_lc_template.h,v 1.3 2010/05/22 13:15:59 tnozaki Exp $ */
2 
3 /*-
4  * Copyright (c)1999, 2008 Citrus Project,
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
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
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
26  * SUCH DAMAGE.
27  */
28 
29 /*-
30  * Copyright (c) 1998 The NetBSD Foundation, Inc.
31  * All rights reserved.
32  *
33  * This code is derived from software contributed to The NetBSD Foundation
34  * by Paul Kranenburg.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  * 1. Redistributions of source code must retain the above copyright
40  *    notice, this list of conditions and the following disclaimer.
41  * 2. Redistributions in binary form must reproduce the above copyright
42  *    notice, this list of conditions and the following disclaimer in the
43  *    documentation and/or other materials provided with the distribution.
44  *
45  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
46  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
47  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
49  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
50  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
51  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
52  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55  * POSSIBILITY OF SUCH DAMAGE.
56  */
57 
58 /*-
59  * Copyright (c) 1993
60  *	The Regents of the University of California.  All rights reserved.
61  *
62  * This code is derived from software contributed to Berkeley by
63  * Paul Borman at Krystal Technologies.
64  *
65  * Redistribution and use in source and binary forms, with or without
66  * modification, are permitted provided that the following conditions
67  * are met:
68  * 1. Redistributions of source code must retain the above copyright
69  *    notice, this list of conditions and the following disclaimer.
70  * 2. Redistributions in binary form must reproduce the above copyright
71  *    notice, this list of conditions and the following disclaimer in the
72  *    documentation and/or other materials provided with the distribution.
73  * 3. Neither the name of the University nor the names of its contributors
74  *    may be used to endorse or promote products derived from this software
75  *    without specific prior written permission.
76  *
77  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
78  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
79  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
80  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
81  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
82  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
83  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
84  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
85  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
86  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
87  * SUCH DAMAGE.
88  */
89 
90 #ifndef _NB_LC_TEMPLATE_H_
91 #define _NB_LC_TEMPLATE_H_
92 
93 #define _nb_part_t		_PREFIX(part_t)
94 #define _nb_part_cache		_PREFIX(part_cache)
95 #define _nb_default_c		_PREFIX(default_c)
96 #define _nb_default_posix	_PREFIX(default_posix)
97 #define _nb_mutex		_PREFIX(mutex)
98 
99 typedef struct _nb_part_t {
100 	char name[_LOCALENAME_LEN_MAX];
101 	_CATEGORY_TYPE *impl;
102 	SIMPLEQ_ENTRY(_nb_part_t) entry;
103 } _nb_part_t;
104 
105 static SIMPLEQ_HEAD(, _nb_part_t) _nb_part_cache =
106     SIMPLEQ_HEAD_INITIALIZER(_nb_part_cache);
107 
108 static const _nb_part_t _nb_default_c = {
109     _C_LOCALE,
110     __UNCONST(&_CATEGORY_DEFAULT),
111     { NULL },
112 };
113 
114 static const _nb_part_t _nb_default_posix = {
115     _POSIX_LOCALE,
116     __UNCONST(&_CATEGORY_DEFAULT),
117     { NULL },
118 };
119 
120 #ifdef _REENTRANT
121 static mutex_t _nb_mutex = MUTEX_INITIALIZER;
122 #endif
123 
124 static int
125 _PREFIX(load_sub)(const char * __restrict name, const char * __restrict real,
126     _nb_part_t ** __restrict part, int force)
127 {
128 	_nb_part_t *p, *q;
129 	int ret;
130 
131 	_DIAGASSERT(name != NULL);
132 	_DIAGASSERT(part != NULL);
133 
134 	if (!strcmp(_C_LOCALE, name)) {
135 		p = __UNCONST(&_nb_default_c);
136 	} else if (!strcmp(_POSIX_LOCALE, name)) {
137 		p = __UNCONST(&_nb_default_posix);
138 	} else {
139 		SIMPLEQ_FOREACH(p, &_nb_part_cache, entry) {
140 			if (!strcmp((const char *)&p->name[0], name))
141 				goto found;
142 		}
143 		p = malloc(sizeof(*p));
144 		if (p == NULL)
145 			return ENOMEM;
146 		if (force) {
147 			p->impl = __UNCONST(&_CATEGORY_DEFAULT);
148 		} else {
149 			_DIAGASSERT(_PathLocale != NULL);
150 			ret = _PREFIX(create_impl)((const char *)_PathLocale,
151 			    name, &p->impl);
152 			if (ret) {
153 				free(p);
154 				return ret;
155 			}
156 		}
157 		strlcpy(&p->name[0], name, sizeof(p->name));
158 		SIMPLEQ_INSERT_TAIL(&_nb_part_cache, p, entry);
159 	}
160 found:
161 	if (real != NULL) {
162 		q = malloc(sizeof(*q));
163 		if (q == NULL)
164 			return ENOMEM;
165 		strlcpy(&q->name[0], real, sizeof(p->name));
166 		q->impl = p->impl;
167 		SIMPLEQ_INSERT_TAIL(&_nb_part_cache, q, entry);
168 		p = q;
169 	}
170 	*part = p;
171 	return 0;
172 }
173 
174 static __inline int
175 _PREFIX(load)(const char * __restrict name,
176     _nb_part_t ** __restrict part)
177 {
178 	int ret, force;
179 	char path[PATH_MAX + 1], loccat[PATH_MAX + 1], buf[PATH_MAX + 1];
180 	const char *aliaspath, *alias;
181 
182 #define _LOAD_SUB_ALIAS(key)						\
183 do {									\
184 	alias = __unaliasname(aliaspath, key, &buf[0], sizeof(buf));	\
185 	if (alias != NULL) {						\
186 		ret = (force = !__isforcemapping(alias))		\
187 		    ? _PREFIX(load_sub)(name, NULL, part, force)	\
188 		    : _PREFIX(load_sub)(alias, name, part, force);	\
189 		_DIAGASSERT(!ret || !force);				\
190 		goto done;						\
191 	}								\
192 } while (/*CONSTCOND*/0)
193 
194 	/* (1) non-aliased file */
195 	mutex_lock(&_nb_mutex);
196 	ret = _PREFIX(load_sub)(name, NULL, part, 0);
197 	if (ret != ENOENT)
198 		goto done;
199 
200 	/* (2) lookup locname/catname type alias */
201 	_DIAGASSERT(_PathLocale != NULL);
202 	snprintf(&path[0], sizeof(path),
203 	    "%s/" _LOCALE_ALIAS_NAME, _PathLocale);
204 	aliaspath = (const char *)&path[0];
205 	snprintf(&loccat[0], sizeof(loccat),
206 	    "%s/" _CATEGORY_NAME, name);
207 	_LOAD_SUB_ALIAS((const char *)&loccat[0]);
208 
209 	/* (3) lookup locname type alias */
210 	_LOAD_SUB_ALIAS(name);
211 
212 done:
213 	mutex_unlock(&_nb_mutex);
214 	return ret;
215 }
216 
217 static const char *
218 _PREFIX(setlocale)(const char * __restrict name,
219     struct _locale_impl_t * __restrict locale)
220 {
221 	_nb_part_t *part;
222 
223 	/* name may be NULL */
224 	_DIAGASSERT(locale != NULL);
225 
226 	if (name != NULL) {
227 		if (*name == '\0')
228 			name = _get_locale_env(_CATEGORY_NAME);
229 		_DIAGASSERT(name != NULL);
230 		_DIAGASSERT(locale->part_name[(size_t)_CATEGORY_ID] != NULL);
231 		if (strcmp(name, locale->part_name[(size_t)_CATEGORY_ID])) {
232 			if (_PREFIX(load)(name, &part))
233 				return NULL;
234 			locale->part_name[(size_t)_CATEGORY_ID]
235 			    = &part->name[0];
236 			locale->part_impl[(size_t)_CATEGORY_ID]
237 			    = part->impl;
238 			_PREFIX(build_cache)(locale->cache, part->impl);
239 			if (locale == &_global_locale)
240 				_PREFIX(fixup)(part->impl);
241 		}
242 	}
243 	return locale->part_name[(size_t)_CATEGORY_ID];
244 }
245 
246 #include "generic_lc_template.h"
247 
248 #endif /*_NB_LC_TEMPLATE_H_*/
249