1/* $NetBSD: nb_lc_template.h,v 1.2 2009/01/11 02:46:29 christos 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
99typedef 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
105static SIMPLEQ_HEAD(, _nb_part_t) _nb_part_cache =
106    SIMPLEQ_HEAD_INITIALIZER(_nb_part_cache);
107
108static const _nb_part_t _nb_default_c = {
109    _C_LOCALE,
110    __UNCONST(&_CATEGORY_DEFAULT),
111    { NULL },
112};
113
114static const _nb_part_t _nb_default_posix = {
115    _POSIX_LOCALE,
116    __UNCONST(&_CATEGORY_DEFAULT),
117    { NULL },
118};
119
120#ifdef _REENTRANT
121static mutex_t _nb_mutex = MUTEX_INITIALIZER;
122#endif
123
124static 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	}
160found:
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
174static __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)						\
183do {									\
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
212done:
213	mutex_unlock(&_nb_mutex);
214	return ret;
215}
216
217static 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