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