]> git.ipfire.org Git - thirdparty/glibc.git/blob - intl/dcigettext.c
* intl/tst-gettext3.c: New file.
[thirdparty/glibc.git] / intl / dcigettext.c
1 /* Implementation of the internal dcigettext function.
2 Copyright (C) 1995-2002,2003,2004,2005 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
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.
9
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
13 Lesser General Public License for more details.
14
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. */
19
20 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
21 This must come before <config.h> because <config.h> may include
22 <features.h>, and once <features.h> has been included, it's too late. */
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 /* Thread safetyness. */
82 #ifdef _LIBC
83 # include <bits/libc-lock.h>
84 #else
85 /* Provide dummy implementation if this is outside glibc. */
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 /* Alignment of types. */
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 /* The internal variables in the standalone libintl.a must have different
103 names than the internal variables in GNU libc, otherwise programs
104 using libintl.a cannot be linked statically. */
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 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
113 #ifndef offsetof
114 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
115 #endif
116
117 /* @@ end of prolog @@ */
118
119 #ifdef _LIBC
120 /* Rename the non ANSI C functions. This is required by the standard
121 because some ANSI C functions will require linking with this object
122 file and the name space must not be polluted. */
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 /* Amount to increase buffer size by in each try. */
144 #define PATH_INCR 32
145
146 /* The following is from pathmax.h. */
147 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
148 PATH_MAX but might cause redefinition warnings when sys/param.h is
149 later included (as on MORE/BSD 4.3). */
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 /* Don't include sys/param.h if it already has been. */
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 /* This is the type used for the search tree where known translations
176 are stored. */
177 struct known_translation_t
178 {
179 /* Domain in which to search. */
180 const char *domainname;
181
182 /* The category. */
183 int category;
184
185 /* State of the catalog counter at the point the string was found. */
186 int counter;
187
188 /* Catalog where the string was found. */
189 struct loaded_l10nfile *domain;
190
191 /* And finally the translation. */
192 const char *translation;
193 size_t translation_length;
194
195 /* Pointer to the string in question. */
196 char msgid[ZERO];
197 };
198
199 /* Root of the search tree with known translations. We can use this
200 only if the system provides the `tsearch' function family. */
201 #if defined HAVE_TSEARCH || defined _LIBC
202 # include <search.h>
203
204 static void *root;
205
206 # ifdef _LIBC
207 # define tsearch __tsearch
208 # endif
209
210 /* Function to compare two entries in the table of known translations. */
211 static int transcmp PARAMS ((const void *p1, const void *p2));
212 static int
213 transcmp (p1, p2)
214 const void *p1;
215 const void *p2;
216 {
217 const struct known_translation_t *s1;
218 const struct known_translation_t *s2;
219 int result;
220
221 s1 = (const struct known_translation_t *) p1;
222 s2 = (const struct known_translation_t *) p2;
223
224 result = strcmp (s1->msgid, s2->msgid);
225 if (result == 0)
226 {
227 result = strcmp (s1->domainname, s2->domainname);
228 if (result == 0)
229 /* We compare the category last (though this is the cheapest
230 operation) since it is hopefully always the same (namely
231 LC_MESSAGES). */
232 result = s1->category - s2->category;
233 }
234
235 return result;
236 }
237 #endif
238
239 /* Name of the default domain used for gettext(3) prior any call to
240 textdomain(3). The default value for this is "messages". */
241 const char _nl_default_default_domain[] attribute_hidden = "messages";
242
243 /* Value used as the default domain for gettext(3). */
244 const char *_nl_current_default_domain attribute_hidden
245 = _nl_default_default_domain;
246
247 /* Contains the default location of the message catalogs. */
248
249 #ifdef _LIBC
250 extern const char _nl_default_dirname[];
251 libc_hidden_proto (_nl_default_dirname)
252 #endif
253 const char _nl_default_dirname[] = LOCALEDIR;
254 #ifdef _LIBC
255 libc_hidden_data_def (_nl_default_dirname)
256 #endif
257
258 /* List with bindings of specific domains created by bindtextdomain()
259 calls. */
260 struct binding *_nl_domain_bindings;
261
262 /* Prototypes for local functions. */
263 static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
264 unsigned long int n,
265 const char *translation,
266 size_t translation_len))
267 internal_function;
268 static const char *guess_category_value PARAMS ((int category,
269 const char *categoryname))
270 internal_function;
271 #ifdef _LIBC
272 # include "../locale/localeinfo.h"
273 # define category_to_name(category) _nl_category_names[category]
274 #else
275 static const char *category_to_name PARAMS ((int category)) internal_function;
276 #endif
277
278
279 /* For those loosing systems which don't have `alloca' we have to add
280 some additional code emulating it. */
281 #ifdef HAVE_ALLOCA
282 /* Nothing has to be done. */
283 # define freea(p) /* nothing */
284 # define ADD_BLOCK(list, address) /* nothing */
285 # define FREE_BLOCKS(list) /* nothing */
286 #else
287 struct block_list
288 {
289 void *address;
290 struct block_list *next;
291 };
292 # define ADD_BLOCK(list, addr) \
293 do { \
294 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
295 /* If we cannot get a free block we cannot add the new element to \
296 the list. */ \
297 if (newp != NULL) { \
298 newp->address = (addr); \
299 newp->next = (list); \
300 (list) = newp; \
301 } \
302 } while (0)
303 # define FREE_BLOCKS(list) \
304 do { \
305 while (list != NULL) { \
306 struct block_list *old = list; \
307 list = list->next; \
308 free (old->address); \
309 free (old); \
310 } \
311 } while (0)
312 # undef alloca
313 # define alloca(size) (malloc (size))
314 # define freea(p) free (p)
315 #endif /* have alloca */
316
317
318 #ifdef _LIBC
319 /* List of blocks allocated for translations. */
320 typedef struct transmem_list
321 {
322 struct transmem_list *next;
323 char data[ZERO];
324 } transmem_block_t;
325 static struct transmem_list *transmem_list;
326 #else
327 typedef unsigned char transmem_block_t;
328 #endif
329 #if defined _LIBC || HAVE_ICONV
330 static const char *get_output_charset PARAMS ((struct binding *domainbinding))
331 internal_function;
332 #endif
333
334
335 /* Names for the libintl functions are a problem. They must not clash
336 with existing names and they should follow ANSI C. But this source
337 code is also used in GNU C Library where the names have a __
338 prefix. So we have to make a difference here. */
339 #ifdef _LIBC
340 # define DCIGETTEXT __dcigettext
341 #else
342 # define DCIGETTEXT libintl_dcigettext
343 #endif
344
345 /* Lock variable to protect the global data in the gettext implementation. */
346 #ifdef _LIBC
347 __libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
348 #endif
349
350 /* Checking whether the binaries runs SUID must be done and glibc provides
351 easier methods therefore we make a difference here. */
352 #ifdef _LIBC
353 # define ENABLE_SECURE __libc_enable_secure
354 # define DETERMINE_SECURE
355 #else
356 # ifndef HAVE_GETUID
357 # define getuid() 0
358 # endif
359 # ifndef HAVE_GETGID
360 # define getgid() 0
361 # endif
362 # ifndef HAVE_GETEUID
363 # define geteuid() getuid()
364 # endif
365 # ifndef HAVE_GETEGID
366 # define getegid() getgid()
367 # endif
368 static int enable_secure;
369 # define ENABLE_SECURE (enable_secure == 1)
370 # define DETERMINE_SECURE \
371 if (enable_secure == 0) \
372 { \
373 if (getuid () != geteuid () || getgid () != getegid ()) \
374 enable_secure = 1; \
375 else \
376 enable_secure = -1; \
377 }
378 #endif
379
380 /* Get the function to evaluate the plural expression. */
381 #include "plural-eval.c"
382
383 /* Look up MSGID in the DOMAINNAME message catalog for the current
384 CATEGORY locale and, if PLURAL is nonzero, search over string
385 depending on the plural form determined by N. */
386 char *
387 DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
388 const char *domainname;
389 const char *msgid1;
390 const char *msgid2;
391 int plural;
392 unsigned long int n;
393 int category;
394 {
395 #ifndef HAVE_ALLOCA
396 struct block_list *block_list = NULL;
397 #endif
398 struct loaded_l10nfile *domain;
399 struct binding *binding;
400 const char *categoryname;
401 const char *categoryvalue;
402 char *dirname, *xdomainname;
403 char *single_locale;
404 char *retval;
405 size_t retlen;
406 int saved_errno;
407 #if defined HAVE_TSEARCH || defined _LIBC
408 struct known_translation_t *search;
409 struct known_translation_t **foundp = NULL;
410 size_t msgid_len;
411 #endif
412 size_t domainname_len;
413
414 /* If no real MSGID is given return NULL. */
415 if (msgid1 == NULL)
416 return NULL;
417
418 #ifdef _LIBC
419 if (category < 0 || category >= __LC_LAST || category == LC_ALL)
420 /* Bogus. */
421 return (plural == 0
422 ? (char *) msgid1
423 /* Use the Germanic plural rule. */
424 : n == 1 ? (char *) msgid1 : (char *) msgid2);
425 #endif
426
427 __libc_rwlock_rdlock (_nl_state_lock);
428
429 /* If DOMAINNAME is NULL, we are interested in the default domain. If
430 CATEGORY is not LC_MESSAGES this might not make much sense but the
431 definition left this undefined. */
432 if (domainname == NULL)
433 domainname = _nl_current_default_domain;
434
435 #if defined HAVE_TSEARCH || defined _LIBC
436 msgid_len = strlen (msgid1) + 1;
437
438 /* Try to find the translation among those which we found at
439 some time. */
440 search = (struct known_translation_t *)
441 alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
442 memcpy (search->msgid, msgid1, msgid_len);
443 search->domainname = domainname;
444 search->category = category;
445
446 /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
447 tsearch calls can be fatal. */
448 __libc_rwlock_define_initialized (static, tree_lock);
449 __libc_rwlock_rdlock (tree_lock);
450
451 foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
452
453 __libc_rwlock_unlock (tree_lock);
454
455 freea (search);
456 if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
457 {
458 /* Now deal with plural. */
459 if (plural)
460 retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
461 (*foundp)->translation_length);
462 else
463 retval = (char *) (*foundp)->translation;
464
465 __libc_rwlock_unlock (_nl_state_lock);
466 return retval;
467 }
468 #endif
469
470 /* Preserve the `errno' value. */
471 saved_errno = errno;
472
473 /* See whether this is a SUID binary or not. */
474 DETERMINE_SECURE;
475
476 /* First find matching binding. */
477 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
478 {
479 int compare = strcmp (domainname, binding->domainname);
480 if (compare == 0)
481 /* We found it! */
482 break;
483 if (compare < 0)
484 {
485 /* It is not in the list. */
486 binding = NULL;
487 break;
488 }
489 }
490
491 if (binding == NULL)
492 dirname = (char *) _nl_default_dirname;
493 else if (binding->dirname[0] == '/')
494 dirname = binding->dirname;
495 else
496 {
497 /* We have a relative path. Make it absolute now. */
498 size_t dirname_len = strlen (binding->dirname) + 1;
499 size_t path_max;
500 char *ret;
501
502 path_max = (unsigned int) PATH_MAX;
503 path_max += 2; /* The getcwd docs say to do this. */
504
505 for (;;)
506 {
507 dirname = (char *) alloca (path_max + dirname_len);
508 ADD_BLOCK (block_list, dirname);
509
510 __set_errno (0);
511 ret = getcwd (dirname, path_max);
512 if (ret != NULL || errno != ERANGE)
513 break;
514
515 path_max += path_max / 2;
516 path_max += PATH_INCR;
517 }
518
519 if (ret == NULL)
520 {
521 /* We cannot get the current working directory. Don't signal an
522 error but simply return the default string. */
523 FREE_BLOCKS (block_list);
524 __libc_rwlock_unlock (_nl_state_lock);
525 __set_errno (saved_errno);
526 return (plural == 0
527 ? (char *) msgid1
528 /* Use the Germanic plural rule. */
529 : n == 1 ? (char *) msgid1 : (char *) msgid2);
530 }
531
532 stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
533 }
534
535 /* Now determine the symbolic name of CATEGORY and its value. */
536 categoryname = category_to_name (category);
537 categoryvalue = guess_category_value (category, categoryname);
538
539 domainname_len = strlen (domainname);
540 xdomainname = (char *) alloca (strlen (categoryname)
541 + domainname_len + 5);
542 ADD_BLOCK (block_list, xdomainname);
543
544 stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
545 domainname, domainname_len),
546 ".mo");
547
548 /* Creating working area. */
549 single_locale = (char *) alloca (strlen (categoryvalue) + 1);
550 ADD_BLOCK (block_list, single_locale);
551
552
553 /* Search for the given string. This is a loop because we perhaps
554 got an ordered list of languages to consider for the translation. */
555 while (1)
556 {
557 /* Make CATEGORYVALUE point to the next element of the list. */
558 while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
559 ++categoryvalue;
560 if (categoryvalue[0] == '\0')
561 {
562 /* The whole contents of CATEGORYVALUE has been searched but
563 no valid entry has been found. We solve this situation
564 by implicitly appending a "C" entry, i.e. no translation
565 will take place. */
566 single_locale[0] = 'C';
567 single_locale[1] = '\0';
568 }
569 else
570 {
571 char *cp = single_locale;
572 while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
573 *cp++ = *categoryvalue++;
574 *cp = '\0';
575
576 /* When this is a SUID binary we must not allow accessing files
577 outside the dedicated directories. */
578 if (ENABLE_SECURE && strchr (single_locale, '/') != NULL)
579 /* Ingore this entry. */
580 continue;
581 }
582
583 /* If the current locale value is C (or POSIX) we don't load a
584 domain. Return the MSGID. */
585 if (strcmp (single_locale, "C") == 0
586 || strcmp (single_locale, "POSIX") == 0)
587 {
588 FREE_BLOCKS (block_list);
589 __libc_rwlock_unlock (_nl_state_lock);
590 __set_errno (saved_errno);
591 return (plural == 0
592 ? (char *) msgid1
593 /* Use the Germanic plural rule. */
594 : n == 1 ? (char *) msgid1 : (char *) msgid2);
595 }
596
597
598 /* Find structure describing the message catalog matching the
599 DOMAINNAME and CATEGORY. */
600 domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
601
602 if (domain != NULL)
603 {
604 retval = _nl_find_msg (domain, binding, msgid1, 1, &retlen);
605
606 if (retval == NULL)
607 {
608 int cnt;
609
610 for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
611 {
612 retval = _nl_find_msg (domain->successor[cnt], binding,
613 msgid1, 1, &retlen);
614
615 if (retval != NULL)
616 {
617 domain = domain->successor[cnt];
618 break;
619 }
620 }
621 }
622
623 if (retval != NULL)
624 {
625 /* Found the translation of MSGID1 in domain DOMAIN:
626 starting at RETVAL, RETLEN bytes. */
627 FREE_BLOCKS (block_list);
628 #if defined HAVE_TSEARCH || defined _LIBC
629 if (foundp == NULL)
630 {
631 /* Create a new entry and add it to the search tree. */
632 struct known_translation_t *newp;
633
634 newp = (struct known_translation_t *)
635 malloc (offsetof (struct known_translation_t, msgid)
636 + msgid_len + domainname_len + 1);
637 if (newp != NULL)
638 {
639 char *new_domainname;
640
641 new_domainname = mempcpy (newp->msgid, msgid1, msgid_len);
642 memcpy (new_domainname, domainname, domainname_len + 1);
643 newp->domainname = new_domainname;
644 newp->category = category;
645 newp->counter = _nl_msg_cat_cntr;
646 newp->domain = domain;
647 newp->translation = retval;
648 newp->translation_length = retlen;
649
650 __libc_rwlock_wrlock (tree_lock);
651
652 /* Insert the entry in the search tree. */
653 foundp = (struct known_translation_t **)
654 tsearch (newp, &root, transcmp);
655
656 __libc_rwlock_unlock (tree_lock);
657
658 if (foundp == NULL
659 || __builtin_expect (*foundp != newp, 0))
660 /* The insert failed. */
661 free (newp);
662 }
663 }
664 else
665 {
666 /* We can update the existing entry. */
667 (*foundp)->counter = _nl_msg_cat_cntr;
668 (*foundp)->domain = domain;
669 (*foundp)->translation = retval;
670 (*foundp)->translation_length = retlen;
671 }
672 #endif
673 __set_errno (saved_errno);
674
675 /* Now deal with plural. */
676 if (plural)
677 retval = plural_lookup (domain, n, retval, retlen);
678
679 __libc_rwlock_unlock (_nl_state_lock);
680 return retval;
681 }
682 }
683 }
684 /* NOTREACHED */
685 }
686
687
688 char *
689 internal_function
690 _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
691 struct loaded_l10nfile *domain_file;
692 struct binding *domainbinding;
693 const char *msgid;
694 int convert;
695 size_t *lengthp;
696 {
697 struct loaded_domain *domain;
698 nls_uint32 nstrings;
699 size_t act;
700 char *result;
701 size_t resultlen;
702
703 if (domain_file->decided <= 0)
704 _nl_load_domain (domain_file, domainbinding);
705
706 if (domain_file->data == NULL)
707 return NULL;
708
709 domain = (struct loaded_domain *) domain_file->data;
710
711 nstrings = domain->nstrings;
712
713 /* Locate the MSGID and its translation. */
714 if (domain->hash_tab != NULL)
715 {
716 /* Use the hashing table. */
717 nls_uint32 len = strlen (msgid);
718 nls_uint32 hash_val = __hash_string (msgid);
719 nls_uint32 idx = hash_val % domain->hash_size;
720 nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
721
722 while (1)
723 {
724 nls_uint32 nstr =
725 W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
726
727 if (nstr == 0)
728 /* Hash table entry is empty. */
729 return NULL;
730
731 nstr--;
732
733 /* Compare msgid with the original string at index nstr.
734 We compare the lengths with >=, not ==, because plural entries
735 are represented by strings with an embedded NUL. */
736 if (nstr < nstrings
737 ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
738 && (strcmp (msgid,
739 domain->data + W (domain->must_swap,
740 domain->orig_tab[nstr].offset))
741 == 0)
742 : domain->orig_sysdep_tab[nstr - nstrings].length > len
743 && (strcmp (msgid,
744 domain->orig_sysdep_tab[nstr - nstrings].pointer)
745 == 0))
746 {
747 act = nstr;
748 goto found;
749 }
750
751 if (idx >= domain->hash_size - incr)
752 idx -= domain->hash_size - incr;
753 else
754 idx += incr;
755 }
756 /* NOTREACHED */
757 }
758 else
759 {
760 /* Try the default method: binary search in the sorted array of
761 messages. */
762 size_t top, bottom;
763
764 bottom = 0;
765 top = nstrings;
766 while (bottom < top)
767 {
768 int cmp_val;
769
770 act = (bottom + top) / 2;
771 cmp_val = strcmp (msgid, (domain->data
772 + W (domain->must_swap,
773 domain->orig_tab[act].offset)));
774 if (cmp_val < 0)
775 top = act;
776 else if (cmp_val > 0)
777 bottom = act + 1;
778 else
779 goto found;
780 }
781 /* No translation was found. */
782 return NULL;
783 }
784
785 found:
786 /* The translation was found at index ACT. If we have to convert the
787 string to use a different character set, this is the time. */
788 if (act < nstrings)
789 {
790 result = (char *)
791 (domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
792 resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
793 }
794 else
795 {
796 result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
797 resultlen = domain->trans_sysdep_tab[act - nstrings].length;
798 }
799
800 #if defined _LIBC || HAVE_ICONV
801 if (convert)
802 {
803 /* We are supposed to do a conversion. */
804 const char *encoding = get_output_charset (domainbinding);
805
806 /* Search whether a table with converted translations for this
807 encoding has already been allocated. */
808 size_t nconversions = domain->nconversions;
809 struct converted_domain *convd = NULL;
810 size_t i;
811
812 for (i = nconversions; i > 0; )
813 {
814 i--;
815 if (strcmp (domain->conversions[i].encoding, encoding) == 0)
816 {
817 convd = &domain->conversions[i];
818 break;
819 }
820 }
821
822 if (convd == NULL)
823 {
824 /* Allocate a table for the converted translations for this
825 encoding. */
826 struct converted_domain *new_conversions =
827 (struct converted_domain *)
828 (domain->conversions != NULL
829 ? realloc (domain->conversions,
830 (nconversions + 1) * sizeof (struct converted_domain))
831 : malloc ((nconversions + 1) * sizeof (struct converted_domain)));
832
833 if (__builtin_expect (new_conversions == NULL, 0))
834 /* Nothing we can do, no more memory. */
835 goto converted;
836 domain->conversions = new_conversions;
837
838 /* Copy the 'encoding' string to permanent storage. */
839 encoding = strdup (encoding);
840 if (__builtin_expect (encoding == NULL, 0))
841 /* Nothing we can do, no more memory. */
842 goto converted;
843
844 convd = &new_conversions[nconversions];
845 convd->encoding = encoding;
846
847 /* Find out about the character set the file is encoded with.
848 This can be found (in textual form) in the entry "". If this
849 entry does not exist or if this does not contain the 'charset='
850 information, we will assume the charset matches the one the
851 current locale and we don't have to perform any conversion. */
852 # ifdef _LIBC
853 convd->conv = (__gconv_t) -1;
854 # else
855 # if HAVE_ICONV
856 convd->conv = (iconv_t) -1;
857 # endif
858 # endif
859 {
860 char *nullentry;
861 size_t nullentrylen;
862
863 /* Get the header entry. This is a recursion, but it doesn't
864 reallocate domain->conversions because we pass convert = 0. */
865 nullentry =
866 _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
867
868 if (nullentry != NULL)
869 {
870 const char *charsetstr;
871
872 charsetstr = strstr (nullentry, "charset=");
873 if (charsetstr != NULL)
874 {
875 size_t len;
876 char *charset;
877 const char *outcharset;
878
879 charsetstr += strlen ("charset=");
880 len = strcspn (charsetstr, " \t\n");
881
882 charset = (char *) alloca (len + 1);
883 # if defined _LIBC || HAVE_MEMPCPY
884 *((char *) mempcpy (charset, charsetstr, len)) = '\0';
885 # else
886 memcpy (charset, charsetstr, len);
887 charset[len] = '\0';
888 # endif
889
890 outcharset = encoding;
891
892 # ifdef _LIBC
893 /* We always want to use transliteration. */
894 outcharset = norm_add_slashes (outcharset, "TRANSLIT");
895 charset = norm_add_slashes (charset, "");
896 if (__gconv_open (outcharset, charset, &convd->conv,
897 GCONV_AVOID_NOCONV)
898 != __GCONV_OK)
899 convd->conv = (__gconv_t) -1;
900 # else
901 # if HAVE_ICONV
902 /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
903 we want to use transliteration. */
904 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
905 || _LIBICONV_VERSION >= 0x0105
906 if (strchr (outcharset, '/') == NULL)
907 {
908 char *tmp;
909
910 len = strlen (outcharset);
911 tmp = (char *) alloca (len + 10 + 1);
912 memcpy (tmp, outcharset, len);
913 memcpy (tmp + len, "//TRANSLIT", 10 + 1);
914 outcharset = tmp;
915
916 convd->conv = iconv_open (outcharset, charset);
917
918 freea (outcharset);
919 }
920 else
921 # endif
922 convd->conv = iconv_open (outcharset, charset);
923 # endif
924 # endif
925
926 freea (charset);
927 }
928 }
929 }
930 convd->conv_tab = NULL;
931 /* Here domain->conversions is still == new_conversions. */
932 domain->nconversions++;
933 }
934
935 if (
936 # ifdef _LIBC
937 convd->conv != (__gconv_t) -1
938 # else
939 # if HAVE_ICONV
940 convd->conv != (iconv_t) -1
941 # endif
942 # endif
943 )
944 {
945 /* We are supposed to do a conversion. First allocate an
946 appropriate table with the same structure as the table
947 of translations in the file, where we can put the pointers
948 to the converted strings in.
949 There is a slight complication with plural entries. They
950 are represented by consecutive NUL terminated strings. We
951 handle this case by converting RESULTLEN bytes, including
952 NULs. */
953
954 if (convd->conv_tab == NULL
955 && ((convd->conv_tab =
956 (char **) calloc (nstrings + domain->n_sysdep_strings,
957 sizeof (char *)))
958 == NULL))
959 /* Mark that we didn't succeed allocating a table. */
960 convd->conv_tab = (char **) -1;
961
962 if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
963 /* Nothing we can do, no more memory. */
964 goto converted;
965
966 if (convd->conv_tab[act] == NULL)
967 {
968 /* We haven't used this string so far, so it is not
969 translated yet. Do this now. */
970 /* We use a bit more efficient memory handling.
971 We allocate always larger blocks which get used over
972 time. This is faster than many small allocations. */
973 __libc_lock_define_initialized (static, lock)
974 # define INITIAL_BLOCK_SIZE 4080
975 static unsigned char *freemem;
976 static size_t freemem_size;
977
978 const unsigned char *inbuf;
979 unsigned char *outbuf;
980 int malloc_count;
981 # ifndef _LIBC
982 transmem_block_t *transmem_list = NULL;
983 # endif
984
985 __libc_lock_lock (lock);
986
987 inbuf = (const unsigned char *) result;
988 outbuf = freemem + sizeof (size_t);
989
990 malloc_count = 0;
991 while (1)
992 {
993 transmem_block_t *newmem;
994 # ifdef _LIBC
995 size_t non_reversible;
996 int res;
997
998 if (freemem_size < sizeof (size_t))
999 goto resize_freemem;
1000
1001 res = __gconv (convd->conv,
1002 &inbuf, inbuf + resultlen,
1003 &outbuf,
1004 outbuf + freemem_size - sizeof (size_t),
1005 &non_reversible);
1006
1007 if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
1008 break;
1009
1010 if (res != __GCONV_FULL_OUTPUT)
1011 {
1012 __libc_lock_unlock (lock);
1013 goto converted;
1014 }
1015
1016 inbuf = (const unsigned char *) result;
1017 # else
1018 # if HAVE_ICONV
1019 const char *inptr = (const char *) inbuf;
1020 size_t inleft = resultlen;
1021 char *outptr = (char *) outbuf;
1022 size_t outleft;
1023
1024 if (freemem_size < sizeof (size_t))
1025 goto resize_freemem;
1026
1027 outleft = freemem_size - sizeof (size_t);
1028 if (iconv (convd->conv,
1029 (ICONV_CONST char **) &inptr, &inleft,
1030 &outptr, &outleft)
1031 != (size_t) (-1))
1032 {
1033 outbuf = (unsigned char *) outptr;
1034 break;
1035 }
1036 if (errno != E2BIG)
1037 {
1038 __libc_lock_unlock (lock);
1039 goto converted;
1040 }
1041 # endif
1042 # endif
1043
1044 resize_freemem:
1045 /* We must allocate a new buffer or resize the old one. */
1046 if (malloc_count > 0)
1047 {
1048 ++malloc_count;
1049 freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
1050 newmem = (transmem_block_t *) realloc (transmem_list,
1051 freemem_size);
1052 # ifdef _LIBC
1053 if (newmem != NULL)
1054 transmem_list = transmem_list->next;
1055 else
1056 {
1057 struct transmem_list *old = transmem_list;
1058
1059 transmem_list = transmem_list->next;
1060 free (old);
1061 }
1062 # endif
1063 }
1064 else
1065 {
1066 malloc_count = 1;
1067 freemem_size = INITIAL_BLOCK_SIZE;
1068 newmem = (transmem_block_t *) malloc (freemem_size);
1069 }
1070 if (__builtin_expect (newmem == NULL, 0))
1071 {
1072 freemem = NULL;
1073 freemem_size = 0;
1074 __libc_lock_unlock (lock);
1075 goto converted;
1076 }
1077
1078 # ifdef _LIBC
1079 /* Add the block to the list of blocks we have to free
1080 at some point. */
1081 newmem->next = transmem_list;
1082 transmem_list = newmem;
1083
1084 freemem = (unsigned char *) newmem->data;
1085 freemem_size -= offsetof (struct transmem_list, data);
1086 # else
1087 transmem_list = newmem;
1088 freemem = newmem;
1089 # endif
1090
1091 outbuf = freemem + sizeof (size_t);
1092 }
1093
1094 /* We have now in our buffer a converted string. Put this
1095 into the table of conversions. */
1096 *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
1097 convd->conv_tab[act] = (char *) freemem;
1098 /* Shrink freemem, but keep it aligned. */
1099 freemem_size -= outbuf - freemem;
1100 freemem = outbuf;
1101 freemem += freemem_size & (alignof (size_t) - 1);
1102 freemem_size = freemem_size & ~ (alignof (size_t) - 1);
1103
1104 __libc_lock_unlock (lock);
1105 }
1106
1107 /* Now convd->conv_tab[act] contains the translation of all
1108 the plural variants. */
1109 result = convd->conv_tab[act] + sizeof (size_t);
1110 resultlen = *(size_t *) convd->conv_tab[act];
1111 }
1112 }
1113
1114 converted:
1115 /* The result string is converted. */
1116
1117 #endif /* _LIBC || HAVE_ICONV */
1118
1119 *lengthp = resultlen;
1120 return result;
1121 }
1122
1123
1124 /* Look up a plural variant. */
1125 static char *
1126 internal_function
1127 plural_lookup (domain, n, translation, translation_len)
1128 struct loaded_l10nfile *domain;
1129 unsigned long int n;
1130 const char *translation;
1131 size_t translation_len;
1132 {
1133 struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
1134 unsigned long int index;
1135 const char *p;
1136
1137 index = plural_eval (domaindata->plural, n);
1138 if (index >= domaindata->nplurals)
1139 /* This should never happen. It means the plural expression and the
1140 given maximum value do not match. */
1141 index = 0;
1142
1143 /* Skip INDEX strings at TRANSLATION. */
1144 p = translation;
1145 while (index-- > 0)
1146 {
1147 #ifdef _LIBC
1148 p = __rawmemchr (p, '\0');
1149 #else
1150 p = strchr (p, '\0');
1151 #endif
1152 /* And skip over the NUL byte. */
1153 p++;
1154
1155 if (p >= translation + translation_len)
1156 /* This should never happen. It means the plural expression
1157 evaluated to a value larger than the number of variants
1158 available for MSGID1. */
1159 return (char *) translation;
1160 }
1161 return (char *) p;
1162 }
1163
1164 #ifndef _LIBC
1165 /* Return string representation of locale CATEGORY. */
1166 static const char *
1167 internal_function
1168 category_to_name (category)
1169 int category;
1170 {
1171 const char *retval;
1172
1173 switch (category)
1174 {
1175 #ifdef LC_COLLATE
1176 case LC_COLLATE:
1177 retval = "LC_COLLATE";
1178 break;
1179 #endif
1180 #ifdef LC_CTYPE
1181 case LC_CTYPE:
1182 retval = "LC_CTYPE";
1183 break;
1184 #endif
1185 #ifdef LC_MONETARY
1186 case LC_MONETARY:
1187 retval = "LC_MONETARY";
1188 break;
1189 #endif
1190 #ifdef LC_NUMERIC
1191 case LC_NUMERIC:
1192 retval = "LC_NUMERIC";
1193 break;
1194 #endif
1195 #ifdef LC_TIME
1196 case LC_TIME:
1197 retval = "LC_TIME";
1198 break;
1199 #endif
1200 #ifdef LC_MESSAGES
1201 case LC_MESSAGES:
1202 retval = "LC_MESSAGES";
1203 break;
1204 #endif
1205 #ifdef LC_RESPONSE
1206 case LC_RESPONSE:
1207 retval = "LC_RESPONSE";
1208 break;
1209 #endif
1210 #ifdef LC_ALL
1211 case LC_ALL:
1212 /* This might not make sense but is perhaps better than any other
1213 value. */
1214 retval = "LC_ALL";
1215 break;
1216 #endif
1217 default:
1218 /* If you have a better idea for a default value let me know. */
1219 retval = "LC_XXX";
1220 }
1221
1222 return retval;
1223 }
1224 #endif
1225
1226 /* Guess value of current locale from value of the environment variables. */
1227 static const char *
1228 internal_function
1229 guess_category_value (category, categoryname)
1230 int category;
1231 const char *categoryname;
1232 {
1233 const char *language;
1234 const char *retval;
1235
1236 /* The highest priority value is the `LANGUAGE' environment
1237 variable. But we don't use the value if the currently selected
1238 locale is the C locale. This is a GNU extension. */
1239 language = getenv ("LANGUAGE");
1240 if (language != NULL && language[0] == '\0')
1241 language = NULL;
1242
1243 /* We have to proceed with the POSIX methods of looking to `LC_ALL',
1244 `LC_xxx', and `LANG'. On some systems this can be done by the
1245 `setlocale' function itself. */
1246 #ifdef _LIBC
1247 retval = __current_locale_name (category);
1248 #else
1249 retval = _nl_locale_name (category, categoryname);
1250 #endif
1251
1252 return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
1253 }
1254
1255 #if defined _LIBC || HAVE_ICONV
1256 /* Returns the output charset. */
1257 static const char *
1258 internal_function
1259 get_output_charset (domainbinding)
1260 struct binding *domainbinding;
1261 {
1262 /* The output charset should normally be determined by the locale. But
1263 sometimes the locale is not used or not correctly set up, so we provide
1264 a possibility for the user to override this: the OUTPUT_CHARSET
1265 environment variable. Moreover, the value specified through
1266 bind_textdomain_codeset overrides both. */
1267 if (domainbinding != NULL && domainbinding->codeset != NULL)
1268 return domainbinding->codeset;
1269 else
1270 {
1271 /* For speed reasons, we look at the value of OUTPUT_CHARSET only
1272 once. This is a user variable that is not supposed to change
1273 during a program run. */
1274 static char *output_charset_cache;
1275 static int output_charset_cached;
1276
1277 if (!output_charset_cached)
1278 {
1279 const char *value = getenv ("OUTPUT_CHARSET");
1280
1281 if (value != NULL && value[0] != '\0')
1282 {
1283 size_t len = strlen (value) + 1;
1284 char *value_copy = (char *) malloc (len);
1285
1286 if (value_copy != NULL)
1287 memcpy (value_copy, value, len);
1288 output_charset_cache = value_copy;
1289 }
1290 output_charset_cached = 1;
1291 }
1292
1293 if (output_charset_cache != NULL)
1294 return output_charset_cache;
1295 else
1296 {
1297 # ifdef _LIBC
1298 return _NL_CURRENT (LC_CTYPE, CODESET);
1299 # else
1300 # if HAVE_ICONV
1301 extern const char *locale_charset PARAMS ((void);
1302 return locale_charset ();
1303 # endif
1304 # endif
1305 }
1306 }
1307 }
1308 #endif
1309
1310 /* @@ begin of epilog @@ */
1311
1312 /* We don't want libintl.a to depend on any other library. So we
1313 avoid the non-standard function stpcpy. In GNU C Library this
1314 function is available, though. Also allow the symbol HAVE_STPCPY
1315 to be defined. */
1316 #if !_LIBC && !HAVE_STPCPY
1317 static char *
1318 stpcpy (dest, src)
1319 char *dest;
1320 const char *src;
1321 {
1322 while ((*dest++ = *src++) != '\0')
1323 /* Do nothing. */ ;
1324 return dest - 1;
1325 }
1326 #endif
1327
1328 #if !_LIBC && !HAVE_MEMPCPY
1329 static void *
1330 mempcpy (dest, src, n)
1331 void *dest;
1332 const void *src;
1333 size_t n;
1334 {
1335 return (void *) ((char *) memcpy (dest, src, n) + n);
1336 }
1337 #endif
1338
1339
1340 #ifdef _LIBC
1341 /* If we want to free all resources we have to do some work at
1342 program's end. */
1343 libc_freeres_fn (free_mem)
1344 {
1345 void *old;
1346
1347 while (_nl_domain_bindings != NULL)
1348 {
1349 struct binding *oldp = _nl_domain_bindings;
1350 _nl_domain_bindings = _nl_domain_bindings->next;
1351 if (oldp->dirname != _nl_default_dirname)
1352 /* Yes, this is a pointer comparison. */
1353 free (oldp->dirname);
1354 free (oldp->codeset);
1355 free (oldp);
1356 }
1357
1358 if (_nl_current_default_domain != _nl_default_default_domain)
1359 /* Yes, again a pointer comparison. */
1360 free ((char *) _nl_current_default_domain);
1361
1362 /* Remove the search tree with the known translations. */
1363 __tdestroy (root, free);
1364 root = NULL;
1365
1366 while (transmem_list != NULL)
1367 {
1368 old = transmem_list;
1369 transmem_list = transmem_list->next;
1370 free (old);
1371 }
1372 }
1373 #endif