(DCIGETTEXT): Release the lock before returning.
[kopensolaris-gnu/glibc.git] / intl / dcigettext.c
1 /* Implementation of the internal dcigettext function.
2    Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public
15    License along with the GNU C Library; see the file COPYING.LIB.  If not,
16    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17    Boston, MA 02111-1307, USA.  */
18
19 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
20    This must come before <config.h> because <config.h> may include
21    <features.h>, and once <features.h> has been included, it's too late.  */
22 #ifndef _GNU_SOURCE
23 # define _GNU_SOURCE    1
24 #endif
25
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29
30 #include <sys/types.h>
31
32 #if defined __GNUC__ && !defined C_ALLOCA
33 # define alloca __builtin_alloca
34 # define HAVE_ALLOCA 1
35 #else
36 # if (defined HAVE_ALLOCA_H || defined _LIBC) && !defined C_ALLOCA
37 #  include <alloca.h>
38 # else
39 #  ifdef _AIX
40  #pragma alloca
41 #  else
42 #   ifndef alloca
43 char *alloca ();
44 #   endif
45 #  endif
46 # endif
47 #endif
48
49 #include <errno.h>
50 #ifndef errno
51 extern int errno;
52 #endif
53 #ifndef __set_errno
54 # define __set_errno(val) errno = (val)
55 #endif
56
57 #if defined STDC_HEADERS || defined _LIBC
58 # include <stddef.h>
59 # include <stdlib.h>
60 #else
61 char *getenv ();
62 # ifdef HAVE_MALLOC_H
63 #  include <malloc.h>
64 # else
65 void free ();
66 # endif
67 #endif
68
69 #if defined HAVE_STRING_H || defined _LIBC
70 # include <string.h>
71 #else
72 # include <strings.h>
73 #endif
74 #if !HAVE_STRCHR && !defined _LIBC
75 # ifndef strchr
76 #  define strchr index
77 # endif
78 #endif
79
80 #if defined HAVE_UNISTD_H || defined _LIBC
81 # include <unistd.h>
82 #endif
83
84 #if defined HAVE_LOCALE_H || defined _LIBC
85 # include <locale.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 #ifdef _LIBC
94 # include <libintl.h>
95 #else
96 # include "libgnuintl.h"
97 #endif
98 #include "hash-string.h"
99
100 /* Thread safetyness.  */
101 #ifdef _LIBC
102 # include <bits/libc-lock.h>
103 #else
104 /* Provide dummy implementation if this is outside glibc.  */
105 # define __libc_lock_define_initialized(CLASS, NAME)
106 # define __libc_lock_lock(NAME)
107 # define __libc_lock_unlock(NAME)
108 # define __libc_rwlock_define_initialized(CLASS, NAME)
109 # define __libc_rwlock_rdlock(NAME)
110 # define __libc_rwlock_unlock(NAME)
111 #endif
112
113 /* Alignment of types.  */
114 #if defined __GNUC__ && __GNUC__ >= 2
115 # define alignof(TYPE) __alignof__ (TYPE)
116 #else
117 # define alignof(TYPE) \
118     ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
119 #endif
120
121 /* The internal variables in the standalone libintl.a must have different
122    names than the internal variables in GNU libc, otherwise programs
123    using libintl.a cannot be linked statically.  */
124 #if !defined _LIBC
125 # define _nl_default_default_domain _nl_default_default_domain__
126 # define _nl_current_default_domain _nl_current_default_domain__
127 # define _nl_default_dirname _nl_default_dirname__
128 # define _nl_domain_bindings _nl_domain_bindings__
129 #endif
130
131 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
132 #ifndef offsetof
133 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
134 #endif
135
136 /* @@ end of prolog @@ */
137
138 #ifdef _LIBC
139 /* Rename the non ANSI C functions.  This is required by the standard
140    because some ANSI C functions will require linking with this object
141    file and the name space must not be polluted.  */
142 # define getcwd __getcwd
143 # ifndef stpcpy
144 #  define stpcpy __stpcpy
145 # endif
146 # define tfind __tfind
147 #else
148 # if !defined HAVE_GETCWD
149 char *getwd ();
150 #  define getcwd(buf, max) getwd (buf)
151 # else
152 char *getcwd ();
153 # endif
154 # ifndef HAVE_STPCPY
155 static char *stpcpy PARAMS ((char *dest, const char *src));
156 # endif
157 # ifndef HAVE_MEMPCPY
158 static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
159 # endif
160 #endif
161
162 /* Amount to increase buffer size by in each try.  */
163 #define PATH_INCR 32
164
165 /* The following is from pathmax.h.  */
166 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
167    PATH_MAX but might cause redefinition warnings when sys/param.h is
168    later included (as on MORE/BSD 4.3).  */
169 #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
170 # include <limits.h>
171 #endif
172
173 #ifndef _POSIX_PATH_MAX
174 # define _POSIX_PATH_MAX 255
175 #endif
176
177 #if !defined PATH_MAX && defined _PC_PATH_MAX
178 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
179 #endif
180
181 /* Don't include sys/param.h if it already has been.  */
182 #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
183 # include <sys/param.h>
184 #endif
185
186 #if !defined PATH_MAX && defined MAXPATHLEN
187 # define PATH_MAX MAXPATHLEN
188 #endif
189
190 #ifndef PATH_MAX
191 # define PATH_MAX _POSIX_PATH_MAX
192 #endif
193
194 /* XPG3 defines the result of `setlocale (category, NULL)' as:
195    ``Directs `setlocale()' to query `category' and return the current
196      setting of `local'.''
197    However it does not specify the exact format.  Neither do SUSV2 and
198    ISO C 99.  So we can use this feature only on selected systems (e.g.
199    those using GNU C Library).  */
200 #ifdef _LIBC
201 # define HAVE_LOCALE_NULL
202 #endif
203
204 /* This is the type used for the search tree where known translations
205    are stored.  */
206 struct known_translation_t
207 {
208   /* Domain in which to search.  */
209   char *domainname;
210
211   /* The category.  */
212   int category;
213
214   /* State of the catalog counter at the point the string was found.  */
215   int counter;
216
217   /* Catalog where the string was found.  */
218   struct loaded_l10nfile *domain;
219
220   /* And finally the translation.  */
221   const char *translation;
222   size_t translation_length;
223
224   /* Pointer to the string in question.  */
225   char msgid[ZERO];
226 };
227
228 /* Root of the search tree with known translations.  We can use this
229    only if the system provides the `tsearch' function family.  */
230 #if defined HAVE_TSEARCH || defined _LIBC
231 # include <search.h>
232
233 static void *root;
234
235 # ifdef _LIBC
236 #  define tsearch __tsearch
237 # endif
238
239 /* Function to compare two entries in the table of known translations.  */
240 static int transcmp PARAMS ((const void *p1, const void *p2));
241 static int
242 transcmp (p1, p2)
243      const void *p1;
244      const void *p2;
245 {
246   const struct known_translation_t *s1;
247   const struct known_translation_t *s2;
248   int result;
249
250   s1 = (const struct known_translation_t *) p1;
251   s2 = (const struct known_translation_t *) p2;
252
253   result = strcmp (s1->msgid, s2->msgid);
254   if (result == 0)
255     {
256       result = strcmp (s1->domainname, s2->domainname);
257       if (result == 0)
258         /* We compare the category last (though this is the cheapest
259            operation) since it is hopefully always the same (namely
260            LC_MESSAGES).  */
261         result = s1->category - s2->category;
262     }
263
264   return result;
265 }
266 #endif
267
268 /* Name of the default domain used for gettext(3) prior any call to
269    textdomain(3).  The default value for this is "messages".  */
270 const char _nl_default_default_domain[] = "messages";
271
272 /* Value used as the default domain for gettext(3).  */
273 const char *_nl_current_default_domain = _nl_default_default_domain;
274
275 /* Contains the default location of the message catalogs.  */
276 const char _nl_default_dirname[] = LOCALEDIR;
277
278 /* List with bindings of specific domains created by bindtextdomain()
279    calls.  */
280 struct binding *_nl_domain_bindings;
281
282 /* Prototypes for local functions.  */
283 static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
284                                     unsigned long int n,
285                                     const char *translation,
286                                     size_t translation_len))
287      internal_function;
288 static unsigned long int plural_eval PARAMS ((struct expression *pexp,
289                                               unsigned long int n))
290      internal_function;
291 static const char *category_to_name PARAMS ((int category)) internal_function;
292 static const char *guess_category_value PARAMS ((int category,
293                                                  const char *categoryname))
294      internal_function;
295
296
297 /* For those loosing systems which don't have `alloca' we have to add
298    some additional code emulating it.  */
299 #ifdef HAVE_ALLOCA
300 /* Nothing has to be done.  */
301 # define ADD_BLOCK(list, address) /* nothing */
302 # define FREE_BLOCKS(list) /* nothing */
303 #else
304 struct block_list
305 {
306   void *address;
307   struct block_list *next;
308 };
309 # define ADD_BLOCK(list, addr)                                                \
310   do {                                                                        \
311     struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
312     /* If we cannot get a free block we cannot add the new element to         \
313        the list.  */                                                          \
314     if (newp != NULL) {                                                       \
315       newp->address = (addr);                                                 \
316       newp->next = (list);                                                    \
317       (list) = newp;                                                          \
318     }                                                                         \
319   } while (0)
320 # define FREE_BLOCKS(list)                                                    \
321   do {                                                                        \
322     while (list != NULL) {                                                    \
323       struct block_list *old = list;                                          \
324       list = list->next;                                                      \
325       free (old);                                                             \
326     }                                                                         \
327   } while (0)
328 # undef alloca
329 # define alloca(size) (malloc (size))
330 #endif  /* have alloca */
331
332
333 #ifdef _LIBC
334 /* List of blocks allocated for translations.  */
335 typedef struct transmem_list
336 {
337   struct transmem_list *next;
338   char data[ZERO];
339 } transmem_block_t;
340 static struct transmem_list *transmem_list;
341 #else
342 typedef unsigned char transmem_block_t;
343 #endif
344
345
346 /* Names for the libintl functions are a problem.  They must not clash
347    with existing names and they should follow ANSI C.  But this source
348    code is also used in GNU C Library where the names have a __
349    prefix.  So we have to make a difference here.  */
350 #ifdef _LIBC
351 # define DCIGETTEXT __dcigettext
352 #else
353 # define DCIGETTEXT dcigettext__
354 #endif
355
356 /* Lock variable to protect the global data in the gettext implementation.  */
357 __libc_rwlock_define_initialized (, _nl_state_lock)
358
359 /* Checking whether the binaries runs SUID must be done and glibc provides
360    easier methods therefore we make a difference here.  */
361 #ifdef _LIBC
362 # define ENABLE_SECURE __libc_enable_secure
363 # define DETERMINE_SECURE
364 #else
365 static int enable_secure;
366 # define ENABLE_SECURE (enable_secure == 1)
367 # define DETERMINE_SECURE \
368   if (enable_secure == 0)                                                     \
369     {                                                                         \
370       if (getuid () != geteuid () || getgid () != getegid ())                 \
371         enable_secure = 1;                                                    \
372       else                                                                    \
373         enable_secure = -1;                                                   \
374     }
375 #endif
376
377 /* Look up MSGID in the DOMAINNAME message catalog for the current
378    CATEGORY locale and, if PLURAL is nonzero, search over string
379    depending on the plural form determined by N.  */
380 char *
381 DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
382      const char *domainname;
383      const char *msgid1;
384      const char *msgid2;
385      int plural;
386      unsigned long int n;
387      int category;
388 {
389 #ifndef HAVE_ALLOCA
390   struct block_list *block_list = NULL;
391 #endif
392   struct loaded_l10nfile *domain;
393   struct binding *binding;
394   const char *categoryname;
395   const char *categoryvalue;
396   char *dirname, *xdomainname;
397   char *single_locale;
398   char *retval;
399   size_t retlen;
400   int saved_errno;
401 #if defined HAVE_TSEARCH || defined _LIBC
402   struct known_translation_t *search;
403   struct known_translation_t **foundp = NULL;
404   size_t msgid_len;
405 #endif
406   size_t domainname_len;
407
408   /* If no real MSGID is given return NULL.  */
409   if (msgid1 == NULL)
410     return NULL;
411
412   __libc_rwlock_rdlock (_nl_state_lock);
413
414   /* If DOMAINNAME is NULL, we are interested in the default domain.  If
415      CATEGORY is not LC_MESSAGES this might not make much sense but the
416      definition left this undefined.  */
417   if (domainname == NULL)
418     domainname = _nl_current_default_domain;
419
420 #if defined HAVE_TSEARCH || defined _LIBC
421   msgid_len = strlen (msgid1) + 1;
422
423   /* Try to find the translation among those which we found at
424      some time.  */
425   search = (struct known_translation_t *)
426            alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
427   memcpy (search->msgid, msgid1, msgid_len);
428   search->domainname = (char *) domainname;
429   search->category = category;
430
431   foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
432   if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
433     {
434       /* Now deal with plural.  */
435       if (plural)
436         retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
437                                 (*foundp)->translation_length);
438       else
439         retval = (char *) (*foundp)->translation;
440
441       __libc_rwlock_unlock (_nl_state_lock);
442       return retval;
443     }
444 #endif
445
446   /* Preserve the `errno' value.  */
447   saved_errno = errno;
448
449   /* See whether this is a SUID binary or not.  */
450   DETERMINE_SECURE;
451
452   /* First find matching binding.  */
453   for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
454     {
455       int compare = strcmp (domainname, binding->domainname);
456       if (compare == 0)
457         /* We found it!  */
458         break;
459       if (compare < 0)
460         {
461           /* It is not in the list.  */
462           binding = NULL;
463           break;
464         }
465     }
466
467   if (binding == NULL)
468     dirname = (char *) _nl_default_dirname;
469   else if (binding->dirname[0] == '/')
470     dirname = binding->dirname;
471   else
472     {
473       /* We have a relative path.  Make it absolute now.  */
474       size_t dirname_len = strlen (binding->dirname) + 1;
475       size_t path_max;
476       char *ret;
477
478       path_max = (unsigned int) PATH_MAX;
479       path_max += 2;            /* The getcwd docs say to do this.  */
480
481       dirname = (char *) alloca (path_max + dirname_len);
482       ADD_BLOCK (block_list, dirname);
483
484       __set_errno (0);
485       while ((ret = getcwd (dirname, path_max)) == NULL && errno == ERANGE)
486         {
487           path_max += PATH_INCR;
488           dirname = (char *) alloca (path_max + dirname_len);
489           ADD_BLOCK (block_list, dirname);
490           __set_errno (0);
491         }
492
493       if (ret == NULL)
494         {
495           /* We cannot get the current working directory.  Don't signal an
496              error but simply return the default string.  */
497           FREE_BLOCKS (block_list);
498           __libc_rwlock_unlock (_nl_state_lock);
499           __set_errno (saved_errno);
500           return (plural == 0
501                   ? (char *) msgid1
502                   /* Use the Germanic plural rule.  */
503                   : n == 1 ? (char *) msgid1 : (char *) msgid2);
504         }
505
506       stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
507     }
508
509   /* Now determine the symbolic name of CATEGORY and its value.  */
510   categoryname = category_to_name (category);
511   categoryvalue = guess_category_value (category, categoryname);
512
513   domainname_len = strlen (domainname);
514   xdomainname = (char *) alloca (strlen (categoryname)
515                                  + domainname_len + 5);
516   ADD_BLOCK (block_list, xdomainname);
517
518   stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
519                   domainname, domainname_len),
520           ".mo");
521
522   /* Creating working area.  */
523   single_locale = (char *) alloca (strlen (categoryvalue) + 1);
524   ADD_BLOCK (block_list, single_locale);
525
526
527   /* Search for the given string.  This is a loop because we perhaps
528      got an ordered list of languages to consider for the translation.  */
529   while (1)
530     {
531       /* Make CATEGORYVALUE point to the next element of the list.  */
532       while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
533         ++categoryvalue;
534       if (categoryvalue[0] == '\0')
535         {
536           /* The whole contents of CATEGORYVALUE has been searched but
537              no valid entry has been found.  We solve this situation
538              by implicitly appending a "C" entry, i.e. no translation
539              will take place.  */
540           single_locale[0] = 'C';
541           single_locale[1] = '\0';
542         }
543       else
544         {
545           char *cp = single_locale;
546           while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
547             *cp++ = *categoryvalue++;
548           *cp = '\0';
549
550           /* When this is a SUID binary we must not allow accessing files
551              outside the dedicated directories.  */
552           if (ENABLE_SECURE && strchr (single_locale, '/') != NULL)
553             /* Ingore this entry.  */
554             continue;
555         }
556
557       /* If the current locale value is C (or POSIX) we don't load a
558          domain.  Return the MSGID.  */
559       if (strcmp (single_locale, "C") == 0
560           || strcmp (single_locale, "POSIX") == 0)
561         {
562           FREE_BLOCKS (block_list);
563           __libc_rwlock_unlock (_nl_state_lock);
564           __set_errno (saved_errno);
565           return (plural == 0
566                   ? (char *) msgid1
567                   /* Use the Germanic plural rule.  */
568                   : n == 1 ? (char *) msgid1 : (char *) msgid2);
569         }
570
571
572       /* Find structure describing the message catalog matching the
573          DOMAINNAME and CATEGORY.  */
574       domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
575
576       if (domain != NULL)
577         {
578           retval = _nl_find_msg (domain, binding, msgid1, &retlen);
579
580           if (retval == NULL)
581             {
582               int cnt;
583
584               for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
585                 {
586                   retval = _nl_find_msg (domain->successor[cnt], binding,
587                                          msgid1, &retlen);
588
589                   if (retval != NULL)
590                     {
591                       domain = domain->successor[cnt];
592                       break;
593                     }
594                 }
595             }
596
597           if (retval != NULL)
598             {
599               /* Found the translation of MSGID1 in domain DOMAIN:
600                  starting at RETVAL, RETLEN bytes.  */
601               FREE_BLOCKS (block_list);
602               __set_errno (saved_errno);
603 #if defined HAVE_TSEARCH || defined _LIBC
604               if (foundp == NULL)
605                 {
606                   /* Create a new entry and add it to the search tree.  */
607                   struct known_translation_t *newp;
608
609                   newp = (struct known_translation_t *)
610                     malloc (offsetof (struct known_translation_t, msgid)
611                             + msgid_len + domainname_len + 1);
612                   if (newp != NULL)
613                     {
614                       newp->domainname =
615                         mempcpy (newp->msgid, msgid1, msgid_len);
616                       memcpy (newp->domainname, domainname, domainname_len + 1);
617                       newp->category = category;
618                       newp->counter = _nl_msg_cat_cntr;
619                       newp->domain = domain;
620                       newp->translation = retval;
621                       newp->translation_length = retlen;
622
623                       /* Insert the entry in the search tree.  */
624                       foundp = (struct known_translation_t **)
625                         tsearch (newp, &root, transcmp);
626                       if (foundp == NULL
627                           || __builtin_expect (*foundp != newp, 0))
628                         /* The insert failed.  */
629                         free (newp);
630                     }
631                 }
632               else
633                 {
634                   /* We can update the existing entry.  */
635                   (*foundp)->counter = _nl_msg_cat_cntr;
636                   (*foundp)->domain = domain;
637                   (*foundp)->translation = retval;
638                   (*foundp)->translation_length = retlen;
639                 }
640 #endif
641               /* Now deal with plural.  */
642               if (plural)
643                 retval = plural_lookup (domain, n, retval, retlen);
644
645               __libc_rwlock_unlock (_nl_state_lock);
646               return retval;
647             }
648         }
649     }
650   /* NOTREACHED */
651 }
652
653
654 char *
655 internal_function
656 _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
657      struct loaded_l10nfile *domain_file;
658      struct binding *domainbinding;
659      const char *msgid;
660      size_t *lengthp;
661 {
662   struct loaded_domain *domain;
663   size_t act;
664   char *result;
665   size_t resultlen;
666
667   if (domain_file->decided == 0)
668     _nl_load_domain (domain_file, domainbinding);
669
670   if (domain_file->data == NULL)
671     return NULL;
672
673   domain = (struct loaded_domain *) domain_file->data;
674
675   /* Locate the MSGID and its translation.  */
676   if (domain->hash_size > 2 && domain->hash_tab != NULL)
677     {
678       /* Use the hashing table.  */
679       nls_uint32 len = strlen (msgid);
680       nls_uint32 hash_val = hash_string (msgid);
681       nls_uint32 idx = hash_val % domain->hash_size;
682       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
683
684       while (1)
685         {
686           nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
687
688           if (nstr == 0)
689             /* Hash table entry is empty.  */
690             return NULL;
691
692           /* Compare msgid with the original string at index nstr-1.
693              We compare the lengths with >=, not ==, because plural entries
694              are represented by strings with an embedded NUL.  */
695           if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) >= len
696               && (strcmp (msgid,
697                           domain->data + W (domain->must_swap,
698                                             domain->orig_tab[nstr - 1].offset))
699                   == 0))
700             {
701               act = nstr - 1;
702               goto found;
703             }
704
705           if (idx >= domain->hash_size - incr)
706             idx -= domain->hash_size - incr;
707           else
708             idx += incr;
709         }
710       /* NOTREACHED */
711     }
712   else
713     {
714       /* Try the default method:  binary search in the sorted array of
715          messages.  */
716       size_t top, bottom;
717
718       bottom = 0;
719       top = domain->nstrings;
720       while (bottom < top)
721         {
722           int cmp_val;
723
724           act = (bottom + top) / 2;
725           cmp_val = strcmp (msgid, (domain->data
726                                     + W (domain->must_swap,
727                                          domain->orig_tab[act].offset)));
728           if (cmp_val < 0)
729             top = act;
730           else if (cmp_val > 0)
731             bottom = act + 1;
732           else
733             goto found;
734         }
735       /* No translation was found.  */
736       return NULL;
737     }
738
739  found:
740   /* The translation was found at index ACT.  If we have to convert the
741      string to use a different character set, this is the time.  */
742   result = ((char *) domain->data
743             + W (domain->must_swap, domain->trans_tab[act].offset));
744   resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
745
746 #if defined _LIBC || HAVE_ICONV
747   if (domain->codeset_cntr
748       != (domainbinding != NULL ? domainbinding->codeset_cntr : 0))
749     {
750       /* The domain's codeset has changed through bind_textdomain_codeset()
751          since the message catalog was initialized or last accessed.  We
752          have to reinitialize the converter.  */
753       _nl_free_domain_conv (domain);
754       _nl_init_domain_conv (domain_file, domain, domainbinding);
755     }
756
757   if (
758 # ifdef _LIBC
759       domain->conv != (__gconv_t) -1
760 # else
761 #  if HAVE_ICONV
762       domain->conv != (iconv_t) -1
763 #  endif
764 # endif
765       )
766     {
767       /* We are supposed to do a conversion.  First allocate an
768          appropriate table with the same structure as the table
769          of translations in the file, where we can put the pointers
770          to the converted strings in.
771          There is a slight complication with plural entries.  They
772          are represented by consecutive NUL terminated strings.  We
773          handle this case by converting RESULTLEN bytes, including
774          NULs.  */
775
776       if (domain->conv_tab == NULL
777           && ((domain->conv_tab = (char **) calloc (domain->nstrings,
778                                                     sizeof (char *)))
779               == NULL))
780         /* Mark that we didn't succeed allocating a table.  */
781         domain->conv_tab = (char **) -1;
782
783       if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
784         /* Nothing we can do, no more memory.  */
785         goto converted;
786
787       if (domain->conv_tab[act] == NULL)
788         {
789           /* We haven't used this string so far, so it is not
790              translated yet.  Do this now.  */
791           /* We use a bit more efficient memory handling.
792              We allocate always larger blocks which get used over
793              time.  This is faster than many small allocations.   */
794           __libc_lock_define_initialized (static, lock)
795 # define INITIAL_BLOCK_SIZE     4080
796           static unsigned char *freemem;
797           static size_t freemem_size;
798
799           const unsigned char *inbuf;
800           unsigned char *outbuf;
801           int malloc_count;
802 # ifndef _LIBC
803           transmem_block_t *transmem_list = NULL;
804 # endif
805
806           __libc_lock_lock (lock);
807
808           inbuf = (const unsigned char *) result;
809           outbuf = freemem + sizeof (size_t);
810
811           malloc_count = 0;
812           while (1)
813             {
814               transmem_block_t *newmem;
815 # ifdef _LIBC
816               size_t non_reversible;
817               int res;
818
819               if (freemem_size < sizeof (size_t))
820                 goto resize_freemem;
821
822               res = __gconv (domain->conv,
823                              &inbuf, inbuf + resultlen,
824                              &outbuf,
825                              outbuf + freemem_size - sizeof (size_t),
826                              &non_reversible);
827
828               if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
829                 break;
830
831               if (res != __GCONV_FULL_OUTPUT)
832                 {
833                   __libc_lock_unlock (lock);
834                   goto converted;
835                 }
836
837               inbuf = result;
838 # else
839 #  if HAVE_ICONV
840               const char *inptr = (const char *) inbuf;
841               size_t inleft = resultlen;
842               char *outptr = (char *) outbuf;
843               size_t outleft;
844
845               if (freemem_size < sizeof (size_t))
846                 goto resize_freemem;
847
848               outleft = freemem_size - sizeof (size_t);
849               if (iconv (domain->conv,
850                          (ICONV_CONST char **) &inptr, &inleft,
851                          &outptr, &outleft)
852                   != (size_t) (-1))
853                 {
854                   outbuf = (unsigned char *) outptr;
855                   break;
856                 }
857               if (errno != E2BIG)
858                 {
859                   __libc_lock_unlock (lock);
860                   goto converted;
861                 }
862 #  endif
863 # endif
864
865             resize_freemem:
866               /* We must allocate a new buffer or resize the old one.  */
867               if (malloc_count > 0)
868                 {
869                   ++malloc_count;
870                   freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
871                   newmem = (transmem_block_t *) realloc (transmem_list,
872                                                          freemem_size);
873 # ifdef _LIBC
874                   if (newmem != NULL)
875                     transmem_list = transmem_list->next;
876                   else
877                     {
878                       struct transmem_list *old = transmem_list;
879
880                       transmem_list = transmem_list->next;
881                       free (old);
882                     }
883 # endif
884                 }
885               else
886                 {
887                   malloc_count = 1;
888                   freemem_size = INITIAL_BLOCK_SIZE;
889                   newmem = (transmem_block_t *) malloc (freemem_size);
890                 }
891               if (__builtin_expect (newmem == NULL, 0))
892                 {
893                   freemem = NULL;
894                   freemem_size = 0;
895                   __libc_lock_unlock (lock);
896                   goto converted;
897                 }
898
899 # ifdef _LIBC
900               /* Add the block to the list of blocks we have to free
901                  at some point.  */
902               newmem->next = transmem_list;
903               transmem_list = newmem;
904
905               freemem = newmem->data;
906               freemem_size -= offsetof (struct transmem_list, data);
907 # else
908               transmem_list = newmem;
909               freemem = newmem;
910 # endif
911
912               outbuf = freemem + sizeof (size_t);
913             }
914
915           /* We have now in our buffer a converted string.  Put this
916              into the table of conversions.  */
917           *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
918           domain->conv_tab[act] = (char *) freemem;
919           /* Shrink freemem, but keep it aligned.  */
920           freemem_size -= outbuf - freemem;
921           freemem = outbuf;
922           freemem += freemem_size & (alignof (size_t) - 1);
923           freemem_size = freemem_size & ~ (alignof (size_t) - 1);
924
925           __libc_lock_unlock (lock);
926         }
927
928       /* Now domain->conv_tab[act] contains the translation of all
929          the plural variants.  */
930       result = domain->conv_tab[act] + sizeof (size_t);
931       resultlen = *(size_t *) domain->conv_tab[act];
932     }
933
934  converted:
935   /* The result string is converted.  */
936
937 #endif /* _LIBC || HAVE_ICONV */
938
939   *lengthp = resultlen;
940   return result;
941 }
942
943
944 /* Look up a plural variant.  */
945 static char *
946 internal_function
947 plural_lookup (domain, n, translation, translation_len)
948      struct loaded_l10nfile *domain;
949      unsigned long int n;
950      const char *translation;
951      size_t translation_len;
952 {
953   struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
954   unsigned long int index;
955   const char *p;
956
957   index = plural_eval (domaindata->plural, n);
958   if (index >= domaindata->nplurals)
959     /* This should never happen.  It means the plural expression and the
960        given maximum value do not match.  */
961     index = 0;
962
963   /* Skip INDEX strings at TRANSLATION.  */
964   p = translation;
965   while (index-- > 0)
966     {
967 #ifdef _LIBC
968       p = __rawmemchr (p, '\0');
969 #else
970       p = strchr (p, '\0');
971 #endif
972       /* And skip over the NUL byte.  */
973       p++;
974
975       if (p >= translation + translation_len)
976         /* This should never happen.  It means the plural expression
977            evaluated to a value larger than the number of variants
978            available for MSGID1.  */
979         return (char *) translation;
980     }
981   return (char *) p;
982 }
983
984
985 /* Function to evaluate the plural expression and return an index value.  */
986 static unsigned long int
987 internal_function
988 plural_eval (pexp, n)
989      struct expression *pexp;
990      unsigned long int n;
991 {
992   switch (pexp->nargs)
993     {
994     case 0:
995       switch (pexp->operation)
996         {
997         case var:
998           return n;
999         case num:
1000           return pexp->val.num;
1001         default:
1002           break;
1003         }
1004       /* NOTREACHED */
1005       break;
1006     case 1:
1007       {
1008         /* pexp->operation must be lnot.  */
1009         unsigned long int arg = plural_eval (pexp->val.args[0], n);
1010         return ! arg;
1011       }
1012     case 2:
1013       {
1014         unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
1015         if (pexp->operation == lor)
1016           return leftarg || plural_eval (pexp->val.args[1], n);
1017         else if (pexp->operation == land)
1018           return leftarg && plural_eval (pexp->val.args[1], n);
1019         else
1020           {
1021             unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
1022
1023             switch (pexp->operation)
1024               {
1025               case mult:
1026                 return leftarg * rightarg;
1027               case divide:
1028                 return leftarg / rightarg;
1029               case module:
1030                 return leftarg % rightarg;
1031               case plus:
1032                 return leftarg + rightarg;
1033               case minus:
1034                 return leftarg - rightarg;
1035               case less_than:
1036                 return leftarg < rightarg;
1037               case greater_than:
1038                 return leftarg > rightarg;
1039               case less_or_equal:
1040                 return leftarg <= rightarg;
1041               case greater_or_equal:
1042                 return leftarg >= rightarg;
1043               case equal:
1044                 return leftarg == rightarg;
1045               case not_equal:
1046                 return leftarg != rightarg;
1047               default:
1048                 break;
1049               }
1050           }
1051         /* NOTREACHED */
1052         break;
1053       }
1054     case 3:
1055       {
1056         /* pexp->operation must be qmop.  */
1057         unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
1058         return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
1059       }
1060     }
1061   /* NOTREACHED */
1062   return 0;
1063 }
1064
1065
1066 /* Return string representation of locale CATEGORY.  */
1067 static const char *
1068 internal_function
1069 category_to_name (category)
1070      int category;
1071 {
1072   const char *retval;
1073
1074   switch (category)
1075   {
1076 #ifdef LC_COLLATE
1077   case LC_COLLATE:
1078     retval = "LC_COLLATE";
1079     break;
1080 #endif
1081 #ifdef LC_CTYPE
1082   case LC_CTYPE:
1083     retval = "LC_CTYPE";
1084     break;
1085 #endif
1086 #ifdef LC_MONETARY
1087   case LC_MONETARY:
1088     retval = "LC_MONETARY";
1089     break;
1090 #endif
1091 #ifdef LC_NUMERIC
1092   case LC_NUMERIC:
1093     retval = "LC_NUMERIC";
1094     break;
1095 #endif
1096 #ifdef LC_TIME
1097   case LC_TIME:
1098     retval = "LC_TIME";
1099     break;
1100 #endif
1101 #ifdef LC_MESSAGES
1102   case LC_MESSAGES:
1103     retval = "LC_MESSAGES";
1104     break;
1105 #endif
1106 #ifdef LC_RESPONSE
1107   case LC_RESPONSE:
1108     retval = "LC_RESPONSE";
1109     break;
1110 #endif
1111 #ifdef LC_ALL
1112   case LC_ALL:
1113     /* This might not make sense but is perhaps better than any other
1114        value.  */
1115     retval = "LC_ALL";
1116     break;
1117 #endif
1118   default:
1119     /* If you have a better idea for a default value let me know.  */
1120     retval = "LC_XXX";
1121   }
1122
1123   return retval;
1124 }
1125
1126 /* Guess value of current locale from value of the environment variables.  */
1127 static const char *
1128 internal_function
1129 guess_category_value (category, categoryname)
1130      int category;
1131      const char *categoryname;
1132 {
1133   const char *language;
1134   const char *retval;
1135
1136   /* The highest priority value is the `LANGUAGE' environment
1137      variable.  But we don't use the value if the currently selected
1138      locale is the C locale.  This is a GNU extension.  */
1139   language = getenv ("LANGUAGE");
1140   if (language != NULL && language[0] == '\0')
1141     language = NULL;
1142
1143   /* We have to proceed with the POSIX methods of looking to `LC_ALL',
1144      `LC_xxx', and `LANG'.  On some systems this can be done by the
1145      `setlocale' function itself.  */
1146 #if defined _LIBC || (defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL)
1147   retval = setlocale (category, NULL);
1148 #else
1149   /* Setting of LC_ALL overwrites all other.  */
1150   retval = getenv ("LC_ALL");
1151   if (retval == NULL || retval[0] == '\0')
1152     {
1153       /* Next comes the name of the desired category.  */
1154       retval = getenv (categoryname);
1155       if (retval == NULL || retval[0] == '\0')
1156         {
1157           /* Last possibility is the LANG environment variable.  */
1158           retval = getenv ("LANG");
1159           if (retval == NULL || retval[0] == '\0')
1160             /* We use C as the default domain.  POSIX says this is
1161                implementation defined.  */
1162             return "C";
1163         }
1164     }
1165 #endif
1166
1167   return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
1168 }
1169
1170 /* @@ begin of epilog @@ */
1171
1172 /* We don't want libintl.a to depend on any other library.  So we
1173    avoid the non-standard function stpcpy.  In GNU C Library this
1174    function is available, though.  Also allow the symbol HAVE_STPCPY
1175    to be defined.  */
1176 #if !_LIBC && !HAVE_STPCPY
1177 static char *
1178 stpcpy (dest, src)
1179      char *dest;
1180      const char *src;
1181 {
1182   while ((*dest++ = *src++) != '\0')
1183     /* Do nothing. */ ;
1184   return dest - 1;
1185 }
1186 #endif
1187
1188 #if !_LIBC && !HAVE_MEMPCPY
1189 static void *
1190 mempcpy (dest, src, n)
1191      void *dest;
1192      const void *src;
1193      size_t n;
1194 {
1195   return (void *) ((char *) memcpy (dest, src, n) + n);
1196 }
1197 #endif
1198
1199
1200 #ifdef _LIBC
1201 /* If we want to free all resources we have to do some work at
1202    program's end.  */
1203 static void __attribute__ ((unused))
1204 free_mem (void)
1205 {
1206   void *old;
1207
1208   while (_nl_domain_bindings != NULL)
1209     {
1210       struct binding *oldp = _nl_domain_bindings;
1211       _nl_domain_bindings = _nl_domain_bindings->next;
1212       if (oldp->dirname != _nl_default_dirname)
1213         /* Yes, this is a pointer comparison.  */
1214         free (oldp->dirname);
1215       free (oldp->codeset);
1216       free (oldp);
1217     }
1218
1219   if (_nl_current_default_domain != _nl_default_default_domain)
1220     /* Yes, again a pointer comparison.  */
1221     free ((char *) _nl_current_default_domain);
1222
1223   /* Remove the search tree with the known translations.  */
1224   __tdestroy (root, free);
1225   root = NULL;
1226
1227   while (transmem_list != NULL)
1228     {
1229       old = transmem_list;
1230       transmem_list = transmem_list->next;
1231       free (old);
1232     }
1233 }
1234
1235 text_set_element (__libc_subfreeres, free_mem);
1236 #endif