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