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