1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: #ifndef _GNU_SOURCE
24: # define _GNU_SOURCE 1
25: #endif
26:
27: #ifdef HAVE_CONFIG_H
28: # include <config.h>
29: #endif
30:
31: #include <string.h>
32:
33: #if defined _LIBC || defined HAVE_ARGZ_H
34: # include <argz.h>
35: #endif
36: #include <ctype.h>
37: #include <sys/types.h>
38: #include <stdlib.h>
39:
40: #include "loadinfo.h"
41:
42:
43: #ifndef NULL
44: # if defined __STDC__ && __STDC__
45: # define NULL ((void *) 0)
46: # else
47: # define NULL 0
48: # endif
49: #endif
50:
51:
52:
53: #ifdef _LIBC
54:
55:
56:
57: # ifndef stpcpy
58: # define stpcpy(dest, src) __stpcpy(dest, src)
59: # endif
60: #else
61: # ifndef HAVE_STPCPY
62: static char *stpcpy PARAMS ((char *dest, const char *src));
63: # endif
64: #endif
65:
66:
67:
68: #if !defined _LIBC && !defined HAVE___ARGZ_COUNT
69:
70: static size_t argz_count__ PARAMS ((const char *argz, size_t len));
71:
72: static size_t
73: argz_count__ (argz, len)
74: const char *argz;
75: size_t len;
76: {
77: size_t count = 0;
78: while (len > 0)
79: {
80: size_t part_len = strlen (argz);
81: argz += part_len + 1;
82: len -= part_len + 1;
83: count++;
84: }
85: return count;
86: }
87: # undef __argz_count
88: # define __argz_count(argz, len) argz_count__ (argz, len)
89: #else
90: # ifdef _LIBC
91: # define __argz_count(argz, len) INTUSE(__argz_count) (argz, len)
92: # endif
93: #endif
94:
95: #if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
96:
97:
98: static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
99:
100: static void
101: argz_stringify__ (argz, len, sep)
102: char *argz;
103: size_t len;
104: int sep;
105: {
106: while (len > 0)
107: {
108: size_t part_len = strlen (argz);
109: argz += part_len;
110: len -= part_len + 1;
111: if (len > 0)
112: *argz++ = sep;
113: }
114: }
115: # undef __argz_stringify
116: # define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
117: #else
118: # ifdef _LIBC
119: # define __argz_stringify(argz, len, sep) \
120: INTUSE(__argz_stringify) (argz, len, sep)
121: # endif
122: #endif
123:
124: #if !defined _LIBC && !defined HAVE___ARGZ_NEXT
125: static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
126: const char *entry));
127:
128: static char *
129: argz_next__ (argz, argz_len, entry)
130: char *argz;
131: size_t argz_len;
132: const char *entry;
133: {
134: if (entry)
135: {
136: if (entry < argz + argz_len)
137: entry = strchr (entry, '\0') + 1;
138:
139: return entry >= argz + argz_len ? NULL : (char *) entry;
140: }
141: else
142: if (argz_len > 0)
143: return argz;
144: else
145: return 0;
146: }
147: # undef __argz_next
148: # define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
149: #endif
150:
151:
152:
153: static int pop PARAMS ((int x));
154:
155: static inline int
156: pop (x)
157: int x;
158: {
159:
160: x = ((x & ~0x5555) >> 1) + (x & 0x5555);
161: x = ((x & ~0x3333) >> 2) + (x & 0x3333);
162: x = ((x >> 4) + x) & 0x0f0f;
163: x = ((x >> 8) + x) & 0xff;
164:
165: return x;
166: }
167:
168: ^L
169: struct loaded_l10nfile *
170: _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
171: territory, codeset, normalized_codeset, modifier,
172: filename, do_allocate)
173: struct loaded_l10nfile **l10nfile_list;
174: const char *dirlist;
175: size_t dirlist_len;
176: int mask;
177: const char *language;
178: const char *territory;
179: const char *codeset;
180: const char *normalized_codeset;
181: const char *modifier;
182: const char *filename;
183: int do_allocate;
184: {
185: char *abs_filename;
186: struct loaded_l10nfile *last = NULL;
187: struct loaded_l10nfile *retval;
188: char *cp;
189: size_t entries;
190: int cnt;
191:
192:
193: abs_filename = (char *) malloc (dirlist_len
194: + strlen (language)
195: + ((mask & XPG_TERRITORY) != 0
196: ? strlen (territory) + 1 : 0)
197: + ((mask & XPG_CODESET) != 0
198: ? strlen (codeset) + 1 : 0)
199: + ((mask & XPG_NORM_CODESET) != 0
200: ? strlen (normalized_codeset) + 1 : 0)
201: + ((mask & XPG_MODIFIER) != 0
202: ? strlen (modifier) + 1 : 0)
203: + 1 + strlen (filename) + 1);
204:
205: if (abs_filename == NULL)
206: return NULL;
207:
208: retval = NULL;
209: last = NULL;
210:
211:
212: memcpy (abs_filename, dirlist, dirlist_len);
213: __argz_stringify (abs_filename, dirlist_len, ':');
214: cp = abs_filename + (dirlist_len - 1);
215: *cp++ = '/';
216: cp = stpcpy (cp, language);
217:
218: if ((mask & XPG_TERRITORY) != 0)
219: {
220: *cp++ = '_';
221: cp = stpcpy (cp, territory);
222: }
223: if ((mask & XPG_CODESET) != 0)
224: {
225: *cp++ = '.';
226: cp = stpcpy (cp, codeset);
227: }
228: if ((mask & XPG_NORM_CODESET) != 0)
229: {
230: *cp++ = '.';
231: cp = stpcpy (cp, normalized_codeset);
232: }
233: if ((mask & XPG_MODIFIER) != 0)
234: {
235: *cp++ = '@';
236: cp = stpcpy (cp, modifier);
237: }
238:
239: *cp++ = '/';
240: stpcpy (cp, filename);
241:
242:
243:
244: last = NULL;
245: for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
246: if (retval->filename != NULL)
247: {
248: int compare = strcmp (retval->filename, abs_filename);
249: if (compare == 0)
250:
251: break;
252: if (compare < 0)
253: {
254:
255: retval = NULL;
256: break;
257: }
258:
259: last = retval;
260: }
261:
262: if (retval != NULL || do_allocate == 0)
263: {
264: free (abs_filename);
265: return retval;
266: }
267:
268: retval = (struct loaded_l10nfile *)
269: malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len)
270: * (1 << pop (mask))
271: * sizeof (struct loaded_l10nfile *)));
272: if (retval == NULL)
273: {
274: free (abs_filename);
275: return NULL;
276: }
277:
278: retval->filename = abs_filename;
279:
280:
281:
282: retval->decided = (__argz_count (dirlist, dirlist_len) != 1
283: || ((mask & XPG_CODESET) != 0
284: && (mask & XPG_NORM_CODESET) != 0));
285: retval->data = NULL;
286:
287: if (last == NULL)
288: {
289: retval->next = *l10nfile_list;
290: *l10nfile_list = retval;
291: }
292: else
293: {
294: retval->next = last->next;
295: last->next = retval;
296: }
297:
298: entries = 0;
299:
300:
301:
302: cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask;
303: for (; cnt >= 0; --cnt)
304: if ((cnt & ~mask) == 0)
305: {
306:
307: char *dir = NULL;
308:
309: while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
310: != NULL)
311: retval->successor[entries++]
312: = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
313: language, territory, codeset,
314: normalized_codeset, modifier, filename, 1);
315: }
316: retval->successor[entries] = NULL;
317:
318: return retval;
319: }
320: ^L
321:
322:
323:
324:
325: const char *
326: _nl_normalize_codeset (codeset, name_len)
327: const char *codeset;
328: size_t name_len;
329: {
330: int len = 0;
331: int only_digit = 1;
332: char *retval;
333: char *wp;
334: size_t cnt;
335:
336: for (cnt = 0; cnt < name_len; ++cnt)
337: if (isalnum ((unsigned char) codeset[cnt]))
338: {
339: ++len;
340:
341: if (isalpha ((unsigned char) codeset[cnt]))
342: only_digit = 0;
343: }
344:
345: retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
346:
347: if (retval != NULL)
348: {
349: if (only_digit)
350: wp = stpcpy (retval, "iso");
351: else
352: wp = retval;
353:
354: for (cnt = 0; cnt < name_len; ++cnt)
355: if (isalpha ((unsigned char) codeset[cnt]))
356: *wp++ = tolower ((unsigned char) codeset[cnt]);
357: else if (isdigit ((unsigned char) codeset[cnt]))
358: *wp++ = codeset[cnt];
359:
360: *wp = '\0';
361: }
362:
363: return (const char *) retval;
364: }
365:
366:
367:
368:
369:
370:
371:
372:
373: #if !_LIBC && !HAVE_STPCPY
374: static char *
375: stpcpy (dest, src)
376: char *dest;
377: const char *src;
378: {
379: while ((*dest++ = *src++) != '\0')
380: ;
381: return dest - 1;
382: }
383: #endif