Add test case for FNM_PERIOD handling with FNM_EXTMATCH.
[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 "gettext.h"
93 #include "gettextP.h"
94 #ifdef _LIBC
95 # include <libintl.h>
96 #else
97 # include "libgettext.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 _nl_default_default_domain__
127 # define _nl_current_default_domain _nl_current_default_domain__
128 # define _nl_default_dirname _nl_default_dirname__
129 # define _nl_domain_bindings _nl_domain_bindings__
130 #endif
131
132 /* @@ end of prolog @@ */
133
134 #ifdef _LIBC
135 /* Rename the non ANSI C functions.  This is required by the standard
136    because some ANSI C functions will require linking with this object
137    file and the name space must not be polluted.  */
138 # define getcwd __getcwd
139 # ifndef stpcpy
140 #  define stpcpy __stpcpy
141 # endif
142 # define tfind __tfind
143 #else
144 # if !defined HAVE_GETCWD
145 char *getwd ();
146 #  define getcwd(buf, max) getwd (buf)
147 # else
148 char *getcwd ();
149 # endif
150 # ifndef HAVE_STPCPY
151 static char *stpcpy PARAMS ((char *dest, const char *src));
152 # endif
153 # ifndef HAVE_MEMPCPY
154 static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
155 # endif
156 #endif
157
158 /* Amount to increase buffer size by in each try.  */
159 #define PATH_INCR 32
160
161 /* The following is from pathmax.h.  */
162 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
163    PATH_MAX but might cause redefinition warnings when sys/param.h is
164    later included (as on MORE/BSD 4.3).  */
165 #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
166 # include <limits.h>
167 #endif
168
169 #ifndef _POSIX_PATH_MAX
170 # define _POSIX_PATH_MAX 255
171 #endif
172
173 #if !defined PATH_MAX && defined _PC_PATH_MAX
174 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
175 #endif
176
177 /* Don't include sys/param.h if it already has been.  */
178 #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
179 # include <sys/param.h>
180 #endif
181
182 #if !defined PATH_MAX && defined MAXPATHLEN
183 # define PATH_MAX MAXPATHLEN
184 #endif
185
186 #ifndef PATH_MAX
187 # define PATH_MAX _POSIX_PATH_MAX
188 #endif
189
190 /* XPG3 defines the result of `setlocale (category, NULL)' as:
191    ``Directs `setlocale()' to query `category' and return the current
192      setting of `local'.''
193    However it does not specify the exact format.  And even worse: POSIX
194    defines this not at all.  So we can use this feature only on selected
195    system (e.g. those using GNU C Library).  */
196 #ifdef _LIBC
197 # define HAVE_LOCALE_NULL
198 #endif
199
200 /* We want to allocate a string at the end of the struct.  gcc makes
201    this easy.  */
202 #ifdef __GNUC__
203 # define ZERO 0
204 #else
205 # define ZERO 1
206 #endif
207
208 /* This is the type used for the search tree where known translations
209    are stored.  */
210 struct known_translation_t
211 {
212   /* Domain in which to search.  */
213   char *domainname;
214
215   /* The category.  */
216   int category;
217
218   /* State of the catalog counter at the point the string was found.  */
219   int counter;
220
221   /* Catalog where the string was found.  */
222   struct loaded_l10nfile *domain;
223
224   /* And finally the translation.  */
225   const char *translation;
226   size_t translation_length;
227
228   /* Pointer to the string in question.  */
229   char msgid[ZERO];
230 };
231
232 /* Root of the search tree with known translations.  We can use this
233    only if the system provides the `tsearch' function family.  */
234 #if defined HAVE_TSEARCH || defined _LIBC
235 # include <search.h>
236
237 static void *root;
238
239 # ifdef _LIBC
240 #  define tsearch __tsearch
241 # endif
242
243 /* Function to compare two entries in the table of known translations.  */
244 static int
245 transcmp (const void *p1, const void *p2)
246 {
247   const struct known_translation_t *s1;
248   const struct known_translation_t *s2;
249   int result;
250
251   s1 = (const struct known_translation_t *) p1;
252   s2 = (const struct known_translation_t *) p2;
253
254   result = strcmp (s1->msgid, s2->msgid);
255   if (result == 0)
256     {
257       result = strcmp (s1->domainname, s2->domainname);
258       if (result == 0)
259         /* We compare the category last (though this is the cheapest
260            operation) since it is hopefully always the same (namely
261            LC_MESSAGES).  */
262         result = s1->category - s2->category;
263     }
264
265   return result;
266 }
267 #endif
268
269 /* Name of the default domain used for gettext(3) prior any call to
270    textdomain(3).  The default value for this is "messages".  */
271 const char _nl_default_default_domain[] = "messages";
272
273 /* Value used as the default domain for gettext(3).  */
274 const char *_nl_current_default_domain = _nl_default_default_domain;
275
276 /* Contains the default location of the message catalogs.  */
277 const char _nl_default_dirname[] = GNULOCALEDIR;
278
279 /* List with bindings of specific domains created by bindtextdomain()
280    calls.  */
281 struct binding *_nl_domain_bindings;
282
283 /* Prototypes for local functions.  */
284 static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
285                                     unsigned long int n,
286                                     const char *translation,
287                                     size_t translation_len))
288      internal_function;
289 static unsigned long int plural_eval PARAMS ((struct expression *pexp,
290                                               unsigned long int n))
291      internal_function;
292 static const char *category_to_name PARAMS ((int category)) internal_function;
293 static const char *guess_category_value PARAMS ((int category,
294                                                  const char *categoryname))
295      internal_function;
296
297
298 /* For those loosing systems which don't have `alloca' we have to add
299    some additional code emulating it.  */
300 #ifdef HAVE_ALLOCA
301 /* Nothing has to be done.  */
302 # define ADD_BLOCK(list, address) /* nothing */
303 # define FREE_BLOCKS(list) /* nothing */
304 #else
305 struct block_list
306 {
307   void *address;
308   struct block_list *next;
309 };
310 # define ADD_BLOCK(list, addr)                                                \
311   do {                                                                        \
312     struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
313     /* If we cannot get a free block we cannot add the new element to         \
314        the list.  */                                                          \
315     if (newp != NULL) {                                                       \
316       newp->address = (addr);                                                 \
317       newp->next = (list);                                                    \
318       (list) = newp;                                                          \
319     }                                                                         \
320   } while (0)
321 # define FREE_BLOCKS(list)                                                    \
322   do {                                                                        \
323     while (list != NULL) {                                                    \
324       struct block_list *old = list;                                          \
325       list = list->next;                                                      \
326       free (old);                                                             \
327     }                                                                         \
328   } while (0)
329 # undef alloca
330 # define alloca(size) (malloc (size))
331 #endif  /* have alloca */
332
333
334 #ifdef _LIBC
335 /* List of blocks allocated for translations.  */
336 typedef struct transmem_list
337 {
338   struct transmem_list *next;
339   char data[0];
340 } transmem_block_t;
341 static struct transmem_list *transmem_list;
342 #else
343 typedef char transmem_block_t;
344 #endif
345
346
347 /* Names for the libintl functions are a problem.  They must not clash
348    with existing names and they should follow ANSI C.  But this source
349    code is also used in GNU C Library where the names have a __
350    prefix.  So we have to make a difference here.  */
351 #ifdef _LIBC
352 # define DCIGETTEXT __dcigettext
353 #else
354 # define DCIGETTEXT dcigettext__
355 #endif
356
357 /* Lock variable to protect the global data in the gettext implementation.  */
358 __libc_rwlock_define_initialized (, _nl_state_lock)
359
360 /* Checking whether the binaries runs SUID must be done and glibc provides
361    easier methods therefore we make a difference here.  */
362 #ifdef _LIBC
363 # define ENABLE_SECURE __libc_enable_secure
364 # define DETERMINE_SECURE
365 #else
366 static int enable_secure;
367 # define ENABLE_SECURE (enable_secure == 1)
368 # define DETERMINE_SECURE \
369   if (enable_secure == 0)                                                     \
370     {                                                                         \
371       if (getuid () != geteuid () || getgid () != getegid ())                 \
372         enable_secure = 1;                                                    \
373       else                                                                    \
374         enable_secure = -1;                                                   \
375     }
376 #endif
377
378 /* Look up MSGID in the DOMAINNAME message catalog for the current
379    CATEGORY locale and, if PLURAL is nonzero, search over string
380    depending on the plural form determined by N.  */
381 char *
382 DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
383      const char *domainname;
384      const char *msgid1;
385      const char *msgid2;
386      int plural;
387      unsigned long int n;
388      int category;
389 {
390 #ifndef HAVE_ALLOCA
391   struct block_list *block_list = NULL;
392 #endif
393   struct loaded_l10nfile *domain;
394   struct binding *binding;
395   const char *categoryname;
396   const char *categoryvalue;
397   char *dirname, *xdomainname;
398   char *single_locale;
399   char *retval;
400   size_t retlen;
401   int saved_errno;
402 #if defined HAVE_TSEARCH || defined _LIBC
403   struct known_translation_t *search;
404   struct known_translation_t **foundp = NULL;
405   size_t msgid_len;
406 #endif
407   size_t domainname_len;
408
409   /* If no real MSGID is given return NULL.  */
410   if (msgid1 == NULL)
411     return NULL;
412
413   __libc_rwlock_rdlock (_nl_state_lock);
414
415   /* If DOMAINNAME is NULL, we are interested in the default domain.  If
416      CATEGORY is not LC_MESSAGES this might not make much sense but the
417      definition left this undefined.  */
418   if (domainname == NULL)
419     domainname = _nl_current_default_domain;
420
421 #if defined HAVE_TSEARCH || defined _LIBC
422   msgid_len = strlen (msgid1) + 1;
423
424   /* Try to find the translation among those which we found at
425      some time.  */
426   search =
427     (struct known_translation_t *) alloca (sizeof (*search) + msgid_len);
428   memcpy (search->msgid, msgid1, msgid_len);
429   search->domainname = (char *) domainname;
430   search->category = category;
431
432   foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
433   if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
434     {
435       /* Now deal with plural.  */
436       if (plural)
437         retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
438                                 (*foundp)->translation_length);
439       else
440         retval = (char *) (*foundp)->translation;
441
442       __libc_rwlock_unlock (_nl_state_lock);
443       return retval;
444     }
445 #endif
446
447   /* Preserve the `errno' value.  */
448   saved_errno = errno;
449
450   /* See whether this is a SUID binary or not.  */
451   DETERMINE_SECURE;
452
453   /* First find matching binding.  */
454   for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
455     {
456       int compare = strcmp (domainname, binding->domainname);
457       if (compare == 0)
458         /* We found it!  */
459         break;
460       if (compare < 0)
461         {
462           /* It is not in the list.  */
463           binding = NULL;
464           break;
465         }
466     }
467
468   if (binding == NULL)
469     dirname = (char *) _nl_default_dirname;
470   else if (binding->dirname[0] == '/')
471     dirname = binding->dirname;
472   else
473     {
474       /* We have a relative path.  Make it absolute now.  */
475       size_t dirname_len = strlen (binding->dirname) + 1;
476       size_t path_max;
477       char *ret;
478
479       path_max = (unsigned int) PATH_MAX;
480       path_max += 2;            /* The getcwd docs say to do this.  */
481
482       dirname = (char *) alloca (path_max + dirname_len);
483       ADD_BLOCK (block_list, dirname);
484
485       __set_errno (0);
486       while ((ret = getcwd (dirname, path_max)) == NULL && errno == ERANGE)
487         {
488           path_max += PATH_INCR;
489           dirname = (char *) alloca (path_max + dirname_len);
490           ADD_BLOCK (block_list, dirname);
491           __set_errno (0);
492         }
493
494       if (ret == NULL)
495         {
496           /* We cannot get the current working directory.  Don't signal an
497              error but simply return the default string.  */
498           FREE_BLOCKS (block_list);
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, 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], msgid1,
587                                          &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 (sizeof (*newp) + msgid_len
611                             + domainname_len + 1 - ZERO);
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, msgid, lengthp)
657      struct loaded_l10nfile *domain_file;
658      const char *msgid;
659      size_t *lengthp;
660 {
661   struct loaded_domain *domain;
662   size_t act;
663   char *result;
664   size_t resultlen;
665
666   if (domain_file->decided == 0)
667     _nl_load_domain (domain_file);
668
669   if (domain_file->data == NULL)
670     return NULL;
671
672   domain = (struct loaded_domain *) domain_file->data;
673
674   /* Locate the MSGID and its translation.  */
675   if (domain->hash_size > 2 && domain->hash_tab != NULL)
676     {
677       /* Use the hashing table.  */
678       nls_uint32 len = strlen (msgid);
679       nls_uint32 hash_val = hash_string (msgid);
680       nls_uint32 idx = hash_val % domain->hash_size;
681       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
682       nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
683
684       if (nstr == 0)
685         /* Hash table entry is empty.  */
686         return NULL;
687
688       while (1)
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           nstr = W (domain->must_swap, domain->hash_tab[idx]);
709           if (nstr == 0)
710             /* Hash table entry is empty.  */
711             return NULL;
712         }
713       /* NOTREACHED */
714     }
715   else
716     {
717       /* Try the default method:  binary search in the sorted array of
718          messages.  */
719       size_t top, bottom;
720
721       bottom = 0;
722       top = domain->nstrings;
723       while (bottom < top)
724         {
725           int cmp_val;
726
727           act = (bottom + top) / 2;
728           cmp_val = strcmp (msgid, (domain->data
729                                     + W (domain->must_swap,
730                                          domain->orig_tab[act].offset)));
731           if (cmp_val < 0)
732             top = act;
733           else if (cmp_val > 0)
734             bottom = act + 1;
735           else
736             goto found;
737         }
738       /* No translation was found.  */
739       return NULL;
740     }
741
742  found:
743   /* The translation was found at index ACT.  If we have to convert the
744      string to use a different character set, this is the time.  */
745   result = ((char *) domain->data
746             + W (domain->must_swap, domain->trans_tab[act].offset));
747   resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
748
749 #if defined _LIBC || HAVE_ICONV
750   if (
751 # ifdef _LIBC
752       domain->conv != (__gconv_t) -1
753 # else
754 #  if HAVE_ICONV
755       domain->conv != (iconv_t) -1
756 #  endif
757 # endif
758       )
759     {
760       /* We are supposed to do a conversion.  First allocate an
761          appropriate table with the same structure as the table
762          of translations in the file, where we can put the pointers
763          to the converted strings in.
764          There is a slight complication with plural entries.  They
765          are represented by consecutive NUL terminated strings.  We
766          handle this case by converting RESULTLEN bytes, including
767          NULs.  */
768
769       if (domain->conv_tab == NULL
770           && ((domain->conv_tab = (char **) calloc (domain->nstrings,
771                                                     sizeof (char *)))
772               == NULL))
773         /* Mark that we didn't succeed allocating a table.  */
774         domain->conv_tab = (char **) -1;
775
776       if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
777         /* Nothing we can do, no more memory.  */
778         goto converted;
779
780       if (domain->conv_tab[act] == NULL)
781         {
782           /* We haven't used this string so far, so it is not
783              translated yet.  Do this now.  */
784           /* We use a bit more efficient memory handling.
785              We allocate always larger blocks which get used over
786              time.  This is faster than many small allocations.   */
787           __libc_lock_define_initialized (static, lock)
788 # define INITIAL_BLOCK_SIZE     4080
789           static unsigned char *freemem;
790           static size_t freemem_size;
791
792           const unsigned char *inbuf;
793           unsigned char *outbuf;
794           int malloc_count;
795 # ifndef _LIBC
796           transmem_block_t *transmem_list = NULL;
797 # endif
798
799           __libc_lock_lock (lock);
800
801           inbuf = result;
802           outbuf = freemem + sizeof (size_t);
803
804           malloc_count = 0;
805           while (1)
806             {
807               transmem_block_t *newmem;
808 # ifdef _LIBC
809               size_t non_reversible;
810               int res;
811
812               if (freemem_size < sizeof (size_t))
813                 goto resize_freemem;
814
815               res = __gconv (domain->conv,
816                              &inbuf, inbuf + resultlen,
817                              &outbuf,
818                              outbuf + freemem_size - sizeof (size_t),
819                              &non_reversible);
820
821               if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
822                 break;
823
824               if (res != __GCONV_FULL_OUTPUT)
825                 {
826                   __libc_lock_unlock (lock);
827                   goto converted;
828                 }
829
830               inbuf = result;
831 # else
832 #  if HAVE_ICONV
833               const char *inptr = (const char *) inbuf;
834               size_t inleft = resultlen;
835               char *outptr = (char *) outbuf;
836               size_t outleft;
837
838               if (freemem_size < sizeof (size_t))
839                 goto resize_freemem;
840
841               outleft = freemem_size - sizeof (size_t);
842               if (iconv (domain->conv, &inptr, &inleft, &outptr, &outleft)
843                   != (size_t) (-1))
844                 {
845                   outbuf = (unsigned char *) outptr;
846                   break;
847                 }
848               if (errno != E2BIG)
849                 {
850                   __libc_lock_unlock (lock);
851                   goto converted;
852                 }
853 #  endif
854 # endif
855
856             resize_freemem:
857               /* We must allocate a new buffer or resize the old one.  */
858               if (malloc_count > 0)
859                 {
860                   ++malloc_count;
861                   freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
862                   newmem = (transmem_block_t *) realloc (transmem_list,
863                                                          freemem_size);
864 # ifdef _LIBC
865                   if (newmem != NULL)
866                     transmem_list = transmem_list->next;
867                   else
868                     {
869                       struct transmem_list *old = transmem_list;
870
871                       transmem_list = transmem_list->next;
872                       free (old);
873                     }
874 # endif
875                 }
876               else
877                 {
878                   malloc_count = 1;
879                   freemem_size = INITIAL_BLOCK_SIZE;
880                   newmem = (transmem_block_t *) malloc (freemem_size);
881                 }
882               if (__builtin_expect (newmem == NULL, 0))
883                 {
884                   freemem = NULL;
885                   freemem_size = 0;
886                   __libc_lock_unlock (lock);
887                   goto converted;
888                 }
889
890 # ifdef _LIBC
891               /* Add the block to the list of blocks we have to free
892                  at some point.  */
893               newmem->next = transmem_list;
894               transmem_list = newmem;
895
896               freemem = newmem->data;
897               freemem_size -= offsetof (struct transmem_list, data);
898 # else
899               transmem_list = newmem;
900               freemem = newmem;
901 # endif
902
903               outbuf = freemem + sizeof (size_t);
904             }
905
906           /* We have now in our buffer a converted string.  Put this
907              into the table of conversions.  */
908           *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
909           domain->conv_tab[act] = freemem;
910           /* Shrink freemem, but keep it aligned.  */
911           freemem_size -= outbuf - freemem;
912           freemem = outbuf;
913           freemem += freemem_size & (alignof (size_t) - 1);
914           freemem_size = freemem_size & ~ (alignof (size_t) - 1);
915
916           __libc_lock_unlock (lock);
917         }
918
919       /* Now domain->conv_tab[act] contains the translation of all
920          the plural variants.  */
921       result = domain->conv_tab[act] + sizeof (size_t);
922       resultlen = *(size_t *) domain->conv_tab[act];
923     }
924
925  converted:
926   /* The result string is converted.  */
927
928 #endif /* _LIBC || HAVE_ICONV */
929
930   *lengthp = resultlen;
931   return result;
932 }
933
934
935 /* Look up a plural variant.  */
936 static char *
937 internal_function
938 plural_lookup (domain, n, translation, translation_len)
939      struct loaded_l10nfile *domain;
940      unsigned long int n;
941      const char *translation;
942      size_t translation_len;
943 {
944   struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
945   unsigned long int index;
946   const char *p;
947
948   index = plural_eval (domaindata->plural, n);
949   if (index >= domaindata->nplurals)
950     /* This should never happen.  It means the plural expression and the
951        given maximum value do not match.  */
952     index = 0;
953
954   /* Skip INDEX strings at TRANSLATION.  */
955   p = translation;
956   while (index-- > 0)
957     {
958 #ifdef _LIBC
959       p = __rawmemchr (p, '\0');
960 #else
961       p = strchr (p, '\0');
962 #endif
963       /* And skip over the NUL byte.  */
964       p++;
965
966       if (p >= translation + translation_len)
967         /* This should never happen.  It means the plural expression
968            evaluated to a value larger than the number of variants
969            available for MSGID1.  */
970         return (char *) translation;
971     }
972   return (char *) p;
973 }
974
975
976 /* Function to evaluate the plural expression and return an index value.  */
977 static unsigned long int
978 internal_function
979 plural_eval (pexp, n)
980      struct expression *pexp;
981      unsigned long int n;
982 {
983   switch (pexp->operation)
984     {
985     case var:
986       return n;
987     case num:
988       return pexp->val.num;
989     case mult:
990       return (plural_eval (pexp->val.args2.left, n)
991               * plural_eval (pexp->val.args2.right, n));
992     case divide:
993       return (plural_eval (pexp->val.args2.left, n)
994               / plural_eval (pexp->val.args2.right, n));
995     case module:
996       return (plural_eval (pexp->val.args2.left, n)
997               % plural_eval (pexp->val.args2.right, n));
998     case plus:
999       return (plural_eval (pexp->val.args2.left, n)
1000               + plural_eval (pexp->val.args2.right, n));
1001     case minus:
1002       return (plural_eval (pexp->val.args2.left, n)
1003               - plural_eval (pexp->val.args2.right, n));
1004     case equal:
1005       return (plural_eval (pexp->val.args2.left, n)
1006               == plural_eval (pexp->val.args2.right, n));
1007     case not_equal:
1008       return (plural_eval (pexp->val.args2.left, n)
1009               != plural_eval (pexp->val.args2.right, n));
1010     case land:
1011       return (plural_eval (pexp->val.args2.left, n)
1012               && plural_eval (pexp->val.args2.right, n));
1013     case lor:
1014       return (plural_eval (pexp->val.args2.left, n)
1015               || plural_eval (pexp->val.args2.right, n));
1016     case qmop:
1017       return (plural_eval (pexp->val.args3.bexp, n)
1018               ? plural_eval (pexp->val.args3.tbranch, n)
1019               : plural_eval (pexp->val.args3.fbranch, n));
1020     }
1021   /* NOTREACHED */
1022   return 0;
1023 }
1024
1025
1026 /* Return string representation of locale CATEGORY.  */
1027 static const char *
1028 internal_function
1029 category_to_name (category)
1030      int category;
1031 {
1032   const char *retval;
1033
1034   switch (category)
1035   {
1036 #ifdef LC_COLLATE
1037   case LC_COLLATE:
1038     retval = "LC_COLLATE";
1039     break;
1040 #endif
1041 #ifdef LC_CTYPE
1042   case LC_CTYPE:
1043     retval = "LC_CTYPE";
1044     break;
1045 #endif
1046 #ifdef LC_MONETARY
1047   case LC_MONETARY:
1048     retval = "LC_MONETARY";
1049     break;
1050 #endif
1051 #ifdef LC_NUMERIC
1052   case LC_NUMERIC:
1053     retval = "LC_NUMERIC";
1054     break;
1055 #endif
1056 #ifdef LC_TIME
1057   case LC_TIME:
1058     retval = "LC_TIME";
1059     break;
1060 #endif
1061 #ifdef LC_MESSAGES
1062   case LC_MESSAGES:
1063     retval = "LC_MESSAGES";
1064     break;
1065 #endif
1066 #ifdef LC_RESPONSE
1067   case LC_RESPONSE:
1068     retval = "LC_RESPONSE";
1069     break;
1070 #endif
1071 #ifdef LC_ALL
1072   case LC_ALL:
1073     /* This might not make sense but is perhaps better than any other
1074        value.  */
1075     retval = "LC_ALL";
1076     break;
1077 #endif
1078   default:
1079     /* If you have a better idea for a default value let me know.  */
1080     retval = "LC_XXX";
1081   }
1082
1083   return retval;
1084 }
1085
1086 /* Guess value of current locale from value of the environment variables.  */
1087 static const char *
1088 internal_function
1089 guess_category_value (category, categoryname)
1090      int category;
1091      const char *categoryname;
1092 {
1093   const char *language;
1094   const char *retval;
1095
1096   /* The highest priority value is the `LANGUAGE' environment
1097      variable.  But we don't use the value if the currently selected
1098      locale is the C locale.  This is a GNU extension.  */
1099   language = getenv ("LANGUAGE");
1100   if (language != NULL && language[0] == '\0')
1101     language = NULL;
1102
1103   /* We have to proceed with the POSIX methods of looking to `LC_ALL',
1104      `LC_xxx', and `LANG'.  On some systems this can be done by the
1105      `setlocale' function itself.  */
1106 #if defined _LIBC || (defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL)
1107   retval = setlocale (category, NULL);
1108 #else
1109   /* Setting of LC_ALL overwrites all other.  */
1110   retval = getenv ("LC_ALL");
1111   if (retval == NULL || retval[0] == '\0')
1112     {
1113       /* Next comes the name of the desired category.  */
1114       retval = getenv (categoryname);
1115       if (retval == NULL || retval[0] == '\0')
1116         {
1117           /* Last possibility is the LANG environment variable.  */
1118           retval = getenv ("LANG");
1119           if (retval == NULL || retval[0] == '\0')
1120             /* We use C as the default domain.  POSIX says this is
1121                implementation defined.  */
1122             return "C";
1123         }
1124     }
1125 #endif
1126
1127   return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
1128 }
1129
1130 /* @@ begin of epilog @@ */
1131
1132 /* We don't want libintl.a to depend on any other library.  So we
1133    avoid the non-standard function stpcpy.  In GNU C Library this
1134    function is available, though.  Also allow the symbol HAVE_STPCPY
1135    to be defined.  */
1136 #if !_LIBC && !HAVE_STPCPY
1137 static char *
1138 stpcpy (dest, src)
1139      char *dest;
1140      const char *src;
1141 {
1142   while ((*dest++ = *src++) != '\0')
1143     /* Do nothing. */ ;
1144   return dest - 1;
1145 }
1146 #endif
1147
1148 #if !_LIBC && !HAVE_MEMPCPY
1149 static void *
1150 mempcpy (dest, src, n)
1151      void *dest;
1152      const void *src;
1153      size_t n;
1154 {
1155   return (void *) ((char *) memcpy (dest, src, n) + n);
1156 }
1157 #endif
1158
1159
1160 #ifdef _LIBC
1161 /* If we want to free all resources we have to do some work at
1162    program's end.  */
1163 static void __attribute__ ((unused))
1164 free_mem (void)
1165 {
1166   void *old;
1167
1168   while (_nl_domain_bindings != NULL)
1169     {
1170       struct binding *oldp = _nl_domain_bindings;
1171       _nl_domain_bindings = _nl_domain_bindings->next;
1172       if (oldp->dirname != _nl_default_dirname)
1173         /* Yes, this is a pointer comparison.  */
1174         free (oldp->dirname);
1175       free (oldp->codeset);
1176       free (oldp);
1177     }
1178
1179   if (_nl_current_default_domain != _nl_default_default_domain)
1180     /* Yes, again a pointer comparison.  */
1181     free ((char *) _nl_current_default_domain);
1182
1183   /* Remove the search tree with the known translations.  */
1184   __tdestroy (root, free);
1185   root = NULL;
1186
1187   while (transmem_list != NULL)
1188     {
1189       old = transmem_list;
1190       transmem_list = transmem_list->next;
1191       free (old);
1192     }
1193 }
1194
1195 text_set_element (__libc_subfreeres, free_mem);
1196 #endif