(transmem_block_t): Change to unsigned char, to avoid compiler warning.
[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           __set_errno (saved_errno);
499           return (plural == 0
500                   ? (char *) msgid1
501                   /* Use the Germanic plural rule.  */
502                   : n == 1 ? (char *) msgid1 : (char *) msgid2);
503         }
504
505       stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
506     }
507
508   /* Now determine the symbolic name of CATEGORY and its value.  */
509   categoryname = category_to_name (category);
510   categoryvalue = guess_category_value (category, categoryname);
511
512   domainname_len = strlen (domainname);
513   xdomainname = (char *) alloca (strlen (categoryname)
514                                  + domainname_len + 5);
515   ADD_BLOCK (block_list, xdomainname);
516
517   stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
518                   domainname, domainname_len),
519           ".mo");
520
521   /* Creating working area.  */
522   single_locale = (char *) alloca (strlen (categoryvalue) + 1);
523   ADD_BLOCK (block_list, single_locale);
524
525
526   /* Search for the given string.  This is a loop because we perhaps
527      got an ordered list of languages to consider for the translation.  */
528   while (1)
529     {
530       /* Make CATEGORYVALUE point to the next element of the list.  */
531       while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
532         ++categoryvalue;
533       if (categoryvalue[0] == '\0')
534         {
535           /* The whole contents of CATEGORYVALUE has been searched but
536              no valid entry has been found.  We solve this situation
537              by implicitly appending a "C" entry, i.e. no translation
538              will take place.  */
539           single_locale[0] = 'C';
540           single_locale[1] = '\0';
541         }
542       else
543         {
544           char *cp = single_locale;
545           while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
546             *cp++ = *categoryvalue++;
547           *cp = '\0';
548
549           /* When this is a SUID binary we must not allow accessing files
550              outside the dedicated directories.  */
551           if (ENABLE_SECURE && strchr (single_locale, '/') != NULL)
552             /* Ingore this entry.  */
553             continue;
554         }
555
556       /* If the current locale value is C (or POSIX) we don't load a
557          domain.  Return the MSGID.  */
558       if (strcmp (single_locale, "C") == 0
559           || strcmp (single_locale, "POSIX") == 0)
560         {
561           FREE_BLOCKS (block_list);
562           __libc_rwlock_unlock (_nl_state_lock);
563           __set_errno (saved_errno);
564           return (plural == 0
565                   ? (char *) msgid1
566                   /* Use the Germanic plural rule.  */
567                   : n == 1 ? (char *) msgid1 : (char *) msgid2);
568         }
569
570
571       /* Find structure describing the message catalog matching the
572          DOMAINNAME and CATEGORY.  */
573       domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
574
575       if (domain != NULL)
576         {
577           retval = _nl_find_msg (domain, msgid1, &retlen);
578
579           if (retval == NULL)
580             {
581               int cnt;
582
583               for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
584                 {
585                   retval = _nl_find_msg (domain->successor[cnt], msgid1,
586                                          &retlen);
587
588                   if (retval != NULL)
589                     {
590                       domain = domain->successor[cnt];
591                       break;
592                     }
593                 }
594             }
595
596           if (retval != NULL)
597             {
598               /* Found the translation of MSGID1 in domain DOMAIN:
599                  starting at RETVAL, RETLEN bytes.  */
600               FREE_BLOCKS (block_list);
601               __set_errno (saved_errno);
602 #if defined HAVE_TSEARCH || defined _LIBC
603               if (foundp == NULL)
604                 {
605                   /* Create a new entry and add it to the search tree.  */
606                   struct known_translation_t *newp;
607
608                   newp = (struct known_translation_t *)
609                     malloc (offsetof (struct known_translation_t, msgid)
610                             + msgid_len + domainname_len + 1);
611                   if (newp != NULL)
612                     {
613                       newp->domainname =
614                         mempcpy (newp->msgid, msgid1, msgid_len);
615                       memcpy (newp->domainname, domainname, domainname_len + 1);
616                       newp->category = category;
617                       newp->counter = _nl_msg_cat_cntr;
618                       newp->domain = domain;
619                       newp->translation = retval;
620                       newp->translation_length = retlen;
621
622                       /* Insert the entry in the search tree.  */
623                       foundp = (struct known_translation_t **)
624                         tsearch (newp, &root, transcmp);
625                       if (foundp == NULL
626                           || __builtin_expect (*foundp != newp, 0))
627                         /* The insert failed.  */
628                         free (newp);
629                     }
630                 }
631               else
632                 {
633                   /* We can update the existing entry.  */
634                   (*foundp)->counter = _nl_msg_cat_cntr;
635                   (*foundp)->domain = domain;
636                   (*foundp)->translation = retval;
637                   (*foundp)->translation_length = retlen;
638                 }
639 #endif
640               /* Now deal with plural.  */
641               if (plural)
642                 retval = plural_lookup (domain, n, retval, retlen);
643
644               __libc_rwlock_unlock (_nl_state_lock);
645               return retval;
646             }
647         }
648     }
649   /* NOTREACHED */
650 }
651
652
653 char *
654 internal_function
655 _nl_find_msg (domain_file, msgid, lengthp)
656      struct loaded_l10nfile *domain_file;
657      const char *msgid;
658      size_t *lengthp;
659 {
660   struct loaded_domain *domain;
661   size_t act;
662   char *result;
663   size_t resultlen;
664
665   if (domain_file->decided == 0)
666     _nl_load_domain (domain_file);
667
668   if (domain_file->data == NULL)
669     return NULL;
670
671   domain = (struct loaded_domain *) domain_file->data;
672
673   /* Locate the MSGID and its translation.  */
674   if (domain->hash_size > 2 && domain->hash_tab != NULL)
675     {
676       /* Use the hashing table.  */
677       nls_uint32 len = strlen (msgid);
678       nls_uint32 hash_val = hash_string (msgid);
679       nls_uint32 idx = hash_val % domain->hash_size;
680       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
681
682       while (1)
683         {
684           nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
685
686           if (nstr == 0)
687             /* Hash table entry is empty.  */
688             return NULL;
689
690           /* Compare msgid with the original string at index nstr-1.
691              We compare the lengths with >=, not ==, because plural entries
692              are represented by strings with an embedded NUL.  */
693           if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) >= len
694               && (strcmp (msgid,
695                           domain->data + W (domain->must_swap,
696                                             domain->orig_tab[nstr - 1].offset))
697                   == 0))
698             {
699               act = nstr - 1;
700               goto found;
701             }
702
703           if (idx >= domain->hash_size - incr)
704             idx -= domain->hash_size - incr;
705           else
706             idx += incr;
707         }
708       /* NOTREACHED */
709     }
710   else
711     {
712       /* Try the default method:  binary search in the sorted array of
713          messages.  */
714       size_t top, bottom;
715
716       bottom = 0;
717       top = domain->nstrings;
718       while (bottom < top)
719         {
720           int cmp_val;
721
722           act = (bottom + top) / 2;
723           cmp_val = strcmp (msgid, (domain->data
724                                     + W (domain->must_swap,
725                                          domain->orig_tab[act].offset)));
726           if (cmp_val < 0)
727             top = act;
728           else if (cmp_val > 0)
729             bottom = act + 1;
730           else
731             goto found;
732         }
733       /* No translation was found.  */
734       return NULL;
735     }
736
737  found:
738   /* The translation was found at index ACT.  If we have to convert the
739      string to use a different character set, this is the time.  */
740   result = ((char *) domain->data
741             + W (domain->must_swap, domain->trans_tab[act].offset));
742   resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
743
744 #if defined _LIBC || HAVE_ICONV
745   if (
746 # ifdef _LIBC
747       domain->conv != (__gconv_t) -1
748 # else
749 #  if HAVE_ICONV
750       domain->conv != (iconv_t) -1
751 #  endif
752 # endif
753       )
754     {
755       /* We are supposed to do a conversion.  First allocate an
756          appropriate table with the same structure as the table
757          of translations in the file, where we can put the pointers
758          to the converted strings in.
759          There is a slight complication with plural entries.  They
760          are represented by consecutive NUL terminated strings.  We
761          handle this case by converting RESULTLEN bytes, including
762          NULs.  */
763
764       if (domain->conv_tab == NULL
765           && ((domain->conv_tab = (char **) calloc (domain->nstrings,
766                                                     sizeof (char *)))
767               == NULL))
768         /* Mark that we didn't succeed allocating a table.  */
769         domain->conv_tab = (char **) -1;
770
771       if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
772         /* Nothing we can do, no more memory.  */
773         goto converted;
774
775       if (domain->conv_tab[act] == NULL)
776         {
777           /* We haven't used this string so far, so it is not
778              translated yet.  Do this now.  */
779           /* We use a bit more efficient memory handling.
780              We allocate always larger blocks which get used over
781              time.  This is faster than many small allocations.   */
782           __libc_lock_define_initialized (static, lock)
783 # define INITIAL_BLOCK_SIZE     4080
784           static unsigned char *freemem;
785           static size_t freemem_size;
786
787           const unsigned char *inbuf;
788           unsigned char *outbuf;
789           int malloc_count;
790 # ifndef _LIBC
791           transmem_block_t *transmem_list = NULL;
792 # endif
793
794           __libc_lock_lock (lock);
795
796           inbuf = (const unsigned char *) result;
797           outbuf = freemem + sizeof (size_t);
798
799           malloc_count = 0;
800           while (1)
801             {
802               transmem_block_t *newmem;
803 # ifdef _LIBC
804               size_t non_reversible;
805               int res;
806
807               if (freemem_size < sizeof (size_t))
808                 goto resize_freemem;
809
810               res = __gconv (domain->conv,
811                              &inbuf, inbuf + resultlen,
812                              &outbuf,
813                              outbuf + freemem_size - sizeof (size_t),
814                              &non_reversible);
815
816               if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
817                 break;
818
819               if (res != __GCONV_FULL_OUTPUT)
820                 {
821                   __libc_lock_unlock (lock);
822                   goto converted;
823                 }
824
825               inbuf = result;
826 # else
827 #  if HAVE_ICONV
828               const char *inptr = (const char *) inbuf;
829               size_t inleft = resultlen;
830               char *outptr = (char *) outbuf;
831               size_t outleft;
832
833               if (freemem_size < sizeof (size_t))
834                 goto resize_freemem;
835
836               outleft = freemem_size - sizeof (size_t);
837               if (iconv (domain->conv,
838                          (ICONV_CONST char **) &inptr, &inleft,
839                          &outptr, &outleft)
840                   != (size_t) (-1))
841                 {
842                   outbuf = (unsigned char *) outptr;
843                   break;
844                 }
845               if (errno != E2BIG)
846                 {
847                   __libc_lock_unlock (lock);
848                   goto converted;
849                 }
850 #  endif
851 # endif
852
853             resize_freemem:
854               /* We must allocate a new buffer or resize the old one.  */
855               if (malloc_count > 0)
856                 {
857                   ++malloc_count;
858                   freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
859                   newmem = (transmem_block_t *) realloc (transmem_list,
860                                                          freemem_size);
861 # ifdef _LIBC
862                   if (newmem != NULL)
863                     transmem_list = transmem_list->next;
864                   else
865                     {
866                       struct transmem_list *old = transmem_list;
867
868                       transmem_list = transmem_list->next;
869                       free (old);
870                     }
871 # endif
872                 }
873               else
874                 {
875                   malloc_count = 1;
876                   freemem_size = INITIAL_BLOCK_SIZE;
877                   newmem = (transmem_block_t *) malloc (freemem_size);
878                 }
879               if (__builtin_expect (newmem == NULL, 0))
880                 {
881                   freemem = NULL;
882                   freemem_size = 0;
883                   __libc_lock_unlock (lock);
884                   goto converted;
885                 }
886
887 # ifdef _LIBC
888               /* Add the block to the list of blocks we have to free
889                  at some point.  */
890               newmem->next = transmem_list;
891               transmem_list = newmem;
892
893               freemem = newmem->data;
894               freemem_size -= offsetof (struct transmem_list, data);
895 # else
896               transmem_list = newmem;
897               freemem = newmem;
898 # endif
899
900               outbuf = freemem + sizeof (size_t);
901             }
902
903           /* We have now in our buffer a converted string.  Put this
904              into the table of conversions.  */
905           *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
906           domain->conv_tab[act] = (char *) freemem;
907           /* Shrink freemem, but keep it aligned.  */
908           freemem_size -= outbuf - freemem;
909           freemem = outbuf;
910           freemem += freemem_size & (alignof (size_t) - 1);
911           freemem_size = freemem_size & ~ (alignof (size_t) - 1);
912
913           __libc_lock_unlock (lock);
914         }
915
916       /* Now domain->conv_tab[act] contains the translation of all
917          the plural variants.  */
918       result = domain->conv_tab[act] + sizeof (size_t);
919       resultlen = *(size_t *) domain->conv_tab[act];
920     }
921
922  converted:
923   /* The result string is converted.  */
924
925 #endif /* _LIBC || HAVE_ICONV */
926
927   *lengthp = resultlen;
928   return result;
929 }
930
931
932 /* Look up a plural variant.  */
933 static char *
934 internal_function
935 plural_lookup (domain, n, translation, translation_len)
936      struct loaded_l10nfile *domain;
937      unsigned long int n;
938      const char *translation;
939      size_t translation_len;
940 {
941   struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
942   unsigned long int index;
943   const char *p;
944
945   index = plural_eval (domaindata->plural, n);
946   if (index >= domaindata->nplurals)
947     /* This should never happen.  It means the plural expression and the
948        given maximum value do not match.  */
949     index = 0;
950
951   /* Skip INDEX strings at TRANSLATION.  */
952   p = translation;
953   while (index-- > 0)
954     {
955 #ifdef _LIBC
956       p = __rawmemchr (p, '\0');
957 #else
958       p = strchr (p, '\0');
959 #endif
960       /* And skip over the NUL byte.  */
961       p++;
962
963       if (p >= translation + translation_len)
964         /* This should never happen.  It means the plural expression
965            evaluated to a value larger than the number of variants
966            available for MSGID1.  */
967         return (char *) translation;
968     }
969   return (char *) p;
970 }
971
972
973 /* Function to evaluate the plural expression and return an index value.  */
974 static unsigned long int
975 internal_function
976 plural_eval (pexp, n)
977      struct expression *pexp;
978      unsigned long int n;
979 {
980   switch (pexp->nargs)
981     {
982     case 0:
983       switch (pexp->operation)
984         {
985         case var:
986           return n;
987         case num:
988           return pexp->val.num;
989         default:
990           break;
991         }
992       /* NOTREACHED */
993       break;
994     case 1:
995       {
996         /* pexp->operation must be lnot.  */
997         unsigned long int arg = plural_eval (pexp->val.args[0], n);
998         return ! arg;
999       }
1000     case 2:
1001       {
1002         unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
1003         if (pexp->operation == lor)
1004           return leftarg || plural_eval (pexp->val.args[1], n);
1005         else if (pexp->operation == land)
1006           return leftarg && plural_eval (pexp->val.args[1], n);
1007         else
1008           {
1009             unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
1010
1011             switch (pexp->operation)
1012               {
1013               case mult:
1014                 return leftarg * rightarg;
1015               case divide:
1016                 return leftarg / rightarg;
1017               case module:
1018                 return leftarg % rightarg;
1019               case plus:
1020                 return leftarg + rightarg;
1021               case minus:
1022                 return leftarg - rightarg;
1023               case less_than:
1024                 return leftarg < rightarg;
1025               case greater_than:
1026                 return leftarg > rightarg;
1027               case less_or_equal:
1028                 return leftarg <= rightarg;
1029               case greater_or_equal:
1030                 return leftarg >= rightarg;
1031               case equal:
1032                 return leftarg == rightarg;
1033               case not_equal:
1034                 return leftarg != rightarg;
1035               default:
1036                 break;
1037               }
1038           }
1039         /* NOTREACHED */
1040         break;
1041       }
1042     case 3:
1043       {
1044         /* pexp->operation must be qmop.  */
1045         unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
1046         return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
1047       }
1048     }
1049   /* NOTREACHED */
1050   return 0;
1051 }
1052
1053
1054 /* Return string representation of locale CATEGORY.  */
1055 static const char *
1056 internal_function
1057 category_to_name (category)
1058      int category;
1059 {
1060   const char *retval;
1061
1062   switch (category)
1063   {
1064 #ifdef LC_COLLATE
1065   case LC_COLLATE:
1066     retval = "LC_COLLATE";
1067     break;
1068 #endif
1069 #ifdef LC_CTYPE
1070   case LC_CTYPE:
1071     retval = "LC_CTYPE";
1072     break;
1073 #endif
1074 #ifdef LC_MONETARY
1075   case LC_MONETARY:
1076     retval = "LC_MONETARY";
1077     break;
1078 #endif
1079 #ifdef LC_NUMERIC
1080   case LC_NUMERIC:
1081     retval = "LC_NUMERIC";
1082     break;
1083 #endif
1084 #ifdef LC_TIME
1085   case LC_TIME:
1086     retval = "LC_TIME";
1087     break;
1088 #endif
1089 #ifdef LC_MESSAGES
1090   case LC_MESSAGES:
1091     retval = "LC_MESSAGES";
1092     break;
1093 #endif
1094 #ifdef LC_RESPONSE
1095   case LC_RESPONSE:
1096     retval = "LC_RESPONSE";
1097     break;
1098 #endif
1099 #ifdef LC_ALL
1100   case LC_ALL:
1101     /* This might not make sense but is perhaps better than any other
1102        value.  */
1103     retval = "LC_ALL";
1104     break;
1105 #endif
1106   default:
1107     /* If you have a better idea for a default value let me know.  */
1108     retval = "LC_XXX";
1109   }
1110
1111   return retval;
1112 }
1113
1114 /* Guess value of current locale from value of the environment variables.  */
1115 static const char *
1116 internal_function
1117 guess_category_value (category, categoryname)
1118      int category;
1119      const char *categoryname;
1120 {
1121   const char *language;
1122   const char *retval;
1123
1124   /* The highest priority value is the `LANGUAGE' environment
1125      variable.  But we don't use the value if the currently selected
1126      locale is the C locale.  This is a GNU extension.  */
1127   language = getenv ("LANGUAGE");
1128   if (language != NULL && language[0] == '\0')
1129     language = NULL;
1130
1131   /* We have to proceed with the POSIX methods of looking to `LC_ALL',
1132      `LC_xxx', and `LANG'.  On some systems this can be done by the
1133      `setlocale' function itself.  */
1134 #if defined _LIBC || (defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL)
1135   retval = setlocale (category, NULL);
1136 #else
1137   /* Setting of LC_ALL overwrites all other.  */
1138   retval = getenv ("LC_ALL");
1139   if (retval == NULL || retval[0] == '\0')
1140     {
1141       /* Next comes the name of the desired category.  */
1142       retval = getenv (categoryname);
1143       if (retval == NULL || retval[0] == '\0')
1144         {
1145           /* Last possibility is the LANG environment variable.  */
1146           retval = getenv ("LANG");
1147           if (retval == NULL || retval[0] == '\0')
1148             /* We use C as the default domain.  POSIX says this is
1149                implementation defined.  */
1150             return "C";
1151         }
1152     }
1153 #endif
1154
1155   return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
1156 }
1157
1158 /* @@ begin of epilog @@ */
1159
1160 /* We don't want libintl.a to depend on any other library.  So we
1161    avoid the non-standard function stpcpy.  In GNU C Library this
1162    function is available, though.  Also allow the symbol HAVE_STPCPY
1163    to be defined.  */
1164 #if !_LIBC && !HAVE_STPCPY
1165 static char *
1166 stpcpy (dest, src)
1167      char *dest;
1168      const char *src;
1169 {
1170   while ((*dest++ = *src++) != '\0')
1171     /* Do nothing. */ ;
1172   return dest - 1;
1173 }
1174 #endif
1175
1176 #if !_LIBC && !HAVE_MEMPCPY
1177 static void *
1178 mempcpy (dest, src, n)
1179      void *dest;
1180      const void *src;
1181      size_t n;
1182 {
1183   return (void *) ((char *) memcpy (dest, src, n) + n);
1184 }
1185 #endif
1186
1187
1188 #ifdef _LIBC
1189 /* If we want to free all resources we have to do some work at
1190    program's end.  */
1191 static void __attribute__ ((unused))
1192 free_mem (void)
1193 {
1194   void *old;
1195
1196   while (_nl_domain_bindings != NULL)
1197     {
1198       struct binding *oldp = _nl_domain_bindings;
1199       _nl_domain_bindings = _nl_domain_bindings->next;
1200       if (oldp->dirname != _nl_default_dirname)
1201         /* Yes, this is a pointer comparison.  */
1202         free (oldp->dirname);
1203       free (oldp->codeset);
1204       free (oldp);
1205     }
1206
1207   if (_nl_current_default_domain != _nl_default_default_domain)
1208     /* Yes, again a pointer comparison.  */
1209     free ((char *) _nl_current_default_domain);
1210
1211   /* Remove the search tree with the known translations.  */
1212   __tdestroy (root, free);
1213   root = NULL;
1214
1215   while (transmem_list != NULL)
1216     {
1217       old = transmem_list;
1218       transmem_list = transmem_list->next;
1219       free (old);
1220     }
1221 }
1222
1223 text_set_element (__libc_subfreeres, free_mem);
1224 #endif