1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22: #include <argz.h>
23: #include <bits/libc-lock.h>
24: #include <errno.h>
25: #include <locale.h>
26: #include <stdlib.h>
27: #include <string.h>
28:
29: #include "localeinfo.h"
30:
31:
32:
33: __libc_lock_define (extern , __libc_setlocale_lock attribute_hidden)
34:
35:
36:
37: #define ERROR_RETURN \
38: do { \
39: __set_errno (EINVAL); \
40: return NULL; \
41: } while (0)
42:
43:
44: __locale_t
45: __newlocale (int category_mask, const char *locale, __locale_t base)
46: {
47:
48: const char *newnames[__LC_LAST];
49: struct __locale_struct result;
50: __locale_t result_ptr;
51: char *locale_path;
52: size_t locale_path_len;
53: const char *locpath_var;
54: int cnt;
55: size_t names_len;
56:
57:
58: if (category_mask == 1 << LC_ALL)
59: category_mask = (1 << __LC_LAST) - 1 - (1 << LC_ALL);
60:
61:
62: if ((category_mask & ~((1 << __LC_LAST) - 1 - (1 << LC_ALL))) != 0)
63: ERROR_RETURN;
64:
65:
66: if (locale == NULL)
67: ERROR_RETURN;
68:
69: if (base == _nl_C_locobj_ptr)
70:
71:
72:
73: base = NULL;
74:
75: if ((base == NULL || category_mask == (1 << __LC_LAST) - 1 - (1 << LC_ALL))
76: && (category_mask == 0 || !strcmp (locale, "C")))
77:
78: return _nl_C_locobj_ptr;
79:
80:
81: if (base != NULL)
82: result = *base;
83: else
84:
85: result = _nl_C_locobj;
86:
87:
88:
89: if (category_mask == 0)
90: {
91: result_ptr = (__locale_t) malloc (sizeof (struct __locale_struct));
92: if (result_ptr == NULL)
93: return NULL;
94: *result_ptr = result;
95:
96: goto update;
97: }
98:
99:
100:
101:
102:
103:
104: locale_path = NULL;
105: locale_path_len = 0;
106:
107: locpath_var = getenv ("LOCPATH");
108: if (locpath_var != NULL && locpath_var[0] != '\0')
109: {
110: if (__argz_create_sep (locpath_var, ':',
111: &locale_path, &locale_path_len) != 0)
112: return NULL;
113:
114: if (__argz_add_sep (&locale_path, &locale_path_len,
115: _nl_default_locale_path, ':') != 0)
116: return NULL;
117: }
118:
119:
120:
121: for (cnt = 0; cnt < __LC_LAST; ++cnt)
122: if (cnt != LC_ALL)
123: newnames[cnt] = locale;
124: if (strchr (locale, ';') != NULL)
125: {
126:
127: char *np = strdupa (locale);
128: char *cp;
129: int specified_mask = 0;
130:
131: while ((cp = strchr (np, '=')) != NULL)
132: {
133: for (cnt = 0; cnt < __LC_LAST; ++cnt)
134: if (cnt != LC_ALL
135: && (size_t) (cp - np) == _nl_category_name_sizes[cnt]
136: && memcmp (np, (_nl_category_names.str
137: + _nl_category_name_idxs[cnt]), cp - np) == 0)
138: break;
139:
140: if (cnt == __LC_LAST)
141:
142: ERROR_RETURN;
143:
144:
145: specified_mask |= 1 << cnt;
146: newnames[cnt] = ++cp;
147: cp = strchr (cp, ';');
148: if (cp != NULL)
149: {
150:
151: *cp = '\0';
152: np = cp + 1;
153: }
154: else
155:
156: break;
157: }
158:
159: if (category_mask &~ specified_mask)
160:
161: ERROR_RETURN;
162: }
163:
164:
165: __libc_lock_lock (__libc_setlocale_lock);
166:
167:
168: names_len = 0;
169: for (cnt = 0; cnt < __LC_LAST; ++cnt)
170: {
171: if ((category_mask & 1 << cnt) != 0)
172: {
173: result.__locales[cnt] = _nl_find_locale (locale_path,
174: locale_path_len,
175: cnt, &newnames[cnt]);
176: if (result.__locales[cnt] == NULL)
177: {
178: free_cnt_data_and_exit:
179: while (cnt-- > 0)
180: if (((category_mask & 1 << cnt) != 0)
181: && result.__locales[cnt]->usage_count != UNDELETABLE)
182:
183: _nl_remove_locale (cnt, result.__locales[cnt]);
184:
185:
186: __libc_lock_unlock (__libc_setlocale_lock);
187: return NULL;
188: }
189:
190: if (newnames[cnt] != _nl_C_name)
191: names_len += strlen (newnames[cnt]) + 1;
192: }
193: else if (cnt != LC_ALL && result.__names[cnt] != _nl_C_name)
194:
195: names_len += strlen (result.__names[cnt]) + 1;
196: }
197:
198:
199:
200:
201:
202:
203: result_ptr = malloc (sizeof (struct __locale_struct) + names_len);
204: if (result_ptr == NULL)
205: {
206: cnt = __LC_LAST;
207: goto free_cnt_data_and_exit;
208: }
209:
210: if (base == NULL)
211: {
212:
213:
214: char *namep = (char *) (result_ptr + 1);
215:
216:
217:
218: for (cnt = 0; cnt < __LC_LAST; ++cnt)
219: if ((category_mask & 1 << cnt) != 0 && newnames[cnt] != _nl_C_name)
220: {
221: result.__names[cnt] = namep;
222: namep = __stpcpy (namep, newnames[cnt]) + 1;
223: }
224:
225: *result_ptr = result;
226: }
227: else
228: {
229:
230:
231: char *namep = (char *) (result_ptr + 1);
232:
233: for (cnt = 0; cnt < __LC_LAST; ++cnt)
234: if ((category_mask & 1 << cnt) != 0)
235: {
236: if (base->__locales[cnt]->usage_count != UNDELETABLE)
237:
238: _nl_remove_locale (cnt, base->__locales[cnt]);
239: result_ptr->__locales[cnt] = result.__locales[cnt];
240:
241: if (newnames[cnt] == _nl_C_name)
242: result_ptr->__names[cnt] = _nl_C_name;
243: else
244: {
245: result_ptr->__names[cnt] = namep;
246: namep = __stpcpy (namep, newnames[cnt]) + 1;
247: }
248: }
249: else if (cnt != LC_ALL)
250: {
251:
252: result_ptr->__locales[cnt] = result.__locales[cnt];
253: if (result.__names[cnt] == _nl_C_name)
254: result_ptr->__names[cnt] = _nl_C_name;
255: else
256: {
257: result_ptr->__names[cnt] = namep;
258: namep = __stpcpy (namep, result.__names[cnt]) + 1;
259: }
260: }
261:
262: free (base);
263: }
264:
265:
266: __libc_lock_unlock (__libc_setlocale_lock);
267:
268:
269: update:
270: {
271: union locale_data_value *ctypes = result_ptr->__locales[LC_CTYPE]->values;
272: result_ptr->__ctype_b = (const unsigned short int *)
273: ctypes[_NL_ITEM_INDEX (_NL_CTYPE_CLASS)].string + 128;
274: result_ptr->__ctype_tolower = (const int *)
275: ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOLOWER)].string + 128;
276: result_ptr->__ctype_toupper = (const int *)
277: ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOUPPER)].string + 128;
278: }
279:
280: return result_ptr;
281: }
282: weak_alias (__newlocale, newlocale)