Fix typo in comment.
[kopensolaris-gnu/glibc.git] / intl / dcigettext.c
1 /* Implementation of the internal dcigettext function.
2    Copyright (C) 1995-1999, 2000 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 <stdlib.h>
59 #else
60 char *getenv ();
61 # ifdef HAVE_MALLOC_H
62 #  include <malloc.h>
63 # else
64 void free ();
65 # endif
66 #endif
67
68 #if defined HAVE_STRING_H || defined _LIBC
69 # include <string.h>
70 #else
71 # include <strings.h>
72 #endif
73 #if !HAVE_STRCHR && !defined _LIBC
74 # ifndef strchr
75 #  define strchr index
76 # endif
77 #endif
78
79 #if defined HAVE_UNISTD_H || defined _LIBC
80 # include <unistd.h>
81 #endif
82
83 #if defined HAVE_LOCALE_H || defined _LIBC
84 # include <locale.h>
85 #endif
86
87 #if defined HAVE_SYS_PARAM_H || defined _LIBC
88 # include <sys/param.h>
89 #endif
90
91 #include "gettext.h"
92 #include "gettextP.h"
93 #ifdef _LIBC
94 # include <libintl.h>
95 #else
96 # include "libgettext.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 /* @@ end of prolog @@ */
122
123 #ifdef _LIBC
124 /* Rename the non ANSI C functions.  This is required by the standard
125    because some ANSI C functions will require linking with this object
126    file and the name space must not be polluted.  */
127 # define getcwd __getcwd
128 # ifndef stpcpy
129 #  define stpcpy __stpcpy
130 # endif
131 #else
132 # if !defined HAVE_GETCWD
133 char *getwd ();
134 #  define getcwd(buf, max) getwd (buf)
135 # else
136 char *getcwd ();
137 # endif
138 # ifndef HAVE_STPCPY
139 static char *stpcpy PARAMS ((char *dest, const char *src));
140 # endif
141 # ifndef HAVE_MEMPCPY
142 static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
143 # endif
144 #endif
145
146 /* Amount to increase buffer size by in each try.  */
147 #define PATH_INCR 32
148
149 /* The following is from pathmax.h.  */
150 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
151    PATH_MAX but might cause redefinition warnings when sys/param.h is
152    later included (as on MORE/BSD 4.3).  */
153 #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
154 # include <limits.h>
155 #endif
156
157 #ifndef _POSIX_PATH_MAX
158 # define _POSIX_PATH_MAX 255
159 #endif
160
161 #if !defined PATH_MAX && defined _PC_PATH_MAX
162 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
163 #endif
164
165 /* Don't include sys/param.h if it already has been.  */
166 #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
167 # include <sys/param.h>
168 #endif
169
170 #if !defined PATH_MAX && defined MAXPATHLEN
171 # define PATH_MAX MAXPATHLEN
172 #endif
173
174 #ifndef PATH_MAX
175 # define PATH_MAX _POSIX_PATH_MAX
176 #endif
177
178 /* XPG3 defines the result of `setlocale (category, NULL)' as:
179    ``Directs `setlocale()' to query `category' and return the current
180      setting of `local'.''
181    However it does not specify the exact format.  And even worse: POSIX
182    defines this not at all.  So we can use this feature only on selected
183    system (e.g. those using GNU C Library).  */
184 #ifdef _LIBC
185 # define HAVE_LOCALE_NULL
186 #endif
187
188 /* We want to allocate a string at the end of the struct.  gcc makes
189    this easy.  */
190 #ifdef __GNUC__
191 # define ZERO 0
192 #else
193 # define ZERO 1
194 #endif
195
196 /* This is the type used for the search tree where known translations
197    are stored.  */
198 struct known_translation_t
199 {
200   /* Domain in which to search.  */
201   char *domain;
202
203   /* Plural index.  */
204   unsigned long int plindex;
205
206   /* The category.  */
207   int category;
208
209   /* State of the catalog counter at the point the string was found.  */
210   int counter;
211
212   /* And finally the translation.  */
213   const char *translation;
214
215   /* Pointer to the string in question.  */
216   char msgid[ZERO];
217 };
218
219 /* Root of the search tree with known translations.  We can use this
220    only if the system provides the `tsearch' function family.  */
221 #if defined HAVE_TSEARCH || defined _LIBC
222 # include <search.h>
223
224 static void *root;
225
226 # ifdef _LIBC
227 #  define tsearch __tsearch
228 # endif
229
230 /* Function to compare two entries in the table of known translations.  */
231 static int
232 transcmp (const void *p1, const void *p2)
233 {
234   struct known_translation_t *s1 = (struct known_translation_t *) p1;
235   struct known_translation_t *s2 = (struct known_translation_t *) p2;
236   int result;
237
238   result = strcmp (s1->msgid, s2->msgid);
239   if (result == 0)
240     {
241       result = strcmp (s1->domain, s2->domain);
242       if (result == 0)
243         {
244           result = s1->plindex - s2->plindex;
245           if (result == 0)
246             /* We compare the category last (though this is the cheapest
247                operation) since it is hopefully always the same (namely
248                LC_MESSAGES).  */
249             result = s1->category - s2->category;
250         }
251     }
252
253   return result;
254 }
255 #endif
256
257 /* Name of the default domain used for gettext(3) prior any call to
258    textdomain(3).  The default value for this is "messages".  */
259 const char _nl_default_default_domain[] = "messages";
260
261 /* Value used as the default domain for gettext(3).  */
262 const char *_nl_current_default_domain = _nl_default_default_domain;
263
264 /* Contains the default location of the message catalogs.  */
265 const char _nl_default_dirname[] = GNULOCALEDIR;
266
267 /* List with bindings of specific domains created by bindtextdomain()
268    calls.  */
269 struct binding *_nl_domain_bindings;
270
271 /* Prototypes for local functions.  */
272 static unsigned long int plural_eval (struct expression *pexp,
273                                       unsigned long int n) internal_function;
274 static const char *category_to_name PARAMS ((int category)) internal_function;
275 static const char *guess_category_value PARAMS ((int category,
276                                                  const char *categoryname))
277      internal_function;
278
279
280 /* For those loosing systems which don't have `alloca' we have to add
281    some additional code emulating it.  */
282 #ifdef HAVE_ALLOCA
283 /* Nothing has to be done.  */
284 # define ADD_BLOCK(list, address) /* nothing */
285 # define FREE_BLOCKS(list) /* nothing */
286 #else
287 struct block_list
288 {
289   void *address;
290   struct block_list *next;
291 };
292 # define ADD_BLOCK(list, addr)                                                \
293   do {                                                                        \
294     struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
295     /* If we cannot get a free block we cannot add the new element to         \
296        the list.  */                                                          \
297     if (newp != NULL) {                                                       \
298       newp->address = (addr);                                                 \
299       newp->next = (list);                                                    \
300       (list) = newp;                                                          \
301     }                                                                         \
302   } while (0)
303 # define FREE_BLOCKS(list)                                                    \
304   do {                                                                        \
305     while (list != NULL) {                                                    \
306       struct block_list *old = list;                                          \
307       list = list->next;                                                      \
308       free (old);                                                             \
309     }                                                                         \
310   } while (0)
311 # undef alloca
312 # define alloca(size) (malloc (size))
313 #endif  /* have alloca */
314
315
316 /* Names for the libintl functions are a problem.  They must not clash
317    with existing names and they should follow ANSI C.  But this source
318    code is also used in GNU C Library where the names have a __
319    prefix.  So we have to make a difference here.  */
320 #ifdef _LIBC
321 # define DCIGETTEXT __dcigettext
322 #else
323 # define DCIGETTEXT dcigettext__
324 #endif
325
326 /* Lock variable to protect the global data in the gettext implementation.  */
327 __libc_rwlock_define_initialized (, _nl_state_lock)
328
329 /* Checking whether the binaries runs SUID must be done and glibc provides
330    easier methods therefore we make a difference here.  */
331 #ifdef _LIBC
332 # define ENABLE_SECURE __libc_enable_secure
333 # define DETERMINE_SECURE
334 #else
335 static int enable_secure;
336 # define ENABLE_SECURE (enable_secure == 1)
337 # define DETERMINE_SECURE \
338   if (enable_secure == 0)                                                     \
339     {                                                                         \
340       if (getuid () != geteuid () || getgid () != getegid ())                 \
341         enable_secure = 1;                                                    \
342       else                                                                    \
343         enable_secure = -1;                                                   \
344     }
345 #endif
346
347 /* Look up MSGID in the DOMAINNAME message catalog for the current
348    CATEGORY locale and, if PLURAL is nonzero, search over string
349    depending on the plural form determined by N.  */
350 char *
351 DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
352      const char *domainname;
353      const char *msgid1;
354      const char *msgid2;
355      int plural;
356      unsigned long int n;
357      int category;
358 {
359 #ifndef HAVE_ALLOCA
360   struct block_list *block_list = NULL;
361 #endif
362   struct loaded_l10nfile *domain;
363   struct binding *binding;
364   const char *categoryname;
365   const char *categoryvalue;
366   char *dirname, *xdomainname;
367   char *single_locale;
368   char *retval;
369   int saved_errno;
370 #if defined HAVE_TSEARCH || defined _LIBC
371   struct known_translation_t *search;
372   struct known_translation_t **foundp = NULL;
373   size_t msgid_len;
374 #endif
375   size_t domainname_len;
376
377   /* If no real MSGID is given return NULL.  */
378   if (msgid1 == NULL)
379     return NULL;
380
381   __libc_rwlock_rdlock (_nl_state_lock);
382
383   /* If DOMAINNAME is NULL, we are interested in the default domain.  If
384      CATEGORY is not LC_MESSAGES this might not make much sense but the
385      definition left this undefined.  */
386   if (domainname == NULL)
387     domainname = _nl_current_default_domain;
388
389 #if defined HAVE_TSEARCH || defined _LIBC
390   msgid_len = strlen (msgid1) + 1;
391
392   if (plural == 0)
393     {
394       /* Try to find the translation among those which we found at
395          some time.  */
396       search = (struct known_translation_t *) alloca (sizeof (*search)
397                                                       + msgid_len);
398       memcpy (search->msgid, msgid1, msgid_len);
399       search->domain = (char *) domainname;
400       search->plindex = 0;
401       search->category = category;
402
403       foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
404       if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
405         {
406           __libc_rwlock_unlock (_nl_state_lock);
407           return (char *) (*foundp)->translation;
408         }
409     }
410 #endif
411
412   /* Preserve the `errno' value.  */
413   saved_errno = errno;
414
415   /* See whether this is a SUID binary or not.  */
416   DETERMINE_SECURE;
417
418   /* First find matching binding.  */
419   for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
420     {
421       int compare = strcmp (domainname, binding->domainname);
422       if (compare == 0)
423         /* We found it!  */
424         break;
425       if (compare < 0)
426         {
427           /* It is not in the list.  */
428           binding = NULL;
429           break;
430         }
431     }
432
433   if (binding == NULL)
434     dirname = (char *) _nl_default_dirname;
435   else if (binding->dirname[0] == '/')
436     dirname = binding->dirname;
437   else
438     {
439       /* We have a relative path.  Make it absolute now.  */
440       size_t dirname_len = strlen (binding->dirname) + 1;
441       size_t path_max;
442       char *ret;
443
444       path_max = (unsigned int) PATH_MAX;
445       path_max += 2;            /* The getcwd docs say to do this.  */
446
447       dirname = (char *) alloca (path_max + dirname_len);
448       ADD_BLOCK (block_list, dirname);
449
450       __set_errno (0);
451       while ((ret = getcwd (dirname, path_max)) == NULL && errno == ERANGE)
452         {
453           path_max += PATH_INCR;
454           dirname = (char *) alloca (path_max + dirname_len);
455           ADD_BLOCK (block_list, dirname);
456           __set_errno (0);
457         }
458
459       if (ret == NULL)
460         {
461           /* We cannot get the current working directory.  Don't signal an
462              error but simply return the default string.  */
463           FREE_BLOCKS (block_list);
464           __set_errno (saved_errno);
465           return (plural == 0
466                   ? (char *) msgid1
467                   /* Use the Germanic plural rule.  */
468                   : n == 1 ? (char *) msgid1 : (char *) msgid2);
469         }
470
471       stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
472     }
473
474   /* Now determine the symbolic name of CATEGORY and its value.  */
475   categoryname = category_to_name (category);
476   categoryvalue = guess_category_value (category, categoryname);
477
478   domainname_len = strlen (domainname);
479   xdomainname = (char *) alloca (strlen (categoryname)
480                                  + domainname_len + 5);
481   ADD_BLOCK (block_list, xdomainname);
482
483   stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
484                   domainname, domainname_len),
485           ".mo");
486
487   /* Creating working area.  */
488   single_locale = (char *) alloca (strlen (categoryvalue) + 1);
489   ADD_BLOCK (block_list, single_locale);
490
491
492   /* Search for the given string.  This is a loop because we perhaps
493      got an ordered list of languages to consider for the translation.  */
494   while (1)
495     {
496       /* Make CATEGORYVALUE point to the next element of the list.  */
497       while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
498         ++categoryvalue;
499       if (categoryvalue[0] == '\0')
500         {
501           /* The whole contents of CATEGORYVALUE has been searched but
502              no valid entry has been found.  We solve this situation
503              by implicitly appending a "C" entry, i.e. no translation
504              will take place.  */
505           single_locale[0] = 'C';
506           single_locale[1] = '\0';
507         }
508       else
509         {
510           char *cp = single_locale;
511           while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
512             *cp++ = *categoryvalue++;
513           *cp = '\0';
514
515           /* When this is a SUID binary we must not allow accessing files
516              outside the dedicated directories.  */
517           if (ENABLE_SECURE
518               && (memchr (single_locale, '/',
519                           _nl_find_language (single_locale) - single_locale)
520                   != NULL))
521             /* Ingore this entry.  */
522             continue;
523         }
524
525       /* If the current locale value is C (or POSIX) we don't load a
526          domain.  Return the MSGID.  */
527       if (strcmp (single_locale, "C") == 0
528           || strcmp (single_locale, "POSIX") == 0)
529         {
530           FREE_BLOCKS (block_list);
531           __libc_rwlock_unlock (_nl_state_lock);
532           __set_errno (saved_errno);
533           return (plural == 0
534                   ? (char *) msgid1
535                   /* Use the Germanic plural rule.  */
536                   : n == 1 ? (char *) msgid1 : (char *) msgid2);
537         }
538
539
540       /* Find structure describing the message catalog matching the
541          DOMAINNAME and CATEGORY.  */
542       domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
543
544       if (domain != NULL)
545         {
546           unsigned long int index = 0;
547 #if defined HAVE_TSEARCH || defined _LIBC
548           struct loaded_domain *domaindata =
549             (struct loaded_domain *) domain->data;
550
551           if (plural != 0)
552             {
553               /* Try to find the translation among those which we
554                  found at some time.  */
555               search = (struct known_translation_t *) alloca (sizeof (*search)
556                                                               + msgid_len);
557               memcpy (search->msgid, msgid1, msgid_len);
558               search->domain = (char *) domainname;
559               search->plindex = plural_eval (domaindata->plural, n);
560               if (search->plindex >= domaindata->nplurals)
561                 /* This should never happen.  It means the plural expression
562                    and the given maximum value do not match.  */
563                 search->plindex = 0;
564               index = search->plindex;
565               search->category = category;
566
567               foundp = (struct known_translation_t **) tfind (search, &root,
568                                                               transcmp);
569               if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
570                 {
571                   __libc_rwlock_unlock (_nl_state_lock);
572                   return (char *) (*foundp)->translation;
573                 }
574             }
575 #endif
576
577           retval = _nl_find_msg (domain, msgid1, index);
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                                          index);
587
588                   if (retval != NULL)
589                     break;
590                 }
591             }
592
593           if (retval != NULL)
594             {
595               FREE_BLOCKS (block_list);
596               __set_errno (saved_errno);
597 #if defined HAVE_TSEARCH || defined _LIBC
598               if (foundp == NULL)
599                 {
600                   /* Create a new entry and add it to the search tree.  */
601                   struct known_translation_t *newp;
602
603                   newp = (struct known_translation_t *)
604                     malloc (sizeof (*newp) + msgid_len
605                             + domainname_len + 1 - ZERO);
606                   if (newp != NULL)
607                     {
608                       newp->domain = mempcpy (newp->msgid, msgid1, msgid_len);
609                       memcpy (newp->domain, domainname, domainname_len + 1);
610                       newp->plindex = index;
611                       newp->category = category;
612                       newp->counter = _nl_msg_cat_cntr;
613                       newp->translation = retval;
614
615                       /* Insert the entry in the search tree.  */
616                       foundp = (struct known_translation_t **)
617                         tsearch (newp, &root, transcmp);
618                       if (foundp == NULL
619                           || __builtin_expect (*foundp != newp, 0))
620                         /* The insert failed.  */
621                         free (newp);
622                     }
623                 }
624               else
625                 {
626                   /* We can update the existing entry.  */
627                   (*foundp)->counter = _nl_msg_cat_cntr;
628                   (*foundp)->translation = retval;
629                 }
630 #endif
631               __libc_rwlock_unlock (_nl_state_lock);
632               return retval;
633             }
634         }
635     }
636   /* NOTREACHED */
637 }
638
639
640 char *
641 internal_function
642 _nl_find_msg (domain_file, msgid, index)
643      struct loaded_l10nfile *domain_file;
644      const char *msgid;
645      unsigned long int index;
646 {
647   struct loaded_domain *domain;
648   size_t act;
649   char *result;
650
651   if (domain_file->decided == 0)
652     _nl_load_domain (domain_file);
653
654   if (domain_file->data == NULL)
655     return NULL;
656
657   domain = (struct loaded_domain *) domain_file->data;
658
659   /* Locate the MSGID and its translation.  */
660   if (domain->hash_size > 2 && domain->hash_tab != NULL)
661     {
662       /* Use the hashing table.  */
663       nls_uint32 len = strlen (msgid);
664       nls_uint32 hash_val = hash_string (msgid);
665       nls_uint32 idx = hash_val % domain->hash_size;
666       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
667       nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
668
669       if (nstr == 0)
670         /* Hash table entry is empty.  */
671         return NULL;
672
673       if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
674           && strcmp (msgid,
675                      domain->data + W (domain->must_swap,
676                                        domain->orig_tab[nstr - 1].offset)) == 0)
677         {
678           act = nstr - 1;
679           goto found;
680         }
681
682       while (1)
683         {
684           if (idx >= domain->hash_size - incr)
685             idx -= domain->hash_size - incr;
686           else
687             idx += incr;
688
689           nstr = W (domain->must_swap, domain->hash_tab[idx]);
690           if (nstr == 0)
691             /* Hash table entry is empty.  */
692             return NULL;
693
694           if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
695               && (strcmp (msgid,
696                           domain->data + W (domain->must_swap,
697                                             domain->orig_tab[nstr - 1].offset))
698                   == 0))
699             {
700               act = nstr - 1;
701               goto found;
702             }
703         }
704       /* NOTREACHED */
705     }
706   else
707     {
708       /* Try the default method:  binary search in the sorted array of
709          messages.  */
710       size_t top, bottom;
711
712       bottom = 0;
713       top = domain->nstrings;
714       while (bottom < top)
715         {
716           int cmp_val;
717
718           act = (bottom + top) / 2;
719           cmp_val = strcmp (msgid, (domain->data
720                                     + W (domain->must_swap,
721                                          domain->orig_tab[act].offset)));
722           if (cmp_val < 0)
723             top = act;
724           else if (cmp_val > 0)
725             bottom = act + 1;
726           else
727             goto found;
728         }
729       /* No translation was found.  */
730       return NULL;
731     }
732
733  found:
734   /* The translation was found at index ACT.  If we have to convert the
735      string to use a different character set, this is the time.  */
736   result = ((char *) domain->data
737             + W (domain->must_swap, domain->trans_tab[act].offset));
738
739 #if defined _LIBC || HAVE_ICONV
740   if (
741 # ifdef _LIBC
742       domain->conv != (__gconv_t) -1
743 # else
744 #  if HAVE_ICONV
745       domain->conv != (iconv_t) -1
746 #  endif
747 # endif
748       )
749     {
750       /* We are supposed to do a conversion.  First allocate an
751          appropriate table with the same structure as the table
752          of translations in the file, where we can put the pointers
753          to the converted strings in.
754          There is a slight complication with the INDEX: We don't know
755          a priori which entries are plural entries. Therefore at any
756          moment we can only translate the variants 0 .. INDEX.  */
757
758       if (domain->conv_tab == NULL
759           && ((domain->conv_tab = (char **) calloc (domain->nstrings,
760                                                     sizeof (char *)))
761               == NULL))
762         /* Mark that we didn't succeed allocating a table.  */
763         domain->conv_tab = (char **) -1;
764
765       if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
766         /* Nothing we can do, no more memory.  */
767         goto converted;
768
769       if (domain->conv_tab[act] == NULL
770           || *(nls_uint32 *) domain->conv_tab[act] < index)
771         {
772           /* We haven't used this string so far, so it is not
773              translated yet.  Do this now.  */
774           /* We use a bit more efficient memory handling.
775              We allocate always larger blocks which get used over
776              time.  This is faster than many small allocations.   */
777           __libc_lock_define_initialized (static, lock)
778           static unsigned char *freemem;
779           static size_t freemem_size;
780
781           size_t resultlen;
782           const unsigned char *inbuf;
783           unsigned char *outbuf;
784
785           /* Note that we translate (index + 1) consecutive strings at
786              once, including the final NUL byte.  */
787           {
788             unsigned long int i = index;
789             char *p = result;
790             do
791               p += strlen (p) + 1;
792             while (i-- > 0);
793             resultlen = p - result;
794           }
795
796           __libc_lock_lock (lock);
797
798           inbuf = result;
799           outbuf = freemem + sizeof (nls_uint32);
800
801           while (1)
802             {
803 # ifdef _LIBC
804               size_t non_reversible;
805               int res;
806
807               if (freemem_size < 4)
808                 goto resize_freemem;
809
810               res = __gconv (domain->conv,
811                              &inbuf, inbuf + resultlen,
812                              &outbuf,
813                              outbuf + freemem_size - sizeof (nls_uint32),
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 < 4)
834                 goto resize_freemem;
835
836               outleft = freemem_size - 4;
837               if (iconv (domain->conv, &inptr, &inleft, &outptr, &outleft)
838                   != (size_t) (-1))
839                 {
840                   outbuf = (unsigned char *) outptr;
841                   break;
842                 }
843               if (errno != E2BIG)
844                 {
845                   __libc_lock_unlock (lock);
846                   goto converted;
847                 }
848 #  endif
849 # endif
850
851             resize_freemem:
852               /* We must resize the buffer.  */
853               freemem_size = 2 * freemem_size;
854               if (freemem_size < 4064)
855                 freemem_size = 4064;
856               freemem = (char *) malloc (freemem_size);
857               if (__builtin_expect (freemem == NULL, 0))
858                 {
859                   freemem_size = 0;
860                   __libc_lock_unlock (lock);
861                   goto converted;
862                 }
863
864               outbuf = freemem + sizeof (nls_uint32);
865             }
866
867           /* We have now in our buffer a converted string.  Put this
868              into the table of conversions.  */
869           *(nls_uint32 *) freemem = index;
870           domain->conv_tab[act] = freemem;
871           /* Shrink freemem, but keep it aligned.  */
872           freemem_size -= outbuf - freemem;
873           freemem = outbuf;
874           freemem += freemem_size & (alignof (nls_uint32) - 1);
875           freemem_size = freemem_size & ~ (alignof (nls_uint32) - 1);
876
877           __libc_lock_unlock (lock);
878         }
879
880       /* Now domain->conv_tab[act] contains the translation of at least
881          the variants 0 .. INDEX.  */
882       result = domain->conv_tab[act] + sizeof (nls_uint32);
883     }
884
885  converted:
886   /* The result string is converted.  */
887
888 #endif /* _LIBC || HAVE_ICONV */
889
890   /* Now skip some strings.  How much depends on the index passed in.  */
891   while (index-- > 0)
892     {
893 #ifdef _LIBC
894       result = __rawmemchr (result, '\0');
895 #else
896       result = strchr (result, '\0');
897 #endif
898       /* And skip over the NUL byte.  */
899       ++result;
900     }
901
902   return result;
903 }
904
905
906 /* Function to evaluate the plural expression and return an index value.  */
907 static unsigned long int
908 internal_function
909 plural_eval (struct expression *pexp, unsigned long int n)
910 {
911   switch (pexp->operation)
912     {
913     case var:
914       return n;
915     case num:
916       return pexp->val.num;
917     case mult:
918       return (plural_eval (pexp->val.args2.left, n)
919               * plural_eval (pexp->val.args2.right, n));
920     case divide:
921       return (plural_eval (pexp->val.args2.left, n)
922               / plural_eval (pexp->val.args2.right, n));
923     case module:
924       return (plural_eval (pexp->val.args2.left, n)
925               % plural_eval (pexp->val.args2.right, n));
926     case plus:
927       return (plural_eval (pexp->val.args2.left, n)
928               + plural_eval (pexp->val.args2.right, n));
929     case minus:
930       return (plural_eval (pexp->val.args2.left, n)
931               - plural_eval (pexp->val.args2.right, n));
932     case equal:
933       return (plural_eval (pexp->val.args2.left, n)
934               == plural_eval (pexp->val.args2.right, n));
935     case not_equal:
936       return (plural_eval (pexp->val.args2.left, n)
937               != plural_eval (pexp->val.args2.right, n));
938     case land:
939       return (plural_eval (pexp->val.args2.left, n)
940               && plural_eval (pexp->val.args2.right, n));
941     case lor:
942       return (plural_eval (pexp->val.args2.left, n)
943               || plural_eval (pexp->val.args2.right, n));
944     case qmop:
945       return (plural_eval (pexp->val.args3.bexp, n)
946               ? plural_eval (pexp->val.args3.tbranch, n)
947               : plural_eval (pexp->val.args3.fbranch, n));
948     }
949   /* NOTREACHED */
950   return 0;
951 }
952
953
954 /* Return string representation of locale CATEGORY.  */
955 static const char *
956 internal_function
957 category_to_name (category)
958      int category;
959 {
960   const char *retval;
961
962   switch (category)
963   {
964 #ifdef LC_COLLATE
965   case LC_COLLATE:
966     retval = "LC_COLLATE";
967     break;
968 #endif
969 #ifdef LC_CTYPE
970   case LC_CTYPE:
971     retval = "LC_CTYPE";
972     break;
973 #endif
974 #ifdef LC_MONETARY
975   case LC_MONETARY:
976     retval = "LC_MONETARY";
977     break;
978 #endif
979 #ifdef LC_NUMERIC
980   case LC_NUMERIC:
981     retval = "LC_NUMERIC";
982     break;
983 #endif
984 #ifdef LC_TIME
985   case LC_TIME:
986     retval = "LC_TIME";
987     break;
988 #endif
989 #ifdef LC_MESSAGES
990   case LC_MESSAGES:
991     retval = "LC_MESSAGES";
992     break;
993 #endif
994 #ifdef LC_RESPONSE
995   case LC_RESPONSE:
996     retval = "LC_RESPONSE";
997     break;
998 #endif
999 #ifdef LC_ALL
1000   case LC_ALL:
1001     /* This might not make sense but is perhaps better than any other
1002        value.  */
1003     retval = "LC_ALL";
1004     break;
1005 #endif
1006   default:
1007     /* If you have a better idea for a default value let me know.  */
1008     retval = "LC_XXX";
1009   }
1010
1011   return retval;
1012 }
1013
1014 /* Guess value of current locale from value of the environment variables.  */
1015 static const char *
1016 internal_function
1017 guess_category_value (category, categoryname)
1018      int category;
1019      const char *categoryname;
1020 {
1021   const char *retval;
1022
1023   /* The highest priority value is the `LANGUAGE' environment
1024      variable.  This is a GNU extension.  */
1025   retval = getenv ("LANGUAGE");
1026   if (retval != NULL && retval[0] != '\0')
1027     return retval;
1028
1029   /* `LANGUAGE' is not set.  So we have to proceed with the POSIX
1030      methods of looking to `LC_ALL', `LC_xxx', and `LANG'.  On some
1031      systems this can be done by the `setlocale' function itself.  */
1032 #if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
1033   return setlocale (category, NULL);
1034 #else
1035   /* Setting of LC_ALL overwrites all other.  */
1036   retval = getenv ("LC_ALL");
1037   if (retval != NULL && retval[0] != '\0')
1038     return retval;
1039
1040   /* Next comes the name of the desired category.  */
1041   retval = getenv (categoryname);
1042   if (retval != NULL && retval[0] != '\0')
1043     return retval;
1044
1045   /* Last possibility is the LANG environment variable.  */
1046   retval = getenv ("LANG");
1047   if (retval != NULL && retval[0] != '\0')
1048     return retval;
1049
1050   /* We use C as the default domain.  POSIX says this is implementation
1051      defined.  */
1052   return "C";
1053 #endif
1054 }
1055
1056 /* @@ begin of epilog @@ */
1057
1058 /* We don't want libintl.a to depend on any other library.  So we
1059    avoid the non-standard function stpcpy.  In GNU C Library this
1060    function is available, though.  Also allow the symbol HAVE_STPCPY
1061    to be defined.  */
1062 #if !_LIBC && !HAVE_STPCPY
1063 static char *
1064 stpcpy (dest, src)
1065      char *dest;
1066      const char *src;
1067 {
1068   while ((*dest++ = *src++) != '\0')
1069     /* Do nothing. */ ;
1070   return dest - 1;
1071 }
1072 #endif
1073
1074 #if !_LIBC && !HAVE_MEMPCPY
1075 static void *
1076 mempcpy (dest, src, n)
1077      void *dest;
1078      const void *src;
1079      size_t n;
1080 {
1081   return (void *) ((char *) memcpy (dest, src, n) + n);
1082 }
1083 #endif
1084
1085
1086 #ifdef _LIBC
1087 /* If we want to free all resources we have to do some work at
1088    program's end.  */
1089 static void __attribute__ ((unused))
1090 free_mem (void)
1091 {
1092   struct binding *runp;
1093
1094   for (runp = _nl_domain_bindings; runp != NULL; runp = runp->next)
1095     {
1096       if (runp->dirname != _nl_default_dirname)
1097         /* Yes, this is a pointer comparison.  */
1098         free (runp->dirname);
1099       if (runp->codeset != NULL)
1100         free (runp->codeset);
1101     }
1102
1103   if (_nl_current_default_domain != _nl_default_default_domain)
1104     /* Yes, again a pointer comparison.  */
1105     free ((char *) _nl_current_default_domain);
1106
1107   /* Remove the search tree with the known translations.  */
1108   __tdestroy (root, free);
1109 }
1110
1111 text_set_element (__libc_subfreeres, free_mem);
1112 #endif