1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <assert.h>
21: #include <locale.h>
22: #include <stdlib.h>
23: #include <string.h>
24: #include <unistd.h>
25: #ifdef _POSIX_MAPPED_FILES
26: # include <sys/mman.h>
27: #endif
28:
29: #include "localeinfo.h"
30: #include "../iconv/gconv_charset.h"
31: #include "../iconv/gconv_int.h"
32:
33:
34: #ifdef NL_CURRENT_INDIRECT
35: # define DEFINE_CATEGORY(category, category_name, items, a) \
36: extern struct locale_data _nl_C_##category; \
37: weak_extern (_nl_C_##category)
38: # include "categories.def"
39: # undef DEFINE_CATEGORY
40:
41:
42:
43: struct locale_data *const _nl_C[] attribute_hidden =
44: {
45: # define DEFINE_CATEGORY(category, category_name, items, a) \
46: [category] = &_nl_C_##category,
47: # include "categories.def"
48: # undef DEFINE_CATEGORY
49: };
50: #else
51: # define _nl_C (_nl_C_locobj.__locales)
52: #endif
53:
54:
55:
56:
57: struct loaded_l10nfile *_nl_locale_file_list[__LC_LAST];
58:
59: const char _nl_default_locale_path[] attribute_hidden = LOCALEDIR;
60:
61:
62: struct locale_data *
63: internal_function
64: _nl_find_locale (const char *locale_path, size_t locale_path_len,
65: int category, const char **name)
66: {
67: int mask;
68:
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;
75: struct loaded_l10nfile *locale_file;
76:
77: if ((*name)[0] == '\0')
78: {
79:
80:
81: *name = getenv ("LC_ALL");
82: if (*name == NULL || (*name)[0] == '\0')
83: *name = getenv (_nl_category_names.str
84: + _nl_category_name_idxs[category]);
85: if (*name == NULL || (*name)[0] == '\0')
86: *name = getenv ("LANG");
87: }
88:
89: if (*name == NULL || (*name)[0] == '\0'
90: || (__builtin_expect (__libc_enable_secure, 0)
91: && strchr (*name, '/') != NULL))
92: *name = (char *) _nl_C_name;
93:
94: if (__builtin_expect (strcmp (*name, _nl_C_name), 1) == 0
95: || __builtin_expect (strcmp (*name, _nl_POSIX_name), 1) == 0)
96: {
97:
98:
99: *name = (char *) _nl_C_name;
100: return _nl_C[category];
101: }
102:
103:
104:
105: if (__builtin_expect (locale_path == NULL, 1))
106: {
107: struct locale_data *data = _nl_load_locale_from_archive (category, name);
108: if (__builtin_expect (data != NULL, 1))
109: return data;
110:
111:
112: locale_path = _nl_default_locale_path;
113: locale_path_len = sizeof _nl_default_locale_path;
114: }
115:
116:
117:
118:
119: loc_name = (char *) _nl_expand_alias (*name);
120: if (loc_name == NULL)
121:
122: loc_name = (char *) *name;
123:
124:
125: loc_name = strdupa (loc_name);
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140: mask = _nl_explode_name (loc_name, &language, &modifier, &territory,
141: &codeset, &normalized_codeset);
142:
143:
144:
145: locale_file = _nl_make_l10nflist (&_nl_locale_file_list[category],
146: locale_path, locale_path_len, mask,
147: language, territory, codeset,
148: normalized_codeset, modifier,
149: _nl_category_names.str
150: + _nl_category_name_idxs[category], 0);
151:
152: if (locale_file == NULL)
153: {
154:
155:
156: locale_file = _nl_make_l10nflist (&_nl_locale_file_list[category],
157: locale_path, locale_path_len, mask,
158: language, territory, codeset,
159: normalized_codeset, modifier,
160: _nl_category_names.str
161: + _nl_category_name_idxs[category], 1);
162: if (locale_file == NULL)
163:
164: return NULL;
165: }
166:
167:
168: if (mask & XPG_NORM_CODESET)
169: free ((void *) normalized_codeset);
170:
171: if (locale_file->decided == 0)
172: _nl_load_locale (locale_file, category);
173:
174: if (locale_file->data == NULL)
175: {
176: int cnt;
177: for (cnt = 0; locale_file->successor[cnt] != NULL; ++cnt)
178: {
179: if (locale_file->successor[cnt]->decided == 0)
180: _nl_load_locale (locale_file->successor[cnt], category);
181: if (locale_file->successor[cnt]->data != NULL)
182: break;
183: }
184:
185:
186: locale_file->successor[0] = locale_file->successor[cnt];
187: locale_file = locale_file->successor[cnt];
188:
189: if (locale_file == NULL)
190: return NULL;
191: }
192:
193:
194:
195:
196:
197:
198:
199: if (codeset != NULL)
200: {
201:
202: static const int codeset_idx[] =
203: {
204: [__LC_CTYPE] = _NL_ITEM_INDEX (CODESET),
205: [__LC_NUMERIC] = _NL_ITEM_INDEX (_NL_NUMERIC_CODESET),
206: [__LC_TIME] = _NL_ITEM_INDEX (_NL_TIME_CODESET),
207: [__LC_COLLATE] = _NL_ITEM_INDEX (_NL_COLLATE_CODESET),
208: [__LC_MONETARY] = _NL_ITEM_INDEX (_NL_MONETARY_CODESET),
209: [__LC_MESSAGES] = _NL_ITEM_INDEX (_NL_MESSAGES_CODESET),
210: [__LC_PAPER] = _NL_ITEM_INDEX (_NL_PAPER_CODESET),
211: [__LC_NAME] = _NL_ITEM_INDEX (_NL_NAME_CODESET),
212: [__LC_ADDRESS] = _NL_ITEM_INDEX (_NL_ADDRESS_CODESET),
213: [__LC_TELEPHONE] = _NL_ITEM_INDEX (_NL_TELEPHONE_CODESET),
214: [__LC_MEASUREMENT] = _NL_ITEM_INDEX (_NL_MEASUREMENT_CODESET),
215: [__LC_IDENTIFICATION] = _NL_ITEM_INDEX (_NL_IDENTIFICATION_CODESET)
216: };
217: const struct locale_data *data;
218: const char *locale_codeset;
219: char *clocale_codeset;
220: char *ccodeset;
221:
222: data = (const struct locale_data *) locale_file->data;
223: locale_codeset =
224: (const char *) data->values[codeset_idx[category]].string;
225: assert (locale_codeset != NULL);
226:
227:
228: clocale_codeset = (char *) alloca (strlen (locale_codeset) + 3);
229: strip (clocale_codeset, locale_codeset);
230:
231: ccodeset = (char *) alloca (strlen (codeset) + 3);
232: strip (ccodeset, codeset);
233:
234: if (__gconv_compare_alias (upstr (ccodeset, ccodeset),
235: upstr (clocale_codeset,
236: clocale_codeset)) != 0)
237:
238: return NULL;
239: }
240:
241:
242:
243:
244: if (((const struct locale_data *) locale_file->data)->name == NULL)
245: {
246: char *cp, *endp;
247:
248: endp = strrchr (locale_file->filename, '/');
249: cp = endp - 1;
250: while (cp[-1] != '/')
251: --cp;
252: ((struct locale_data *) locale_file->data)->name = __strndup (cp,
253: endp - cp);
254: }
255:
256:
257: if (modifier != NULL && __strcasecmp (modifier, "TRANSLIT") == 0)
258: ((struct locale_data *) locale_file->data)->use_translit = 1;
259:
260:
261: if (((const struct locale_data *) locale_file->data)->usage_count
262: < MAX_USAGE_COUNT)
263: ++((struct locale_data *) locale_file->data)->usage_count;
264:
265: return (struct locale_data *) locale_file->data;
266: }
267:
268:
269:
270:
271: void
272: internal_function
273: _nl_remove_locale (int locale, struct locale_data *data)
274: {
275: if (--data->usage_count == 0)
276: {
277: if (data->alloc != ld_archive)
278: {
279:
280: struct loaded_l10nfile *ptr = _nl_locale_file_list[locale];
281:
282:
283:
284: while ((struct locale_data *) ptr->data != data)
285: ptr = ptr->next;
286:
287:
288:
289: ptr->decided = 0;
290: ptr->data = NULL;
291: }
292:
293:
294: _nl_unload_locale (data);
295: }
296: }