init version.
[bush.git] / lib / intl / dcigettext.c
blobad21278f22961218b4b866cf52b5a076d334a7cd
1 /* dcigettext.c - Implementation of the internal dcigettext function. */
3 /* Copyright (C) 1995-1999, 2000-2003, 2006-2009 Free Software Foundation, Inc.
5 This file is part of GNU Bush.
7 Bush is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bush is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bush. If not, see <http://www.gnu.org/licenses/>.
21 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
22 This must come before <config.h> because <config.h> may include
23 <features.h>, and once <features.h> has been included, it's too late. */
24 #ifndef _GNU_SOURCE
25 # define _GNU_SOURCE 1
26 #endif
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
32 #include <sys/types.h>
34 #ifdef __GNUC__
35 # define alloca __builtin_alloca
36 # define HAVE_ALLOCA 1
37 #else
38 # ifdef _MSC_VER
39 # include <malloc.h>
40 # define alloca _alloca
41 # else
42 # if defined HAVE_ALLOCA_H || defined _LIBC
43 # include <alloca.h>
44 # else
45 # ifdef _AIX
46 #pragma alloca
47 # else
48 # ifndef alloca
49 char *alloca ();
50 # endif
51 # endif
52 # endif
53 # endif
54 #endif
56 #include <errno.h>
57 #ifndef errno
58 extern int errno;
59 #endif
60 #ifndef __set_errno
61 # define __set_errno(val) errno = (val)
62 #endif
64 #include <stddef.h>
65 #include <stdlib.h>
66 #include <string.h>
68 #if defined HAVE_UNISTD_H || defined _LIBC
69 # include <unistd.h>
70 #endif
72 #include <locale.h>
74 #ifdef _LIBC
75 /* Guess whether integer division by zero raises signal SIGFPE.
76 Set to 1 only if you know for sure. In case of doubt, set to 0. */
77 # if defined __alpha__ || defined __arm__ || defined __i386__ \
78 || defined __m68k__ || defined __s390__
79 # define INTDIV0_RAISES_SIGFPE 1
80 # else
81 # define INTDIV0_RAISES_SIGFPE 0
82 # endif
83 #endif
84 #if !INTDIV0_RAISES_SIGFPE
85 # include <signal.h>
86 #endif
88 #if defined HAVE_SYS_PARAM_H || defined _LIBC
89 # include <sys/param.h>
90 #endif
92 #include "gettextP.h"
93 #include "plural-exp.h"
94 #ifdef _LIBC
95 # include <libintl.h>
96 #else
97 # include "libgnuintl.h"
98 #endif
99 #include "hash-string.h"
101 /* Thread safetyness. */
102 #ifdef _LIBC
103 # include <bits/libc-lock.h>
104 #else
105 /* Provide dummy implementation if this is outside glibc. */
106 # define __libc_lock_define_initialized(CLASS, NAME)
107 # define __libc_lock_lock(NAME)
108 # define __libc_lock_unlock(NAME)
109 # define __libc_rwlock_define_initialized(CLASS, NAME)
110 # define __libc_rwlock_rdlock(NAME)
111 # define __libc_rwlock_unlock(NAME)
112 #endif
114 /* Alignment of types. */
115 #if defined __GNUC__ && __GNUC__ >= 2
116 # define alignof(TYPE) __alignof__ (TYPE)
117 #else
118 # define alignof(TYPE) \
119 ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
120 #endif
122 /* The internal variables in the standalone libintl.a must have different
123 names than the internal variables in GNU libc, otherwise programs
124 using libintl.a cannot be linked statically. */
125 #if !defined _LIBC
126 # define _nl_default_default_domain libintl_nl_default_default_domain
127 # define _nl_current_default_domain libintl_nl_current_default_domain
128 # define _nl_default_dirname libintl_nl_default_dirname
129 # define _nl_domain_bindings libintl_nl_domain_bindings
130 #endif
132 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
133 #ifndef offsetof
134 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
135 #endif
137 /* @@ end of prolog @@ */
139 #if defined (SHELL) && !defined (HAVE_GETCWD)
140 # define HAVE_GETCWD
141 #endif
143 #ifdef _LIBC
144 /* Rename the non ANSI C functions. This is required by the standard
145 because some ANSI C functions will require linking with this object
146 file and the name space must not be polluted. */
147 # define getcwd __getcwd
148 # ifndef stpcpy
149 # define stpcpy __stpcpy
150 # endif
151 # define tfind __tfind
152 #else
153 # if !defined HAVE_GETCWD
154 char *getwd ();
155 # define getcwd(buf, max) getwd (buf)
156 # else
157 char *getcwd ();
158 # endif
159 # ifndef HAVE_STPCPY
160 static char *stpcpy PARAMS ((char *dest, const char *src));
161 # endif
162 # ifndef HAVE_MEMPCPY
163 static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
164 # endif
165 #endif
167 /* Amount to increase buffer size by in each try. */
168 #define PATH_INCR 32
170 /* The following is from pathmax.h. */
171 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
172 PATH_MAX but might cause redefinition warnings when sys/param.h is
173 later included (as on MORE/BSD 4.3). */
174 #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
175 # include <limits.h>
176 #endif
178 #ifndef _POSIX_PATH_MAX
179 # define _POSIX_PATH_MAX 255
180 #endif
182 #if !defined PATH_MAX && defined _PC_PATH_MAX
183 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
184 #endif
186 /* Don't include sys/param.h if it already has been. */
187 #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
188 # include <sys/param.h>
189 #endif
191 #if !defined PATH_MAX && defined MAXPATHLEN
192 # define PATH_MAX MAXPATHLEN
193 #endif
195 #ifndef PATH_MAX
196 # define PATH_MAX _POSIX_PATH_MAX
197 #endif
199 /* Pathname support.
200 ISSLASH(C) tests whether C is a directory separator character.
201 IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not,
202 it may be concatenated to a directory pathname.
203 IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
205 #if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
206 /* Win32, OS/2, DOS */
207 # define ISSLASH(C) ((C) == '/' || (C) == '\\')
208 # define HAS_DEVICE(P) \
209 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
210 && (P)[1] == ':')
211 # define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
212 # define IS_PATH_WITH_DIR(P) \
213 (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
214 #else
215 /* Unix */
216 # define ISSLASH(C) ((C) == '/')
217 # define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
218 # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
219 #endif
221 /* This is the type used for the search tree where known translations
222 are stored. */
223 struct known_translation_t
225 /* Domain in which to search. */
226 char *domainname;
228 /* The category. */
229 int category;
231 /* State of the catalog counter at the point the string was found. */
232 int counter;
234 /* Catalog where the string was found. */
235 struct loaded_l10nfile *domain;
237 /* And finally the translation. */
238 const char *translation;
239 size_t translation_length;
241 /* Pointer to the string in question. */
242 char msgid[ZERO];
245 /* Root of the search tree with known translations. We can use this
246 only if the system provides the `tsearch' function family. */
247 #if defined HAVE_TSEARCH || defined _LIBC
248 # include <search.h>
250 static void *root;
252 # ifdef _LIBC
253 # define tsearch __tsearch
254 # endif
256 /* Function to compare two entries in the table of known translations. */
257 static int transcmp PARAMS ((const void *p1, const void *p2));
258 static int
259 transcmp (p1, p2)
260 const void *p1;
261 const void *p2;
263 const struct known_translation_t *s1;
264 const struct known_translation_t *s2;
265 int result;
267 s1 = (const struct known_translation_t *) p1;
268 s2 = (const struct known_translation_t *) p2;
270 result = strcmp (s1->msgid, s2->msgid);
271 if (result == 0)
273 result = strcmp (s1->domainname, s2->domainname);
274 if (result == 0)
275 /* We compare the category last (though this is the cheapest
276 operation) since it is hopefully always the same (namely
277 LC_MESSAGES). */
278 result = s1->category - s2->category;
281 return result;
283 #endif
285 #ifndef INTVARDEF
286 # define INTVARDEF(name)
287 #endif
288 #ifndef INTUSE
289 # define INTUSE(name) name
290 #endif
292 /* Name of the default domain used for gettext(3) prior any call to
293 textdomain(3). The default value for this is "messages". */
294 const char _nl_default_default_domain[] attribute_hidden = "messages";
296 /* Value used as the default domain for gettext(3). */
297 const char *_nl_current_default_domain attribute_hidden
298 = _nl_default_default_domain;
300 /* Contains the default location of the message catalogs. */
301 #if defined __EMX__
302 extern const char _nl_default_dirname[];
303 #else
304 const char _nl_default_dirname[] = LOCALEDIR;
305 INTVARDEF (_nl_default_dirname)
306 #endif
308 /* List with bindings of specific domains created by bindtextdomain()
309 calls. */
310 struct binding *_nl_domain_bindings;
312 /* Prototypes for local functions. */
313 static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
314 unsigned long int n,
315 const char *translation,
316 size_t translation_len))
317 internal_function;
318 static const char *guess_category_value PARAMS ((int category,
319 const char *categoryname))
320 internal_function;
321 #ifdef _LIBC
322 # include "../locale/localeinfo.h"
323 # define category_to_name(category) _nl_category_names[category]
324 #else
325 static const char *category_to_name PARAMS ((int category)) internal_function;
326 #endif
329 /* For those loosing systems which don't have `alloca' we have to add
330 some additional code emulating it. */
331 #ifdef HAVE_ALLOCA
332 /* Nothing has to be done. */
333 # define freea(p) /* nothing */
334 # define ADD_BLOCK(list, address) /* nothing */
335 # define FREE_BLOCKS(list) /* nothing */
336 #else
337 struct block_list
339 void *address;
340 struct block_list *next;
342 # define ADD_BLOCK(list, addr) \
343 do { \
344 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
345 /* If we cannot get a free block we cannot add the new element to \
346 the list. */ \
347 if (newp != NULL) { \
348 newp->address = (addr); \
349 newp->next = (list); \
350 (list) = newp; \
352 } while (0)
353 # define FREE_BLOCKS(list) \
354 do { \
355 while (list != NULL) { \
356 struct block_list *old = list; \
357 list = list->next; \
358 free (old->address); \
359 free (old); \
361 } while (0)
362 # undef alloca
363 # define alloca(size) (malloc (size))
364 # define freea(p) free (p)
365 #endif /* have alloca */
368 #ifdef _LIBC
369 /* List of blocks allocated for translations. */
370 typedef struct transmem_list
372 struct transmem_list *next;
373 char data[ZERO];
374 } transmem_block_t;
375 static struct transmem_list *transmem_list;
376 #else
377 typedef unsigned char transmem_block_t;
378 #endif
381 /* Names for the libintl functions are a problem. They must not clash
382 with existing names and they should follow ANSI C. But this source
383 code is also used in GNU C Library where the names have a __
384 prefix. So we have to make a difference here. */
385 #ifdef _LIBC
386 # define DCIGETTEXT __dcigettext
387 #else
388 # define DCIGETTEXT libintl_dcigettext
389 #endif
391 /* Lock variable to protect the global data in the gettext implementation. */
392 #ifdef _LIBC
393 __libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
394 #endif
396 /* Checking whether the binaries runs SUID must be done and glibc provides
397 easier methods therefore we make a difference here. */
398 #ifdef _LIBC
399 # define ENABLE_SECURE __libc_enable_secure
400 # define DETERMINE_SECURE
401 #else
402 # ifndef HAVE_GETUID
403 # define getuid() 0
404 # endif
405 # ifndef HAVE_GETGID
406 # define getgid() 0
407 # endif
408 # ifndef HAVE_GETEUID
409 # define geteuid() getuid()
410 # endif
411 # ifndef HAVE_GETEGID
412 # define getegid() getgid()
413 # endif
414 static int enable_secure;
415 # define ENABLE_SECURE (enable_secure == 1)
416 # define DETERMINE_SECURE \
417 if (enable_secure == 0) \
419 if (getuid () != geteuid () || getgid () != getegid ()) \
420 enable_secure = 1; \
421 else \
422 enable_secure = -1; \
424 #endif
426 #ifndef HAVE_RAISE
427 # define raise(x) kill (getpid (), (x))
428 #endif
430 /* Get the function to evaluate the plural expression. */
431 #include "eval-plural.h"
433 /* Look up MSGID in the DOMAINNAME message catalog for the current
434 CATEGORY locale and, if PLURAL is nonzero, search over string
435 depending on the plural form determined by N. */
436 char *
437 DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
438 const char *domainname;
439 const char *msgid1;
440 const char *msgid2;
441 int plural;
442 unsigned long int n;
443 int category;
445 #ifndef HAVE_ALLOCA
446 struct block_list *block_list = NULL;
447 #endif
448 struct loaded_l10nfile *domain;
449 struct binding *binding;
450 const char *categoryname;
451 const char *categoryvalue;
452 char *dirname, *xdomainname;
453 char *single_locale;
454 char *retval;
455 size_t retlen;
456 int saved_errno;
457 #if defined HAVE_TSEARCH || defined _LIBC
458 struct known_translation_t *search;
459 struct known_translation_t **foundp = NULL;
460 size_t msgid_len;
461 #endif
462 size_t domainname_len;
464 /* If no real MSGID is given return NULL. */
465 if (msgid1 == NULL)
466 return NULL;
468 #ifdef _LIBC
469 if (category < 0 || category >= __LC_LAST || category == LC_ALL)
470 /* Bogus. */
471 return (plural == 0
472 ? (char *) msgid1
473 /* Use the Germanic plural rule. */
474 : n == 1 ? (char *) msgid1 : (char *) msgid2);
475 #endif
477 __libc_rwlock_rdlock (_nl_state_lock);
479 /* If DOMAINNAME is NULL, we are interested in the default domain. If
480 CATEGORY is not LC_MESSAGES this might not make much sense but the
481 definition left this undefined. */
482 if (domainname == NULL)
483 domainname = _nl_current_default_domain;
485 /* OS/2 specific: backward compatibility with older libintl versions */
486 #ifdef LC_MESSAGES_COMPAT
487 if (category == LC_MESSAGES_COMPAT)
488 category = LC_MESSAGES;
489 #endif
491 #if defined HAVE_TSEARCH || defined _LIBC
492 msgid_len = strlen (msgid1) + 1;
494 /* Try to find the translation among those which we found at
495 some time. */
496 search = (struct known_translation_t *)
497 alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
498 memcpy (search->msgid, msgid1, msgid_len);
499 search->domainname = (char *) domainname;
500 search->category = category;
502 foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
503 freea (search);
504 if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
506 /* Now deal with plural. */
507 if (plural)
508 retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
509 (*foundp)->translation_length);
510 else
511 retval = (char *) (*foundp)->translation;
513 __libc_rwlock_unlock (_nl_state_lock);
514 return retval;
516 #endif
518 /* Preserve the `errno' value. */
519 saved_errno = errno;
521 /* See whether this is a SUID binary or not. */
522 DETERMINE_SECURE;
524 /* First find matching binding. */
525 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
527 int compare = strcmp (domainname, binding->domainname);
528 if (compare == 0)
529 /* We found it! */
530 break;
531 if (compare < 0)
533 /* It is not in the list. */
534 binding = NULL;
535 break;
539 if (binding == NULL)
540 dirname = (char *) INTUSE(_nl_default_dirname);
541 else if (IS_ABSOLUTE_PATH (binding->dirname))
542 dirname = binding->dirname;
543 else
545 /* We have a relative path. Make it absolute now. */
546 size_t dirname_len = strlen (binding->dirname) + 1;
547 size_t path_max;
548 char *ret;
550 path_max = (unsigned int) PATH_MAX;
551 path_max += 2; /* The getcwd docs say to do this. */
553 for (;;)
555 dirname = (char *) alloca (path_max + dirname_len);
556 ADD_BLOCK (block_list, dirname);
558 __set_errno (0);
559 ret = getcwd (dirname, path_max);
560 if (ret != NULL || errno != ERANGE)
561 break;
563 path_max += path_max / 2;
564 path_max += PATH_INCR;
567 if (ret == NULL)
568 /* We cannot get the current working directory. Don't signal an
569 error but simply return the default string. */
570 goto return_untranslated;
572 stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
575 /* Now determine the symbolic name of CATEGORY and its value. */
576 categoryname = category_to_name (category);
577 categoryvalue = guess_category_value (category, categoryname);
579 domainname_len = strlen (domainname);
580 xdomainname = (char *) alloca (strlen (categoryname)
581 + domainname_len + 5);
582 ADD_BLOCK (block_list, xdomainname);
584 stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
585 domainname, domainname_len),
586 ".mo");
588 /* Creating working area. */
589 single_locale = (char *) alloca (strlen (categoryvalue) + 1);
590 ADD_BLOCK (block_list, single_locale);
593 /* Search for the given string. This is a loop because we perhaps
594 got an ordered list of languages to consider for the translation. */
595 while (1)
597 /* Make CATEGORYVALUE point to the next element of the list. */
598 while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
599 ++categoryvalue;
600 if (categoryvalue[0] == '\0')
602 /* The whole contents of CATEGORYVALUE has been searched but
603 no valid entry has been found. We solve this situation
604 by implicitly appending a "C" entry, i.e. no translation
605 will take place. */
606 single_locale[0] = 'C';
607 single_locale[1] = '\0';
609 else
611 char *cp = single_locale;
612 while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
613 *cp++ = *categoryvalue++;
614 *cp = '\0';
616 /* When this is a SUID binary we must not allow accessing files
617 outside the dedicated directories. */
618 if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale))
619 /* Ingore this entry. */
620 continue;
623 /* If the current locale value is C (or POSIX) we don't load a
624 domain. Return the MSGID. */
625 if (strcmp (single_locale, "C") == 0
626 || strcmp (single_locale, "POSIX") == 0)
627 break;
629 /* Find structure describing the message catalog matching the
630 DOMAINNAME and CATEGORY. */
631 domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
633 if (domain != NULL)
635 retval = _nl_find_msg (domain, binding, msgid1, &retlen);
637 if (retval == NULL)
639 int cnt;
641 for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
643 retval = _nl_find_msg (domain->successor[cnt], binding,
644 msgid1, &retlen);
646 if (retval != NULL)
648 domain = domain->successor[cnt];
649 break;
654 if (retval != NULL)
656 /* Found the translation of MSGID1 in domain DOMAIN:
657 starting at RETVAL, RETLEN bytes. */
658 FREE_BLOCKS (block_list);
659 #if defined HAVE_TSEARCH || defined _LIBC
660 if (foundp == NULL)
662 /* Create a new entry and add it to the search tree. */
663 struct known_translation_t *newp;
665 newp = (struct known_translation_t *)
666 malloc (offsetof (struct known_translation_t, msgid)
667 + msgid_len + domainname_len + 1);
668 if (newp != NULL)
670 newp->domainname =
671 mempcpy (newp->msgid, msgid1, msgid_len);
672 memcpy (newp->domainname, domainname, domainname_len + 1);
673 newp->category = category;
674 newp->counter = _nl_msg_cat_cntr;
675 newp->domain = domain;
676 newp->translation = retval;
677 newp->translation_length = retlen;
679 /* Insert the entry in the search tree. */
680 foundp = (struct known_translation_t **)
681 tsearch (newp, &root, transcmp);
682 if (foundp == NULL
683 || __builtin_expect (*foundp != newp, 0))
684 /* The insert failed. */
685 free (newp);
688 else
690 /* We can update the existing entry. */
691 (*foundp)->counter = _nl_msg_cat_cntr;
692 (*foundp)->domain = domain;
693 (*foundp)->translation = retval;
694 (*foundp)->translation_length = retlen;
696 #endif
697 __set_errno (saved_errno);
699 /* Now deal with plural. */
700 if (plural)
701 retval = plural_lookup (domain, n, retval, retlen);
703 __libc_rwlock_unlock (_nl_state_lock);
704 return retval;
709 return_untranslated:
710 /* Return the untranslated MSGID. */
711 FREE_BLOCKS (block_list);
712 __libc_rwlock_unlock (_nl_state_lock);
713 #ifndef _LIBC
714 if (!ENABLE_SECURE)
716 extern void _nl_log_untranslated PARAMS ((const char *logfilename,
717 const char *domainname,
718 const char *msgid1,
719 const char *msgid2,
720 int plural));
721 const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED");
723 if (logfilename != NULL && logfilename[0] != '\0')
724 _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
726 #endif
727 __set_errno (saved_errno);
728 return (plural == 0
729 ? (char *) msgid1
730 /* Use the Germanic plural rule. */
731 : n == 1 ? (char *) msgid1 : (char *) msgid2);
735 char *
736 internal_function
737 _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
738 struct loaded_l10nfile *domain_file;
739 struct binding *domainbinding;
740 const char *msgid;
741 size_t *lengthp;
743 struct loaded_domain *domain;
744 nls_uint32 nstrings;
745 size_t act;
746 char *result;
747 size_t resultlen;
749 if (domain_file->decided == 0)
750 _nl_load_domain (domain_file, domainbinding);
752 if (domain_file->data == NULL)
753 return NULL;
755 domain = (struct loaded_domain *) domain_file->data;
757 nstrings = domain->nstrings;
759 /* Locate the MSGID and its translation. */
760 if (domain->hash_tab != NULL)
762 /* Use the hashing table. */
763 nls_uint32 len = strlen (msgid);
764 nls_uint32 hash_val = hash_string (msgid);
765 nls_uint32 idx = hash_val % domain->hash_size;
766 nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
768 while (1)
770 nls_uint32 nstr =
771 W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
773 if (nstr == 0)
774 /* Hash table entry is empty. */
775 return NULL;
777 nstr--;
779 /* Compare msgid with the original string at index nstr.
780 We compare the lengths with >=, not ==, because plural entries
781 are represented by strings with an embedded NUL. */
782 if (nstr < nstrings
783 ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
784 && (strcmp (msgid,
785 domain->data + W (domain->must_swap,
786 domain->orig_tab[nstr].offset))
787 == 0)
788 : domain->orig_sysdep_tab[nstr - nstrings].length > len
789 && (strcmp (msgid,
790 domain->orig_sysdep_tab[nstr - nstrings].pointer)
791 == 0))
793 act = nstr;
794 goto found;
797 if (idx >= domain->hash_size - incr)
798 idx -= domain->hash_size - incr;
799 else
800 idx += incr;
802 /* NOTREACHED */
804 else
806 /* Try the default method: binary search in the sorted array of
807 messages. */
808 size_t top, bottom;
810 bottom = 0;
811 top = nstrings;
812 while (bottom < top)
814 int cmp_val;
816 act = (bottom + top) / 2;
817 cmp_val = strcmp (msgid, (domain->data
818 + W (domain->must_swap,
819 domain->orig_tab[act].offset)));
820 if (cmp_val < 0)
821 top = act;
822 else if (cmp_val > 0)
823 bottom = act + 1;
824 else
825 goto found;
827 /* No translation was found. */
828 return NULL;
831 found:
832 /* The translation was found at index ACT. If we have to convert the
833 string to use a different character set, this is the time. */
834 if (act < nstrings)
836 result = (char *)
837 (domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
838 resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
840 else
842 result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
843 resultlen = domain->trans_sysdep_tab[act - nstrings].length;
846 #if defined _LIBC || HAVE_ICONV
847 if (domain->codeset_cntr
848 != (domainbinding != NULL ? domainbinding->codeset_cntr : 0))
850 /* The domain's codeset has changed through bind_textdomain_codeset()
851 since the message catalog was initialized or last accessed. We
852 have to reinitialize the converter. */
853 _nl_free_domain_conv (domain);
854 _nl_init_domain_conv (domain_file, domain, domainbinding);
857 if (
858 # ifdef _LIBC
859 domain->conv != (__gconv_t) -1
860 # else
861 # if HAVE_ICONV
862 domain->conv != (iconv_t) -1
863 # endif
864 # endif
867 /* We are supposed to do a conversion. First allocate an
868 appropriate table with the same structure as the table
869 of translations in the file, where we can put the pointers
870 to the converted strings in.
871 There is a slight complication with plural entries. They
872 are represented by consecutive NUL terminated strings. We
873 handle this case by converting RESULTLEN bytes, including
874 NULs. */
876 if (domain->conv_tab == NULL
877 && ((domain->conv_tab =
878 (char **) calloc (nstrings + domain->n_sysdep_strings,
879 sizeof (char *)))
880 == NULL))
881 /* Mark that we didn't succeed allocating a table. */
882 domain->conv_tab = (char **) -1;
884 if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
885 /* Nothing we can do, no more memory. */
886 goto converted;
888 if (domain->conv_tab[act] == NULL)
890 /* We haven't used this string so far, so it is not
891 translated yet. Do this now. */
892 /* We use a bit more efficient memory handling.
893 We allocate always larger blocks which get used over
894 time. This is faster than many small allocations. */
895 __libc_lock_define_initialized (static, lock)
896 # define INITIAL_BLOCK_SIZE 4080
897 static unsigned char *freemem;
898 static size_t freemem_size;
900 const unsigned char *inbuf;
901 unsigned char *outbuf;
902 int malloc_count;
903 # ifndef _LIBC
904 transmem_block_t *transmem_list = NULL;
905 # endif
907 __libc_lock_lock (lock);
909 inbuf = (const unsigned char *) result;
910 outbuf = freemem + sizeof (size_t);
912 malloc_count = 0;
913 while (1)
915 transmem_block_t *newmem;
916 # ifdef _LIBC
917 size_t non_reversible;
918 int res;
920 if (freemem_size < sizeof (size_t))
921 goto resize_freemem;
923 res = __gconv (domain->conv,
924 &inbuf, inbuf + resultlen,
925 &outbuf,
926 outbuf + freemem_size - sizeof (size_t),
927 &non_reversible);
929 if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
930 break;
932 if (res != __GCONV_FULL_OUTPUT)
934 __libc_lock_unlock (lock);
935 goto converted;
938 inbuf = result;
939 # else
940 # if HAVE_ICONV
941 const char *inptr = (const char *) inbuf;
942 size_t inleft = resultlen;
943 char *outptr = (char *) outbuf;
944 size_t outleft;
946 if (freemem_size < sizeof (size_t))
947 goto resize_freemem;
949 outleft = freemem_size - sizeof (size_t);
950 if (iconv (domain->conv,
951 (ICONV_CONST char **) &inptr, &inleft,
952 &outptr, &outleft)
953 != (size_t) (-1))
955 outbuf = (unsigned char *) outptr;
956 break;
958 if (errno != E2BIG)
960 __libc_lock_unlock (lock);
961 goto converted;
963 # endif
964 # endif
966 resize_freemem:
967 /* We must allocate a new buffer or resize the old one. */
968 if (malloc_count > 0)
970 ++malloc_count;
971 freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
972 newmem = (transmem_block_t *) realloc (transmem_list,
973 freemem_size);
974 # ifdef _LIBC
975 if (newmem != NULL)
976 transmem_list = transmem_list->next;
977 else
979 struct transmem_list *old = transmem_list;
981 transmem_list = transmem_list->next;
982 free (old);
984 # endif
986 else
988 malloc_count = 1;
989 freemem_size = INITIAL_BLOCK_SIZE;
990 newmem = (transmem_block_t *) malloc (freemem_size);
992 if (__builtin_expect (newmem == NULL, 0))
994 freemem = NULL;
995 freemem_size = 0;
996 __libc_lock_unlock (lock);
997 goto converted;
1000 # ifdef _LIBC
1001 /* Add the block to the list of blocks we have to free
1002 at some point. */
1003 newmem->next = transmem_list;
1004 transmem_list = newmem;
1006 freemem = newmem->data;
1007 freemem_size -= offsetof (struct transmem_list, data);
1008 # else
1009 transmem_list = newmem;
1010 freemem = newmem;
1011 # endif
1013 outbuf = freemem + sizeof (size_t);
1016 /* We have now in our buffer a converted string. Put this
1017 into the table of conversions. */
1018 *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
1019 domain->conv_tab[act] = (char *) freemem;
1020 /* Shrink freemem, but keep it aligned. */
1021 freemem_size -= outbuf - freemem;
1022 freemem = outbuf;
1023 freemem += freemem_size & (alignof (size_t) - 1);
1024 freemem_size = freemem_size & ~ (alignof (size_t) - 1);
1026 __libc_lock_unlock (lock);
1029 /* Now domain->conv_tab[act] contains the translation of all
1030 the plural variants. */
1031 result = domain->conv_tab[act] + sizeof (size_t);
1032 resultlen = *(size_t *) domain->conv_tab[act];
1035 converted:
1036 /* The result string is converted. */
1038 #endif /* _LIBC || HAVE_ICONV */
1040 *lengthp = resultlen;
1041 return result;
1045 /* Look up a plural variant. */
1046 static char *
1047 internal_function
1048 plural_lookup (domain, n, translation, translation_len)
1049 struct loaded_l10nfile *domain;
1050 unsigned long int n;
1051 const char *translation;
1052 size_t translation_len;
1054 struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
1055 unsigned long int index;
1056 const char *p;
1058 index = plural_eval (domaindata->plural, n);
1059 if (index >= domaindata->nplurals)
1060 /* This should never happen. It means the plural expression and the
1061 given maximum value do not match. */
1062 index = 0;
1064 /* Skip INDEX strings at TRANSLATION. */
1065 p = translation;
1066 while (index-- > 0)
1068 #ifdef _LIBC
1069 p = __rawmemchr (p, '\0');
1070 #else
1071 p = strchr (p, '\0');
1072 #endif
1073 /* And skip over the NUL byte. */
1074 p++;
1076 if (p >= translation + translation_len)
1077 /* This should never happen. It means the plural expression
1078 evaluated to a value larger than the number of variants
1079 available for MSGID1. */
1080 return (char *) translation;
1082 return (char *) p;
1085 #ifndef _LIBC
1086 /* Return string representation of locale CATEGORY. */
1087 static const char *
1088 internal_function
1089 category_to_name (category)
1090 int category;
1092 const char *retval;
1094 switch (category)
1096 #ifdef LC_COLLATE
1097 case LC_COLLATE:
1098 retval = "LC_COLLATE";
1099 break;
1100 #endif
1101 #ifdef LC_CTYPE
1102 case LC_CTYPE:
1103 retval = "LC_CTYPE";
1104 break;
1105 #endif
1106 #ifdef LC_MONETARY
1107 case LC_MONETARY:
1108 retval = "LC_MONETARY";
1109 break;
1110 #endif
1111 #ifdef LC_NUMERIC
1112 case LC_NUMERIC:
1113 retval = "LC_NUMERIC";
1114 break;
1115 #endif
1116 #ifdef LC_TIME
1117 case LC_TIME:
1118 retval = "LC_TIME";
1119 break;
1120 #endif
1121 #ifdef LC_MESSAGES
1122 case LC_MESSAGES:
1123 retval = "LC_MESSAGES";
1124 break;
1125 #endif
1126 #ifdef LC_RESPONSE
1127 case LC_RESPONSE:
1128 retval = "LC_RESPONSE";
1129 break;
1130 #endif
1131 #ifdef LC_ALL
1132 case LC_ALL:
1133 /* This might not make sense but is perhaps better than any other
1134 value. */
1135 retval = "LC_ALL";
1136 break;
1137 #endif
1138 default:
1139 /* If you have a better idea for a default value let me know. */
1140 retval = "LC_XXX";
1143 return retval;
1145 #endif
1147 /* Guess value of current locale from value of the environment variables. */
1148 static const char *
1149 internal_function
1150 guess_category_value (category, categoryname)
1151 int category;
1152 const char *categoryname;
1154 const char *language;
1155 const char *retval;
1157 /* The highest priority value is the `LANGUAGE' environment
1158 variable. But we don't use the value if the currently selected
1159 locale is the C locale. This is a GNU extension. */
1160 language = getenv ("LANGUAGE");
1161 if (language != NULL && language[0] == '\0')
1162 language = NULL;
1164 /* We have to proceed with the POSIX methods of looking to `LC_ALL',
1165 `LC_xxx', and `LANG'. On some systems this can be done by the
1166 `setlocale' function itself. */
1167 #ifdef _LIBC
1168 retval = __current_locale_name (category);
1169 #else
1170 retval = _nl_locale_name (category, categoryname);
1171 #endif
1173 /* Ignore LANGUAGE if the locale is set to "C" because
1174 1. "C" locale usually uses the ASCII encoding, and most international
1175 messages use non-ASCII characters. These characters get displayed
1176 as question marks (if using glibc's iconv()) or as invalid 8-bit
1177 characters (because other iconv()s refuse to convert most non-ASCII
1178 characters to ASCII). In any case, the output is ugly.
1179 2. The precise output of some programs in the "C" locale is specified
1180 by POSIX and should not depend on environment variables like
1181 "LANGUAGE". We allow such programs to use gettext(). */
1182 return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
1185 /* @@ begin of epilog @@ */
1187 /* We don't want libintl.a to depend on any other library. So we
1188 avoid the non-standard function stpcpy. In GNU C Library this
1189 function is available, though. Also allow the symbol HAVE_STPCPY
1190 to be defined. */
1191 #if !_LIBC && !HAVE_STPCPY
1192 static char *
1193 stpcpy (dest, src)
1194 char *dest;
1195 const char *src;
1197 while ((*dest++ = *src++) != '\0')
1198 /* Do nothing. */ ;
1199 return dest - 1;
1201 #endif
1203 #if !_LIBC && !HAVE_MEMPCPY
1204 static void *
1205 mempcpy (dest, src, n)
1206 void *dest;
1207 const void *src;
1208 size_t n;
1210 return (void *) ((char *) memcpy (dest, src, n) + n);
1212 #endif
1215 #ifdef _LIBC
1216 /* If we want to free all resources we have to do some work at
1217 program's end. */
1218 libc_freeres_fn (free_mem)
1220 void *old;
1222 while (_nl_domain_bindings != NULL)
1224 struct binding *oldp = _nl_domain_bindings;
1225 _nl_domain_bindings = _nl_domain_bindings->next;
1226 if (oldp->dirname != INTUSE(_nl_default_dirname))
1227 /* Yes, this is a pointer comparison. */
1228 free (oldp->dirname);
1229 free (oldp->codeset);
1230 free (oldp);
1233 if (_nl_current_default_domain != _nl_default_default_domain)
1234 /* Yes, again a pointer comparison. */
1235 free ((char *) _nl_current_default_domain);
1237 /* Remove the search tree with the known translations. */
1238 __tdestroy (root, free);
1239 root = NULL;
1241 while (transmem_list != NULL)
1243 old = transmem_list;
1244 transmem_list = transmem_list->next;
1245 free (old);
1248 #endif