]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/intl/dcigettext.c
commit bash-20080814 snapshot
[thirdparty/bash.git] / lib / intl / dcigettext.c
CommitLineData
2e4498b3 1/* dcigettext.c - Implementation of the internal dcigettext function. */
5e13499c 2
2e4498b3 3/* Copyright (C) 1995-1999, 2000-2003, 2006-2008 Free Software Foundation, Inc.
5e13499c 4
2e4498b3
CR
5 This file is part of GNU Bash.
6
7 Bash 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.
11
12 Bash is distributed in the hope that it will be useful,
5e13499c 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
2e4498b3
CR
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
5e13499c 16
2e4498b3
CR
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
5e13499c
CR
20
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
27
28#ifdef HAVE_CONFIG_H
29# include <config.h>
30#endif
31
32#include <sys/types.h>
33
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
49char *alloca ();
50# endif
51# endif
52# endif
53# endif
54#endif
55
56#include <errno.h>
57#ifndef errno
58extern int errno;
59#endif
60#ifndef __set_errno
61# define __set_errno(val) errno = (val)
62#endif
63
64#include <stddef.h>
65#include <stdlib.h>
66#include <string.h>
67
68#if defined HAVE_UNISTD_H || defined _LIBC
69# include <unistd.h>
70#endif
71
72#include <locale.h>
73
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
87
88#if defined HAVE_SYS_PARAM_H || defined _LIBC
89# include <sys/param.h>
90#endif
91
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"
100
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
113
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
121
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
131
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
136
137/* @@ end of prolog @@ */
138
f75912ae
CR
139#if defined (SHELL) && !defined (HAVE_GETCWD)
140# define HAVE_GETCWD
141#endif
142
5e13499c
CR
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
154char *getwd ();
155# define getcwd(buf, max) getwd (buf)
156# else
157char *getcwd ();
158# endif
159# ifndef HAVE_STPCPY
160static char *stpcpy PARAMS ((char *dest, const char *src));
161# endif
162# ifndef HAVE_MEMPCPY
163static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
164# endif
165#endif
166
167/* Amount to increase buffer size by in each try. */
168#define PATH_INCR 32
169
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
177
178#ifndef _POSIX_PATH_MAX
179# define _POSIX_PATH_MAX 255
180#endif
181
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
185
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
190
191#if !defined PATH_MAX && defined MAXPATHLEN
192# define PATH_MAX MAXPATHLEN
193#endif
194
195#ifndef PATH_MAX
196# define PATH_MAX _POSIX_PATH_MAX
197#endif
198
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.
204 */
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
220
221/* This is the type used for the search tree where known translations
222 are stored. */
223struct known_translation_t
224{
225 /* Domain in which to search. */
226 char *domainname;
227
228 /* The category. */
229 int category;
230
231 /* State of the catalog counter at the point the string was found. */
232 int counter;
233
234 /* Catalog where the string was found. */
235 struct loaded_l10nfile *domain;
236
237 /* And finally the translation. */
238 const char *translation;
239 size_t translation_length;
240
241 /* Pointer to the string in question. */
242 char msgid[ZERO];
243};
244
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>
249
250static void *root;
251
252# ifdef _LIBC
253# define tsearch __tsearch
254# endif
255
256/* Function to compare two entries in the table of known translations. */
257static int transcmp PARAMS ((const void *p1, const void *p2));
258static int
259transcmp (p1, p2)
260 const void *p1;
261 const void *p2;
262{
263 const struct known_translation_t *s1;
264 const struct known_translation_t *s2;
265 int result;
266
267 s1 = (const struct known_translation_t *) p1;
268 s2 = (const struct known_translation_t *) p2;
269
270 result = strcmp (s1->msgid, s2->msgid);
271 if (result == 0)
272 {
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;
279 }
280
281 return result;
282}
283#endif
284
285#ifndef INTVARDEF
286# define INTVARDEF(name)
287#endif
288#ifndef INTUSE
289# define INTUSE(name) name
290#endif
291
292/* Name of the default domain used for gettext(3) prior any call to
293 textdomain(3). The default value for this is "messages". */
294const char _nl_default_default_domain[] attribute_hidden = "messages";
295
296/* Value used as the default domain for gettext(3). */
297const char *_nl_current_default_domain attribute_hidden
298 = _nl_default_default_domain;
299
300/* Contains the default location of the message catalogs. */
301#if defined __EMX__
302extern const char _nl_default_dirname[];
303#else
304const char _nl_default_dirname[] = LOCALEDIR;
305INTVARDEF (_nl_default_dirname)
306#endif
307
308/* List with bindings of specific domains created by bindtextdomain()
309 calls. */
310struct binding *_nl_domain_bindings;
311
312/* Prototypes for local functions. */
313static 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;
318static 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
325static const char *category_to_name PARAMS ((int category)) internal_function;
326#endif
327
328
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
337struct block_list
338{
339 void *address;
340 struct block_list *next;
341};
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; \
351 } \
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); \
360 } \
361 } while (0)
362# undef alloca
363# define alloca(size) (malloc (size))
364# define freea(p) free (p)
365#endif /* have alloca */
366
367
368#ifdef _LIBC
369/* List of blocks allocated for translations. */
370typedef struct transmem_list
371{
372 struct transmem_list *next;
373 char data[ZERO];
374} transmem_block_t;
375static struct transmem_list *transmem_list;
376#else
377typedef unsigned char transmem_block_t;
378#endif
379
380
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
390
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
395
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
414static int enable_secure;
415# define ENABLE_SECURE (enable_secure == 1)
416# define DETERMINE_SECURE \
417 if (enable_secure == 0) \
418 { \
419 if (getuid () != geteuid () || getgid () != getegid ()) \
420 enable_secure = 1; \
421 else \
422 enable_secure = -1; \
423 }
424#endif
425
ec2199bd
CR
426#ifndef HAVE_RAISE
427# define raise(x) kill (getpid (), (x))
428#endif
429
5e13499c
CR
430/* Get the function to evaluate the plural expression. */
431#include "eval-plural.h"
432
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. */
436char *
437DCIGETTEXT (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;
444{
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;
463
464 /* If no real MSGID is given return NULL. */
465 if (msgid1 == NULL)
466 return NULL;
467
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
476
477 __libc_rwlock_rdlock (_nl_state_lock);
478
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;
484
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
490
491#if defined HAVE_TSEARCH || defined _LIBC
492 msgid_len = strlen (msgid1) + 1;
493
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;
501
502 foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
503 freea (search);
504 if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
505 {
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;
512
513 __libc_rwlock_unlock (_nl_state_lock);
514 return retval;
515 }
516#endif
517
518 /* Preserve the `errno' value. */
519 saved_errno = errno;
520
521 /* See whether this is a SUID binary or not. */
522 DETERMINE_SECURE;
523
524 /* First find matching binding. */
525 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
526 {
527 int compare = strcmp (domainname, binding->domainname);
528 if (compare == 0)
529 /* We found it! */
530 break;
531 if (compare < 0)
532 {
533 /* It is not in the list. */
534 binding = NULL;
535 break;
536 }
537 }
538
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
544 {
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;
549
550 path_max = (unsigned int) PATH_MAX;
551 path_max += 2; /* The getcwd docs say to do this. */
552
553 for (;;)
554 {
555 dirname = (char *) alloca (path_max + dirname_len);
556 ADD_BLOCK (block_list, dirname);
557
558 __set_errno (0);
559 ret = getcwd (dirname, path_max);
560 if (ret != NULL || errno != ERANGE)
561 break;
562
563 path_max += path_max / 2;
564 path_max += PATH_INCR;
565 }
566
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;
571
572 stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
573 }
574
575 /* Now determine the symbolic name of CATEGORY and its value. */
576 categoryname = category_to_name (category);
577 categoryvalue = guess_category_value (category, categoryname);
578
579 domainname_len = strlen (domainname);
580 xdomainname = (char *) alloca (strlen (categoryname)
581 + domainname_len + 5);
582 ADD_BLOCK (block_list, xdomainname);
583
584 stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
585 domainname, domainname_len),
586 ".mo");
587
588 /* Creating working area. */
589 single_locale = (char *) alloca (strlen (categoryvalue) + 1);
590 ADD_BLOCK (block_list, single_locale);
591
592
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)
596 {
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')
601 {
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';
608 }
609 else
610 {
611 char *cp = single_locale;
612 while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
613 *cp++ = *categoryvalue++;
614 *cp = '\0';
615
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;
621 }
622
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;
628
629 /* Find structure describing the message catalog matching the
630 DOMAINNAME and CATEGORY. */
631 domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
632
633 if (domain != NULL)
634 {
635 retval = _nl_find_msg (domain, binding, msgid1, &retlen);
636
637 if (retval == NULL)
638 {
639 int cnt;
640
641 for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
642 {
643 retval = _nl_find_msg (domain->successor[cnt], binding,
644 msgid1, &retlen);
645
646 if (retval != NULL)
647 {
648 domain = domain->successor[cnt];
649 break;
650 }
651 }
652 }
653
654 if (retval != NULL)
655 {
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)
661 {
662 /* Create a new entry and add it to the search tree. */
663 struct known_translation_t *newp;
664
665 newp = (struct known_translation_t *)
666 malloc (offsetof (struct known_translation_t, msgid)
667 + msgid_len + domainname_len + 1);
668 if (newp != NULL)
669 {
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;
678
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);
686 }
687 }
688 else
689 {
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;
695 }
696#endif
697 __set_errno (saved_errno);
698
699 /* Now deal with plural. */
700 if (plural)
701 retval = plural_lookup (domain, n, retval, retlen);
702
703 __libc_rwlock_unlock (_nl_state_lock);
704 return retval;
705 }
706 }
707 }
708
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)
715 {
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");
722
723 if (logfilename != NULL && logfilename[0] != '\0')
724 _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
725 }
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);
732}
733
734
735char *
736internal_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;
742{
743 struct loaded_domain *domain;
744 nls_uint32 nstrings;
745 size_t act;
746 char *result;
747 size_t resultlen;
748
749 if (domain_file->decided == 0)
750 _nl_load_domain (domain_file, domainbinding);
751
752 if (domain_file->data == NULL)
753 return NULL;
754
755 domain = (struct loaded_domain *) domain_file->data;
756
757 nstrings = domain->nstrings;
758
759 /* Locate the MSGID and its translation. */
760 if (domain->hash_tab != NULL)
761 {
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));
767
768 while (1)
769 {
770 nls_uint32 nstr =
771 W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
772
773 if (nstr == 0)
774 /* Hash table entry is empty. */
775 return NULL;
776
777 nstr--;
778
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))
792 {
793 act = nstr;
794 goto found;
795 }
796
797 if (idx >= domain->hash_size - incr)
798 idx -= domain->hash_size - incr;
799 else
800 idx += incr;
801 }
802 /* NOTREACHED */
803 }
804 else
805 {
806 /* Try the default method: binary search in the sorted array of
807 messages. */
808 size_t top, bottom;
809
810 bottom = 0;
811 top = nstrings;
812 while (bottom < top)
813 {
814 int cmp_val;
815
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;
826 }
827 /* No translation was found. */
828 return NULL;
829 }
830
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)
835 {
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;
839 }
840 else
841 {
842 result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
843 resultlen = domain->trans_sysdep_tab[act - nstrings].length;
844 }
845
846#if defined _LIBC || HAVE_ICONV
847 if (domain->codeset_cntr
848 != (domainbinding != NULL ? domainbinding->codeset_cntr : 0))
849 {
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);
855 }
856
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
865 )
866 {
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. */
875
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;
883
884 if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
885 /* Nothing we can do, no more memory. */
886 goto converted;
887
888 if (domain->conv_tab[act] == NULL)
889 {
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;
899
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
906
907 __libc_lock_lock (lock);
908
909 inbuf = (const unsigned char *) result;
910 outbuf = freemem + sizeof (size_t);
911
912 malloc_count = 0;
913 while (1)
914 {
915 transmem_block_t *newmem;
916# ifdef _LIBC
917 size_t non_reversible;
918 int res;
919
920 if (freemem_size < sizeof (size_t))
921 goto resize_freemem;
922
923 res = __gconv (domain->conv,
924 &inbuf, inbuf + resultlen,
925 &outbuf,
926 outbuf + freemem_size - sizeof (size_t),
927 &non_reversible);
928
929 if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
930 break;
931
932 if (res != __GCONV_FULL_OUTPUT)
933 {
934 __libc_lock_unlock (lock);
935 goto converted;
936 }
937
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;
945
946 if (freemem_size < sizeof (size_t))
947 goto resize_freemem;
948
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))
954 {
955 outbuf = (unsigned char *) outptr;
956 break;
957 }
958 if (errno != E2BIG)
959 {
960 __libc_lock_unlock (lock);
961 goto converted;
962 }
963# endif
964# endif
965
966 resize_freemem:
967 /* We must allocate a new buffer or resize the old one. */
968 if (malloc_count > 0)
969 {
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
978 {
979 struct transmem_list *old = transmem_list;
980
981 transmem_list = transmem_list->next;
982 free (old);
983 }
984# endif
985 }
986 else
987 {
988 malloc_count = 1;
989 freemem_size = INITIAL_BLOCK_SIZE;
990 newmem = (transmem_block_t *) malloc (freemem_size);
991 }
992 if (__builtin_expect (newmem == NULL, 0))
993 {
994 freemem = NULL;
995 freemem_size = 0;
996 __libc_lock_unlock (lock);
997 goto converted;
998 }
999
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;
1005
1006 freemem = newmem->data;
1007 freemem_size -= offsetof (struct transmem_list, data);
1008# else
1009 transmem_list = newmem;
1010 freemem = newmem;
1011# endif
1012
1013 outbuf = freemem + sizeof (size_t);
1014 }
1015
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);
1025
1026 __libc_lock_unlock (lock);
1027 }
1028
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];
1033 }
1034
1035 converted:
1036 /* The result string is converted. */
1037
1038#endif /* _LIBC || HAVE_ICONV */
1039
1040 *lengthp = resultlen;
1041 return result;
1042}
1043
1044
1045/* Look up a plural variant. */
1046static char *
1047internal_function
1048plural_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;
1053{
1054 struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
1055 unsigned long int index;
1056 const char *p;
1057
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;
1063
1064 /* Skip INDEX strings at TRANSLATION. */
1065 p = translation;
1066 while (index-- > 0)
1067 {
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++;
1075
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;
1081 }
1082 return (char *) p;
1083}
1084
1085#ifndef _LIBC
1086/* Return string representation of locale CATEGORY. */
1087static const char *
1088internal_function
1089category_to_name (category)
1090 int category;
1091{
1092 const char *retval;
1093
1094 switch (category)
1095 {
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";
1141 }
1142
1143 return retval;
1144}
1145#endif
1146
1147/* Guess value of current locale from value of the environment variables. */
1148static const char *
1149internal_function
1150guess_category_value (category, categoryname)
1151 int category;
1152 const char *categoryname;
1153{
1154 const char *language;
1155 const char *retval;
1156
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;
1163
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
1172
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;
1183}
1184
1185/* @@ begin of epilog @@ */
1186
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
1192static char *
1193stpcpy (dest, src)
1194 char *dest;
1195 const char *src;
1196{
1197 while ((*dest++ = *src++) != '\0')
1198 /* Do nothing. */ ;
1199 return dest - 1;
1200}
1201#endif
1202
1203#if !_LIBC && !HAVE_MEMPCPY
1204static void *
1205mempcpy (dest, src, n)
1206 void *dest;
1207 const void *src;
1208 size_t n;
1209{
1210 return (void *) ((char *) memcpy (dest, src, n) + n);
1211}
1212#endif
1213
1214
1215#ifdef _LIBC
1216/* If we want to free all resources we have to do some work at
1217 program's end. */
1218libc_freeres_fn (free_mem)
1219{
1220 void *old;
1221
1222 while (_nl_domain_bindings != NULL)
1223 {
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);
1231 }
1232
1233 if (_nl_current_default_domain != _nl_default_default_domain)
1234 /* Yes, again a pointer comparison. */
1235 free ((char *) _nl_current_default_domain);
1236
1237 /* Remove the search tree with the known translations. */
1238 __tdestroy (root, free);
1239 root = NULL;
1240
1241 while (transmem_list != NULL)
1242 {
1243 old = transmem_list;
1244 transmem_list = transmem_list->next;
1245 free (old);
1246 }
1247}
1248#endif