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 <sys/types.h>
32:
33: #ifdef __GNUC__
34: # define alloca __builtin_alloca
35: # define HAVE_ALLOCA 1
36: #else
37: # if defined HAVE_ALLOCA_H || defined _LIBC
38: # include <alloca.h>
39: # else
40: # ifdef _AIX
41: #pragma alloca
42: # else
43: # ifndef alloca
44: char *alloca ();
45: # endif
46: # endif
47: # endif
48: #endif
49:
50: #include <errno.h>
51: #ifndef errno
52: extern int errno;
53: #endif
54: #ifndef __set_errno
55: # define __set_errno(val) errno = (val)
56: #endif
57:
58: #include <stddef.h>
59: #include <stdlib.h>
60: #include <string.h>
61:
62: #if defined HAVE_UNISTD_H || defined _LIBC
63: # include <unistd.h>
64: #endif
65:
66: #include <locale.h>
67:
68: #if defined HAVE_SYS_PARAM_H || defined _LIBC
69: # include <sys/param.h>
70: #endif
71:
72: #include "gettextP.h"
73: #include "plural-exp.h"
74: #ifdef _LIBC
75: # include <libintl.h>
76: #else
77: # include "libgnuintl.h"
78: #endif
79: #include "hash-string.h"
80:
81:
82: #ifdef _LIBC
83: # include <bits/libc-lock.h>
84: #else
85:
86: # define __libc_lock_define_initialized(CLASS, NAME)
87: # define __libc_lock_lock(NAME)
88: # define __libc_lock_unlock(NAME)
89: # define __libc_rwlock_define_initialized(CLASS, NAME)
90: # define __libc_rwlock_rdlock(NAME)
91: # define __libc_rwlock_unlock(NAME)
92: #endif
93:
94:
95: #if defined __GNUC__ && __GNUC__ >= 2
96: # define alignof(TYPE) __alignof__ (TYPE)
97: #else
98: # define alignof(TYPE) \
99: ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
100: #endif
101:
102:
103:
104:
105: #if !defined _LIBC
106: # define _nl_default_default_domain libintl_nl_default_default_domain
107: # define _nl_current_default_domain libintl_nl_current_default_domain
108: # define _nl_default_dirname libintl_nl_default_dirname
109: # define _nl_domain_bindings libintl_nl_domain_bindings
110: #endif
111:
112:
113: #ifndef offsetof
114: # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
115: #endif
116:
117:
118:
119: #ifdef _LIBC
120:
121:
122:
123: # define getcwd __getcwd
124: # ifndef stpcpy
125: # define stpcpy __stpcpy
126: # endif
127: # define tfind __tfind
128: #else
129: # if !defined HAVE_GETCWD
130: char *getwd ();
131: # define getcwd(buf, max) getwd (buf)
132: # else
133: char *getcwd ();
134: # endif
135: # ifndef HAVE_STPCPY
136: static char *stpcpy PARAMS ((char *dest, const char *src));
137: # endif
138: # ifndef HAVE_MEMPCPY
139: static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
140: # endif
141: #endif
142:
143:
144: #define PATH_INCR 32
145:
146:
147:
148:
149:
150: #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
151: # include <limits.h>
152: #endif
153:
154: #ifndef _POSIX_PATH_MAX
155: # define _POSIX_PATH_MAX 255
156: #endif
157:
158: #if !defined PATH_MAX && defined _PC_PATH_MAX
159: # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
160: #endif
161:
162:
163: #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
164: # include <sys/param.h>
165: #endif
166:
167: #if !defined PATH_MAX && defined MAXPATHLEN
168: # define PATH_MAX MAXPATHLEN
169: #endif
170:
171: #ifndef PATH_MAX
172: # define PATH_MAX _POSIX_PATH_MAX
173: #endif
174:
175:
176: #if defined _LIBC || HAVE_NL_LOCALE_NAME
177: # define HAVE_PER_THREAD_LOCALE
178: #endif
179:
180:
181:
182: struct known_translation_t
183: {
184:
185: const char *domainname;
186:
187:
188: int category;
189:
190: #ifdef HAVE_PER_THREAD_LOCALE
191:
192: const char *localename;
193: #endif
194:
195:
196: int counter;
197:
198:
199: struct loaded_l10nfile *domain;
200:
201:
202: const char *translation;
203: size_t translation_length;
204:
205:
206: char msgid[ZERO];
207: };
208:
209:
210:
211: #if defined HAVE_TSEARCH || defined _LIBC
212: # include <search.h>
213:
214: static void *root;
215:
216: # ifdef _LIBC
217: # define tsearch __tsearch
218: # endif
219:
220:
221: static int transcmp PARAMS ((const void *p1, const void *p2));
222: static int
223: transcmp (p1, p2)
224: const void *p1;
225: const void *p2;
226: {
227: const struct known_translation_t *s1;
228: const struct known_translation_t *s2;
229: int result;
230:
231: s1 = (const struct known_translation_t *) p1;
232: s2 = (const struct known_translation_t *) p2;
233:
234: result = strcmp (s1->msgid, s2->msgid);
235: if (result == 0)
236: {
237: result = strcmp (s1->domainname, s2->domainname);
238: if (result == 0)
239: {
240: #ifdef HAVE_PER_THREAD_LOCALE
241: result = strcmp (s1->localename, s2->localename);
242: if (result == 0)
243: #endif
244:
245:
246:
247: result = s1->category - s2->category;
248: }
249: }
250:
251: return result;
252: }
253: #endif
254:
255:
256:
257: const char _nl_default_default_domain[] attribute_hidden = "messages";
258:
259:
260: const char *_nl_current_default_domain attribute_hidden
261: = _nl_default_default_domain;
262:
263:
264:
265: #ifdef _LIBC
266: extern const char _nl_default_dirname[];
267: libc_hidden_proto (_nl_default_dirname)
268: #endif
269: const char _nl_default_dirname[] = LOCALEDIR;
270: #ifdef _LIBC
271: libc_hidden_data_def (_nl_default_dirname)
272: #endif
273:
274:
275:
276: struct binding *_nl_domain_bindings;
277:
278:
279: static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
280: unsigned long int n,
281: const char *translation,
282: size_t translation_len))
283: internal_function;
284: static const char *guess_category_value PARAMS ((int category,
285: const char *categoryname))
286: internal_function;
287: #ifdef _LIBC
288: # include "../locale/localeinfo.h"
289: # define category_to_name(category) \
290: _nl_category_names.str + _nl_category_name_idxs[category]
291: #else
292: static const char *category_to_name PARAMS ((int category)) internal_function;
293: #endif
294:
295:
296:
297:
298: #ifdef HAVE_ALLOCA
299:
300: # define freea(p)
301: # define ADD_BLOCK(list, address)
302: # define FREE_BLOCKS(list)
303: #else
304: struct block_list
305: {
306: void *address;
307: struct block_list *next;
308: };
309: # define ADD_BLOCK(list, addr) \
310: do { \
311: struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
312:
313: \
314: if (newp != NULL) { \
315: newp->address = (addr); \
316: newp->next = (list); \
317: (list) = newp; \
318: } \
319: } while (0)
320: # define FREE_BLOCKS(list) \
321: do { \
322: while (list != NULL) { \
323: struct block_list *old = list; \
324: list = list->next; \
325: free (old->address); \
326: free (old); \
327: } \
328: } while (0)
329: # undef alloca
330: # define alloca(size) (malloc (size))
331: # define freea(p) free (p)
332: #endif
333:
334:
335: #ifdef _LIBC
336:
337: typedef struct transmem_list
338: {
339: struct transmem_list *next;
340: char data[ZERO];
341: } transmem_block_t;
342: static struct transmem_list *transmem_list;
343: #else
344: typedef unsigned char transmem_block_t;
345: #endif
346: #if defined _LIBC || HAVE_ICONV
347: static const char *get_output_charset PARAMS ((struct binding *domainbinding))
348: internal_function;
349: #endif
350:
351:
352:
353:
354:
355:
356: #ifdef _LIBC
357: # define DCIGETTEXT __dcigettext
358: #else
359: # define DCIGETTEXT libintl_dcigettext
360: #endif
361:
362:
363: #ifdef _LIBC
364: __libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
365: #endif
366:
367:
368:
369: #ifdef _LIBC
370: # define ENABLE_SECURE __libc_enable_secure
371: # define DETERMINE_SECURE
372: #else
373: # ifndef HAVE_GETUID
374: # define getuid() 0
375: # endif
376: # ifndef HAVE_GETGID
377: # define getgid() 0
378: # endif
379: # ifndef HAVE_GETEUID
380: # define geteuid() getuid()
381: # endif
382: # ifndef HAVE_GETEGID
383: # define getegid() getgid()
384: # endif
385: static int enable_secure;
386: # define ENABLE_SECURE (enable_secure == 1)
387: # define DETERMINE_SECURE \
388: if (enable_secure == 0) \
389: { \
390: if (getuid () != geteuid () || getgid () != getegid ()) \
391: enable_secure = 1; \
392: else \
393: enable_secure = -1; \
394: }
395: #endif
396:
397:
398: #include "plural-eval.c"
399:
400:
401:
402:
403: char *
404: DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
405: const char *domainname;
406: const char *msgid1;
407: const char *msgid2;
408: int plural;
409: unsigned long int n;
410: int category;
411: {
412: #ifndef HAVE_ALLOCA
413: struct block_list *block_list = NULL;
414: #endif
415: struct loaded_l10nfile *domain;
416: struct binding *binding;
417: const char *categoryname;
418: const char *categoryvalue;
419: char *dirname, *xdomainname;
420: char *single_locale;
421: char *retval;
422: size_t retlen;
423: int saved_errno;
424: #if defined HAVE_TSEARCH || defined _LIBC
425: struct known_translation_t *search;
426: struct known_translation_t **foundp = NULL;
427: size_t msgid_len;
428: # ifdef HAVE_PER_THREAD_LOCALE
429: const char *localename;
430: # endif
431: #endif
432: size_t domainname_len;
433:
434:
435: if (msgid1 == NULL)
436: return NULL;
437:
438: #ifdef _LIBC
439: if (category < 0 || category >= __LC_LAST || category == LC_ALL)
440:
441: return (plural == 0
442: ? (char *) msgid1
443:
444: : n == 1 ? (char *) msgid1 : (char *) msgid2);
445: #endif
446:
447: __libc_rwlock_rdlock (_nl_state_lock);
448:
449:
450:
451:
452: if (domainname == NULL)
453: domainname = _nl_current_default_domain;
454:
455: #if defined HAVE_TSEARCH || defined _LIBC
456: msgid_len = strlen (msgid1) + 1;
457:
458:
459:
460: search = (struct known_translation_t *)
461: alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
462: memcpy (search->msgid, msgid1, msgid_len);
463: search->domainname = domainname;
464: search->category = category;
465: # ifdef HAVE_PER_THREAD_LOCALE
466: # ifdef _LIBC
467: localename = __current_locale_name (category);
468: # endif
469: search->localename = localename;
470: # endif
471:
472:
473:
474: __libc_rwlock_define_initialized (static, tree_lock);
475: __libc_rwlock_rdlock (tree_lock);
476:
477: foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
478:
479: __libc_rwlock_unlock (tree_lock);
480:
481: freea (search);
482: if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
483: {
484:
485: if (plural)
486: retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
487: (*foundp)->translation_length);
488: else
489: retval = (char *) (*foundp)->translation;
490:
491: __libc_rwlock_unlock (_nl_state_lock);
492: return retval;
493: }
494: #endif
495:
496:
497: saved_errno = errno;
498:
499:
500: DETERMINE_SECURE;
501:
502:
503: for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
504: {
505: int compare = strcmp (domainname, binding->domainname);
506: if (compare == 0)
507:
508: break;
509: if (compare < 0)
510: {
511:
512: binding = NULL;
513: break;
514: }
515: }
516:
517: if (binding == NULL)
518: dirname = (char *) _nl_default_dirname;
519: else if (binding->dirname[0] == '/')
520: dirname = binding->dirname;
521: else
522: {
523:
524: size_t dirname_len = strlen (binding->dirname) + 1;
525: size_t path_max;
526: char *ret;
527:
528: path_max = (unsigned int) PATH_MAX;
529: path_max += 2;
530:
531: for (;;)
532: {
533: dirname = (char *) alloca (path_max + dirname_len);
534: ADD_BLOCK (block_list, dirname);
535:
536: __set_errno (0);
5