]> git.ipfire.org Git - thirdparty/glibc.git/blame - locale/findlocale.c
Use <> for include of kernel-features.h.
[thirdparty/glibc.git] / locale / findlocale.c
CommitLineData
4f031072 1/* Copyright (C) 1996-2003, 2006, 2010, 2011 Free Software Foundation, Inc.
e4cf5070 2 This file is part of the GNU C Library.
4b10dd6c 3 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
7a12c6bb 4
e4cf5070 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
7a12c6bb 9
e4cf5070
UD
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
7a12c6bb 14
41bdb6e2
AJ
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
7a12c6bb 19
e7f21fa6 20#include <assert.h>
7a12c6bb
RM
21#include <locale.h>
22#include <stdlib.h>
23#include <string.h>
3081378b 24#include <unistd.h>
72c74375
UD
25#ifdef _POSIX_MAPPED_FILES
26# include <sys/mman.h>
27#endif
7a12c6bb
RM
28
29#include "localeinfo.h"
e7f21fa6 30#include "../iconv/gconv_charset.h"
dd9423a6 31#include "../iconv/gconv_int.h"
7a12c6bb
RM
32
33
9a411bf5
RM
34#ifdef NL_CURRENT_INDIRECT
35# define DEFINE_CATEGORY(category, category_name, items, a) \
f095bb72 36extern struct __locale_data _nl_C_##category; \
9a411bf5
RM
37weak_extern (_nl_C_##category)
38# include "categories.def"
39# undef DEFINE_CATEGORY
40
41/* Array indexed by category of pointers to _nl_C_CATEGORY slots.
42 Elements are zero for categories whose data is never used. */
f095bb72 43struct __locale_data *const _nl_C[] attribute_hidden =
9a411bf5
RM
44 {
45# define DEFINE_CATEGORY(category, category_name, items, a) \
46 [category] = &_nl_C_##category,
47# include "categories.def"
48# undef DEFINE_CATEGORY
49 };
30c14c31
RM
50#else
51# define _nl_C (_nl_C_locobj.__locales)
52#endif
7a12c6bb
RM
53
54
55/* For each category we keep a list of records for the locale files
56 which are somehow addressed. */
5746ef6f 57struct loaded_l10nfile *_nl_locale_file_list[__LC_LAST];
7a12c6bb 58
cb09a2cd
RM
59const char _nl_default_locale_path[] attribute_hidden = LOCALEDIR;
60
7a12c6bb 61
f095bb72 62struct __locale_data *
cb09a2cd 63internal_function
7a12c6bb 64_nl_find_locale (const char *locale_path, size_t locale_path_len,
c84142e8 65 int category, const char **name)
7a12c6bb
RM
66{
67 int mask;
68 /* Name of the locale for this category. */
69 char *loc_name;
70 const char *language;
71 const char *modifier;
72 const char *territory;
73 const char *codeset;
74 const char *normalized_codeset;
7a12c6bb
RM
75 struct loaded_l10nfile *locale_file;
76
63336471 77 if ((*name)[0] == '\0')
7a12c6bb
RM
78 {
79 /* The user decides which locale to use by setting environment
80 variables. */
81 *name = getenv ("LC_ALL");
82 if (*name == NULL || (*name)[0] == '\0')
9446614c
UD
83 *name = getenv (_nl_category_names.str
84 + _nl_category_name_idxs[category]);
7a12c6bb
RM
85 if (*name == NULL || (*name)[0] == '\0')
86 *name = getenv ("LANG");
7a12c6bb
RM
87 }
88
63336471
UD
89 if (*name == NULL || (*name)[0] == '\0'
90 || (__builtin_expect (__libc_enable_secure, 0)
6adc15f5 91 && strchr (*name, '/') != NULL))
63336471
UD
92 *name = (char *) _nl_C_name;
93
3a31f6f4
UD
94 if (__builtin_expect (strcmp (*name, _nl_C_name), 1) == 0
95 || __builtin_expect (strcmp (*name, _nl_POSIX_name), 1) == 0)
7a12c6bb
RM
96 {
97 /* We need not load anything. The needed data is contained in
98 the library itself. */
99 *name = (char *) _nl_C_name;
100 return _nl_C[category];
101 }
102
cb09a2cd
RM
103 /* We really have to load some data. First we try the archive,
104 but only if there was no LOCPATH environment variable specified. */
105 if (__builtin_expect (locale_path == NULL, 1))
106 {
f095bb72
UD
107 struct __locale_data *data
108 = _nl_load_locale_from_archive (category, name);
cb09a2cd
RM
109 if (__builtin_expect (data != NULL, 1))
110 return data;
111
112 /* Nothing in the archive. Set the default path to search below. */
113 locale_path = _nl_default_locale_path;
114 locale_path_len = sizeof _nl_default_locale_path;
115 }
116
7a12c6bb
RM
117 /* We really have to load some data. First see whether the name is
118 an alias. Please note that this makes it impossible to have "C"
119 or "POSIX" as aliases. */
fa0bc87c 120 loc_name = (char *) _nl_expand_alias (*name);
7a12c6bb
RM
121 if (loc_name == NULL)
122 /* It is no alias. */
c84142e8 123 loc_name = (char *) *name;
7a12c6bb
RM
124
125 /* Make a writable copy of the locale name. */
72c74375 126 loc_name = strdupa (loc_name);
7a12c6bb
RM
127
128 /* LOCALE can consist of up to four recognized parts for the XPG syntax:
129
130 language[_territory[.codeset]][@modifier]
131
7a12c6bb
RM
132 Beside the first all of them are allowed to be missing. If the
133 full specified locale is not found, the less specific one are
cb09a2cd 134 looked for. The various part will be stripped off according to
7a12c6bb 135 the following order:
e155c801
UD
136 (1) codeset
137 (2) normalized codeset
138 (3) territory
139 (4) modifier
7a12c6bb
RM
140 */
141 mask = _nl_explode_name (loc_name, &language, &modifier, &territory,
e155c801 142 &codeset, &normalized_codeset);
4f031072
UD
143 if (mask == -1)
144 /* Memory allocate problem. */
145 return NULL;
7a12c6bb
RM
146
147 /* If exactly this locale was already asked for we have an entry with
148 the complete name. */
5746ef6f 149 locale_file = _nl_make_l10nflist (&_nl_locale_file_list[category],
7a12c6bb
RM
150 locale_path, locale_path_len, mask,
151 language, territory, codeset,
e155c801 152 normalized_codeset, modifier,
9446614c
UD
153 _nl_category_names.str
154 + _nl_category_name_idxs[category], 0);
7a12c6bb
RM
155
156 if (locale_file == NULL)
157 {
158 /* Find status record for addressed locale file. We have to search
159 through all directories in the locale path. */
5746ef6f 160 locale_file = _nl_make_l10nflist (&_nl_locale_file_list[category],
7a12c6bb
RM
161 locale_path, locale_path_len, mask,
162 language, territory, codeset,
e155c801 163 normalized_codeset, modifier,
9446614c
UD
164 _nl_category_names.str
165 + _nl_category_name_idxs[category], 1);
7a12c6bb
RM
166 if (locale_file == NULL)
167 /* This means we are out of core. */
168 return NULL;
169 }
7a12c6bb 170
727211c4
UD
171 /* The space for normalized_codeset is dynamically allocated. Free it. */
172 if (mask & XPG_NORM_CODESET)
173 free ((void *) normalized_codeset);
174
7a12c6bb
RM
175 if (locale_file->decided == 0)
176 _nl_load_locale (locale_file, category);
177
178 if (locale_file->data == NULL)
179 {
180 int cnt;
181 for (cnt = 0; locale_file->successor[cnt] != NULL; ++cnt)
182 {
183 if (locale_file->successor[cnt]->decided == 0)
184 _nl_load_locale (locale_file->successor[cnt], category);
185 if (locale_file->successor[cnt]->data != NULL)
186 break;
187 }
188 /* Move the entry we found (or NULL) to the first place of
189 successors. */
190 locale_file->successor[0] = locale_file->successor[cnt];
191 locale_file = locale_file->successor[cnt];
7a12c6bb 192
3a31f6f4
UD
193 if (locale_file == NULL)
194 return NULL;
195 }
7a12c6bb 196
e7f21fa6
UD
197 /* The LC_CTYPE category allows to check whether a locale is really
198 usable. If the locale name contains a charset name and the
199 charset name used in the locale (present in the LC_CTYPE data) is
200 not the same (after resolving aliases etc) we reject the locale
201 since using it would irritate users expecting the charset named
202 in the locale name. */
203 if (codeset != NULL)
204 {
205 /* Get the codeset information from the locale file. */
206 static const int codeset_idx[] =
207 {
208 [__LC_CTYPE] = _NL_ITEM_INDEX (CODESET),
209 [__LC_NUMERIC] = _NL_ITEM_INDEX (_NL_NUMERIC_CODESET),
210 [__LC_TIME] = _NL_ITEM_INDEX (_NL_TIME_CODESET),
211 [__LC_COLLATE] = _NL_ITEM_INDEX (_NL_COLLATE_CODESET),
212 [__LC_MONETARY] = _NL_ITEM_INDEX (_NL_MONETARY_CODESET),
213 [__LC_MESSAGES] = _NL_ITEM_INDEX (_NL_MESSAGES_CODESET),
214 [__LC_PAPER] = _NL_ITEM_INDEX (_NL_PAPER_CODESET),
215 [__LC_NAME] = _NL_ITEM_INDEX (_NL_NAME_CODESET),
216 [__LC_ADDRESS] = _NL_ITEM_INDEX (_NL_ADDRESS_CODESET),
217 [__LC_TELEPHONE] = _NL_ITEM_INDEX (_NL_TELEPHONE_CODESET),
218 [__LC_MEASUREMENT] = _NL_ITEM_INDEX (_NL_MEASUREMENT_CODESET),
219 [__LC_IDENTIFICATION] = _NL_ITEM_INDEX (_NL_IDENTIFICATION_CODESET)
220 };
f095bb72 221 const struct __locale_data *data;
e7f21fa6
UD
222 const char *locale_codeset;
223 char *clocale_codeset;
224 char *ccodeset;
225
f095bb72 226 data = (const struct __locale_data *) locale_file->data;
e7f21fa6
UD
227 locale_codeset =
228 (const char *) data->values[codeset_idx[category]].string;
229 assert (locale_codeset != NULL);
230 /* Note the length of the allocated memory: +3 for up to two slashes
231 and the NUL byte. */
232 clocale_codeset = (char *) alloca (strlen (locale_codeset) + 3);
233 strip (clocale_codeset, locale_codeset);
234
235 ccodeset = (char *) alloca (strlen (codeset) + 3);
236 strip (ccodeset, codeset);
237
9a018f6c
UD
238 if (__gconv_compare_alias (upstr (ccodeset, ccodeset),
239 upstr (clocale_codeset,
240 clocale_codeset)) != 0)
e7f21fa6
UD
241 /* The codesets are not identical, don't use the locale. */
242 return NULL;
243 }
244
7a12c6bb
RM
245 /* Determine the locale name for which loading succeeded. This
246 information comes from the file name. The form is
036cc82f 247 <path>/<locale>/LC_foo. We must extract the <locale> part. */
f095bb72 248 if (((const struct __locale_data *) locale_file->data)->name == NULL)
7a12c6bb 249 {
036cc82f 250 char *cp, *endp;
7a12c6bb
RM
251
252 endp = strrchr (locale_file->filename, '/');
253 cp = endp - 1;
254 while (cp[-1] != '/')
255 --cp;
f095bb72
UD
256 ((struct __locale_data *) locale_file->data)->name
257 = __strndup (cp, endp - cp);
7a12c6bb 258 }
7a12c6bb 259
323fb88d 260 /* Determine whether the user wants transliteration or not. */
5f078c32
UD
261 if (modifier != NULL
262 && __strcasecmp_l (modifier, "TRANSLIT", _nl_C_locobj_ptr) == 0)
f095bb72 263 ((struct __locale_data *) locale_file->data)->use_translit = 1;
323fb88d 264
c84142e8 265 /* Increment the usage count. */
f095bb72 266 if (((const struct __locale_data *) locale_file->data)->usage_count
a5a0310d 267 < MAX_USAGE_COUNT)
f095bb72 268 ++((struct __locale_data *) locale_file->data)->usage_count;
c84142e8 269
f095bb72 270 return (struct __locale_data *) locale_file->data;
7a12c6bb 271}
c84142e8
UD
272
273
274/* Calling this function assumes the lock for handling global locale data
275 is acquired. */
276void
cb09a2cd 277internal_function
f095bb72 278_nl_remove_locale (int locale, struct __locale_data *data)
c84142e8
UD
279{
280 if (--data->usage_count == 0)
281 {
0f283ffc 282 if (data->alloc != ld_archive)
c84142e8 283 {
0f283ffc
RM
284 /* First search the entry in the list of loaded files. */
285 struct loaded_l10nfile *ptr = _nl_locale_file_list[locale];
286
287 /* Search for the entry. It must be in the list. Otherwise it
288 is a bug and we crash badly. */
f095bb72 289 while ((struct __locale_data *) ptr->data != data)
0f283ffc
RM
290 ptr = ptr->next;
291
292 /* Mark the data as not available anymore. So when the data has
293 to be used again it is reloaded. */
294 ptr->decided = 0;
295 ptr->data = NULL;
c84142e8 296 }
c84142e8 297
0f283ffc
RM
298 /* This does the real work. */
299 _nl_unload_locale (data);
c84142e8
UD
300 }
301}