3c86b83f2853a007e899e3c470053e99ebbd0ce3
[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->domain, s2->domain);
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;
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 DOMAINNAME is NULL, we are interested in the default domain.  If
376      CATEGORY is not LC_MESSAGES this might not make much sense but the
377      definition left this undefined.  */
378   if (domainname == NULL)
379     domainname = _nl_current_default_domain;
380
381 #if defined HAVE_TSEARCH || defined _LIBC
382   msgid_len = strlen (msgid1) + 1;
383
384   if (plural == 0)
385     {
386       /* Try to find the translation among those which we found at
387          some time.  */
388       search = (struct known_translation_t *) alloca (sizeof (*search)
389                                                       + msgid_len);
390       memcpy (search->msgid, msgid1, msgid_len);
391       search->domain = (char *) domainname;
392       search->plindex = 0;
393       search->category = category;
394
395       foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
396       if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
397         {
398           __libc_rwlock_unlock (_nl_state_lock);
399           return (char *) (*foundp)->translation;
400         }
401     }
402 #endif
403
404   /* Preserve the `errno' value.  */
405   saved_errno = errno;
406
407   /* See whether this is a SUID binary or not.  */
408   DETERMINE_SECURE;
409
410   /* First find matching binding.  */
411   for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
412     {
413       int compare = strcmp (domainname, binding->domainname);
414       if (compare == 0)
415         /* We found it!  */
416         break;
417       if (compare < 0)
418         {
419           /* It is not in the list.  */
420           binding = NULL;
421           break;
422         }
423     }
424
425   if (binding == NULL)
426     dirname = (char *) _nl_default_dirname;
427   else if (binding->dirname[0] == '/')
428     dirname = binding->dirname;
429   else
430     {
431       /* We have a relative path.  Make it absolute now.  */
432       size_t dirname_len = strlen (binding->dirname) + 1;
433       size_t path_max;
434       char *ret;
435
436       path_max = (unsigned int) PATH_MAX;
437       path_max += 2;            /* The getcwd docs say to do this.  */
438
439       dirname = (char *) alloca (path_max + dirname_len);
440       ADD_BLOCK (block_list, dirname);
441
442       __set_errno (0);
443       while ((ret = getcwd (dirname, path_max)) == NULL && errno == ERANGE)
444         {
445           path_max += PATH_INCR;
446           dirname = (char *) alloca (path_max + dirname_len);
447           ADD_BLOCK (block_list, dirname);
448           __set_errno (0);
449         }
450
451       if (ret == NULL)
452         {
453           /* We cannot get the current working directory.  Don't signal an
454              error but simply return the default string.  */
455           FREE_BLOCKS (block_list);
456           __set_errno (saved_errno);
457           return (plural == 0
458                   ? (char *) msgid1
459                   /* Use the Germanic plural rule.  */
460                   : n == 1 ? (char *) msgid1 : (char *) msgid2);
461         }
462
463       stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
464     }
465
466   /* Now determine the symbolic name of CATEGORY and its value.  */
467   categoryname = category_to_name (category);
468   categoryvalue = guess_category_value (category, categoryname);
469
470   domainname_len = strlen (domainname);
471   xdomainname = (char *) alloca (strlen (categoryname)
472                                  + domainname_len + 5);
473   ADD_BLOCK (block_list, xdomainname);
474
475   stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
476                   domainname, domainname_len),
477           ".mo");
478
479   /* Creating working area.  */
480   single_locale = (char *) alloca (strlen (categoryvalue) + 1);
481   ADD_BLOCK (block_list, single_locale);
482
483
484   /* Search for the given string.  This is a loop because we perhaps
485      got an ordered list of languages to consider for the translation.  */
486   while (1)
487     {
488       /* Make CATEGORYVALUE point to the next element of the list.  */
489       while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
490         ++categoryvalue;
491       if (categoryvalue[0] == '\0')
492         {
493           /* The whole contents of CATEGORYVALUE has been searched but
494              no valid entry has been found.  We solve this situation
495              by implicitly appending a "C" entry, i.e. no translation
496              will take place.  */
497           single_locale[0] = 'C';
498           single_locale[1] = '\0';
499         }
500       else
501         {
502           char *cp = single_locale;
503           while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
504             *cp++ = *categoryvalue++;
505           *cp = '\0';
506
507           /* When this is a SUID binary we must not allow accessing files
508              outside the dedicated directories.  */
509           if (ENABLE_SECURE
510               && (memchr (single_locale, '/',
511                           _nl_find_language (single_locale) - single_locale)
512                   != NULL))
513             /* Ingore this entry.  */
514             continue;
515         }
516
517       /* If the current locale value is C (or POSIX) we don't load a
518          domain.  Return the MSGID.  */
519       if (strcmp (single_locale, "C") == 0
520           || strcmp (single_locale, "POSIX") == 0)
521         {
522           FREE_BLOCKS (block_list);
523           __libc_rwlock_unlock (_nl_state_lock);
524           __set_errno (saved_errno);
525           return (plural == 0
526                   ? (char *) msgid1
527                   /* Use the Germanic plural rule.  */
528                   : n == 1 ? (char *) msgid1 : (char *) msgid2);
529         }
530
531
532       /* Find structure describing the message catalog matching the
533          DOMAINNAME and CATEGORY.  */
534       domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
535
536       if (domain != NULL)
537         {
538           unsigned long int index = 0;
539 #if defined HAVE_TSEARCH || defined _LIBC
540           struct loaded_domain *domaindata =
541             (struct loaded_domain *) domain->data;
542
543           if (plural != 0)
544             {
545               /* Try to find the translation among those which we
546                  found at some time.  */
547               search = (struct known_translation_t *) alloca (sizeof (*search)
548                                                               + msgid_len);
549               memcpy (search->msgid, msgid1, msgid_len);
550               search->domain = (char *) domainname;
551               search->plindex = plural_eval (domaindata->plural, n);
552               if (search->plindex >= domaindata->nplurals)
553                 /* This should never happen.  It means the plural expression
554                    and the given maximum value do not match.  */
555                 search->plindex = 0;
556               index = search->plindex;
557               search->category = category;
558
559               foundp = (struct known_translation_t **) tfind (search, &root,
560                                                               transcmp);
561               if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
562                 {
563                   __libc_rwlock_unlock (_nl_state_lock);
564                   return (char *) (*foundp)->translation;
565                 }
566             }
567 #endif
568
569           retval = _nl_find_msg (domain, msgid1, index);
570
571           if (retval == NULL)
572             {
573               int cnt;
574
575               for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
576                 {
577                   retval = _nl_find_msg (domain->successor[cnt], msgid1,
578                                          index);
579
580                   if (retval != NULL)
581                     break;
582                 }
583             }
584
585           if (retval != NULL)
586             {
587               FREE_BLOCKS (block_list);
588               __set_errno (saved_errno);
589 #if defined HAVE_TSEARCH || defined _LIBC
590               if (foundp == NULL)
591                 {
592                   /* Create a new entry and add it to the search tree.  */
593                   struct known_translation_t *newp;
594
595                   newp = (struct known_translation_t *)
596                     malloc (sizeof (*newp) + msgid_len
597                             + domainname_len + 1 - ZERO);
598                   if (newp != NULL)
599                     {
600                       newp->domain = mempcpy (newp->msgid, msgid1, msgid_len);
601                       memcpy (newp->domain, domainname, domainname_len + 1);
602                       newp->plindex = index;
603                       newp->category = category;
604                       newp->counter = _nl_msg_cat_cntr;
605                       newp->translation = retval;
606
607                       /* Insert the entry in the search tree.  */
608                       foundp = (struct known_translation_t **)
609                         tsearch (newp, &root, transcmp);
610                       if (foundp == NULL
611                           || __builtin_expect (*foundp != newp, 0))
612                         /* The insert failed.  */
613                         free (newp);
614                     }
615                 }
616               else
617                 {
618                   /* We can update the existing entry.  */
619                   (*foundp)->counter = _nl_msg_cat_cntr;
620                   (*foundp)->translation = retval;
621                 }
622 #endif
623               __libc_rwlock_unlock (_nl_state_lock);
624               return retval;
625             }
626         }
627     }
628   /* NOTREACHED */
629 }
630
631
632 char *
633 internal_function
634 _nl_find_msg (domain_file, msgid, index)
635      struct loaded_l10nfile *domain_file;
636      const char *msgid;
637      unsigned long int index;
638 {
639   struct loaded_domain *domain;
640   size_t act;
641   char *result;
642
643   if (domain_file->decided == 0)
644     _nl_load_domain (domain_file);
645
646   if (domain_file->data == NULL)
647     return NULL;
648
649   domain = (struct loaded_domain *) domain_file->data;
650
651   /* Locate the MSGID and its translation.  */
652   if (domain->hash_size > 2 && domain->hash_tab != NULL)
653     {
654       /* Use the hashing table.  */
655       nls_uint32 len = strlen (msgid);
656       nls_uint32 hash_val = hash_string (msgid);
657       nls_uint32 idx = hash_val % domain->hash_size;
658       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
659       nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
660
661       if (nstr == 0)
662         /* Hash table entry is empty.  */
663         return NULL;
664
665       if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
666           && strcmp (msgid,
667                      domain->data + W (domain->must_swap,
668                                        domain->orig_tab[nstr - 1].offset)) == 0)
669         {
670           act = nstr - 1;
671           goto found;
672         }
673
674       while (1)
675         {
676           if (idx >= domain->hash_size - incr)
677             idx -= domain->hash_size - incr;
678           else
679             idx += incr;
680
681           nstr = W (domain->must_swap, domain->hash_tab[idx]);
682           if (nstr == 0)
683             /* Hash table entry is empty.  */
684             return NULL;
685
686           if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
687               && (strcmp (msgid,
688                           domain->data + W (domain->must_swap,
689                                             domain->orig_tab[nstr - 1].offset))
690                   == 0))
691             {
692               act = nstr - 1;
693               goto found;
694             }
695         }
696       /* NOTREACHED */
697     }
698   else
699     {
700       /* Try the default method:  binary search in the sorted array of
701          messages.  */
702       size_t top, bottom;
703
704       bottom = 0;
705       top = domain->nstrings;
706       while (bottom < top)
707         {
708           int cmp_val;
709
710           act = (bottom + top) / 2;
711           cmp_val = strcmp (msgid, (domain->data
712                                     + W (domain->must_swap,
713                                          domain->orig_tab[act].offset)));
714           if (cmp_val < 0)
715             top = act;
716           else if (cmp_val > 0)
717             bottom = act + 1;
718           else
719             goto found;
720         }
721       /* No translation was found.  */
722       return NULL;
723     }
724
725  found:
726   /* The translation was found at index ACT.  If we have to convert the
727      string to use a different character set, this is the time.  */
728   result = (char *) domain->data
729            + W (domain->must_swap, domain->trans_tab[act].offset);
730
731 #if defined _LIBC || HAVE_ICONV
732   if (
733 # ifdef _LIBC
734       domain->conv != (__gconv_t) -1
735 # else
736 #  if HAVE_ICONV
737       domain->conv != (iconv_t) -1
738 #  endif
739 # endif
740       )
741     {
742       /* We are supposed to do a conversion.  First allocate an
743          appropriate table with the same structure as the table
744          of translations in the file, where we can put the pointers
745          to the converted strings in.
746          The is a slight complication with the INDEX: We don't know
747          a priori which entries are plural entries. Therefore at any
748          moment we can only translate the variants 0 .. INDEX.  */
749
750       if (domain->conv_tab == NULL
751           && ((domain->conv_tab = (char **) calloc (domain->nstrings,
752                                                     sizeof (char *)))
753               == NULL))
754         /* Mark that we didn't succeed allocating a table.  */
755         domain->conv_tab = (char **) -1;
756
757       if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
758         /* Nothing we can do, no more memory.  */
759         goto converted;
760
761       if (domain->conv_tab[act] == NULL
762           || *(nls_uint32 *) domain->conv_tab[act] < index)
763         {
764           /* We haven't used this string so far, so it is not
765              translated yet.  Do this now.  */
766           /* We use a bit more efficient memory handling.
767              We allocate always larger blocks which get used over
768              time.  This is faster than many small allocations.   */
769           __libc_lock_define_initialized (static, lock)
770           static unsigned char *freemem;
771           static size_t freemem_size;
772
773           size_t resultlen;
774           const unsigned char *inbuf;
775           unsigned char *outbuf;
776
777           /* Note that we translate (index + 1) consecutive strings at
778              once, including the final NUL byte.  */
779           {
780             unsigned long int i = index;
781             char *p = result;
782             do
783               p += strlen (p) + 1;
784             while (i-- > 0);
785             resultlen = p - result;
786           }
787
788           inbuf = result;
789           outbuf = freemem + 4;
790
791           __libc_lock_lock (lock);
792
793           while (1)
794             {
795 # ifdef _LIBC
796               size_t non_reversible;
797               int res;
798
799               res = __gconv (domain->conv,
800                              &inbuf, inbuf + resultlen,
801                              &outbuf, outbuf + freemem_size,
802                              &non_reversible);
803
804               if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
805                 break;
806
807               if (res != __GCONV_FULL_OUTPUT)
808                 {
809                   __libc_lock_unlock (lock);
810                   goto converted;
811                 }
812
813               inbuf = result;
814 # else
815 #  if HAVE_ICONV
816               const char *inptr = (const char *) inbuf;
817               size_t inleft = resultlen;
818               char *outptr = (char *) outbuf;
819               size_t outleft = freemem_size;
820
821               if (iconv (domain->conv, &inptr, &inleft, &outptr, &outleft)
822                   != (size_t) (-1))
823                 {
824                   outbuf = (unsigned char *) outptr;
825                   break;
826                 }
827               if (errno != E2BIG)
828                 {
829                   __libc_lock_unlock (lock);
830                   goto converted;
831                 }
832 #  endif
833 # endif
834
835               /* We must resize the buffer.  */
836               freemem_size = 2 * freemem_size;
837               if (freemem_size < 4064)
838                 freemem_size = 4064;
839               freemem = (char *) malloc (freemem_size);
840               if (__builtin_expect (freemem == NULL, 0))
841                 {
842                   __libc_lock_unlock (lock);
843                   goto converted;
844                 }
845
846               outbuf = freemem + 4;
847             }
848
849           /* We have now in our buffer a converted string.  Put this
850              into the table of conversions.  */
851           *(nls_uint32 *) freemem = index;
852           domain->conv_tab[act] = freemem;
853           /* Shrink freemem, but keep it aligned.  */
854           freemem_size -= outbuf - freemem;
855           freemem = outbuf;
856           freemem += freemem_size & (__alignof__ (nls_uint32) - 1);
857           freemem_size = freemem_size & ~ (__alignof__ (nls_uint32) - 1);
858
859           __libc_lock_unlock (lock);
860         }
861
862       /* Now domain->conv_tab[act] contains the translation of at least
863          the variants 0 .. INDEX.  */
864       result = domain->conv_tab[act] + 4;
865     }
866
867  converted:
868   /* The result string is converted.  */
869
870 #endif /* _LIBC || HAVE_ICONV */
871
872   /* Now skip some strings.  How much depends on the index passed in.  */
873   while (index-- > 0)
874     {
875 #ifdef _LIBC
876       result = __rawmemchr (result, '\0');
877 #else
878       result = strchr (result, '\0');
879 #endif
880       /* And skip over the NUL byte.  */
881       ++result;
882     }
883
884   return result;
885 }
886
887
888 /* Function to evaluate the plural expression and return an index value.  */
889 static unsigned long int
890 internal_function
891 plural_eval (struct expression *pexp, unsigned long int n)
892 {
893   switch (pexp->operation)
894     {
895     case var:
896       return n;
897     case num:
898       return pexp->val.num;
899     case mult:
900       return (plural_eval (pexp->val.args2.left, n)
901               * plural_eval (pexp->val.args2.right, n));
902     case divide:
903       return (plural_eval (pexp->val.args2.left, n)
904               / plural_eval (pexp->val.args2.right, n));
905     case module:
906       return (plural_eval (pexp->val.args2.left, n)
907               % plural_eval (pexp->val.args2.right, n));
908     case plus:
909       return (plural_eval (pexp->val.args2.left, n)
910               + plural_eval (pexp->val.args2.right, n));
911     case minus:
912       return (plural_eval (pexp->val.args2.left, n)
913               - plural_eval (pexp->val.args2.right, n));
914     case equal:
915       return (plural_eval (pexp->val.args2.left, n)
916               == plural_eval (pexp->val.args2.right, n));
917     case not_equal:
918       return (plural_eval (pexp->val.args2.left, n)
919               != plural_eval (pexp->val.args2.right, n));
920     case land:
921       return (plural_eval (pexp->val.args2.left, n)
922               && plural_eval (pexp->val.args2.right, n));
923     case lor:
924       return (plural_eval (pexp->val.args2.left, n)
925               || plural_eval (pexp->val.args2.right, n));
926     case qmop:
927       return (plural_eval (pexp->val.args3.bexp, n)
928               ? plural_eval (pexp->val.args3.tbranch, n)
929               : plural_eval (pexp->val.args3.fbranch, n));
930     }
931   /* NOTREACHED */
932   return 0;
933 }
934
935
936 /* Return string representation of locale CATEGORY.  */
937 static const char *
938 internal_function
939 category_to_name (category)
940      int category;
941 {
942   const char *retval;
943
944   switch (category)
945   {
946 #ifdef LC_COLLATE
947   case LC_COLLATE:
948     retval = "LC_COLLATE";
949     break;
950 #endif
951 #ifdef LC_CTYPE
952   case LC_CTYPE:
953     retval = "LC_CTYPE";
954     break;
955 #endif
956 #ifdef LC_MONETARY
957   case LC_MONETARY:
958     retval = "LC_MONETARY";
959     break;
960 #endif
961 #ifdef LC_NUMERIC
962   case LC_NUMERIC:
963     retval = "LC_NUMERIC";
964     break;
965 #endif
966 #ifdef LC_TIME
967   case LC_TIME:
968     retval = "LC_TIME";
969     break;
970 #endif
971 #ifdef LC_MESSAGES
972   case LC_MESSAGES:
973     retval = "LC_MESSAGES";
974     break;
975 #endif
976 #ifdef LC_RESPONSE
977   case LC_RESPONSE:
978     retval = "LC_RESPONSE";
979     break;
980 #endif
981 #ifdef LC_ALL
982   case LC_ALL:
983     /* This might not make sense but is perhaps better than any other
984        value.  */
985     retval = "LC_ALL";
986     break;
987 #endif
988   default:
989     /* If you have a better idea for a default value let me know.  */
990     retval = "LC_XXX";
991   }
992
993   return retval;
994 }
995
996 /* Guess value of current locale from value of the environment variables.  */
997 static const char *
998 internal_function
999 guess_category_value (category, categoryname)
1000      int category;
1001      const char *categoryname;
1002 {
1003   const char *retval;
1004
1005   /* The highest priority value is the `LANGUAGE' environment
1006      variable.  This is a GNU extension.  */
1007   retval = getenv ("LANGUAGE");
1008   if (retval != NULL && retval[0] != '\0')
1009     return retval;
1010
1011   /* `LANGUAGE' is not set.  So we have to proceed with the POSIX
1012      methods of looking to `LC_ALL', `LC_xxx', and `LANG'.  On some
1013      systems this can be done by the `setlocale' function itself.  */
1014 #if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
1015   return setlocale (category, NULL);
1016 #else
1017   /* Setting of LC_ALL overwrites all other.  */
1018   retval = getenv ("LC_ALL");
1019   if (retval != NULL && retval[0] != '\0')
1020     return retval;
1021
1022   /* Next comes the name of the desired category.  */
1023   retval = getenv (categoryname);
1024   if (retval != NULL && retval[0] != '\0')
1025     return retval;
1026
1027   /* Last possibility is the LANG environment variable.  */
1028   retval = getenv ("LANG");
1029   if (retval != NULL && retval[0] != '\0')
1030     return retval;
1031
1032   /* We use C as the default domain.  POSIX says this is implementation
1033      defined.  */
1034   return "C";
1035 #endif
1036 }
1037
1038 /* @@ begin of epilog @@ */
1039
1040 /* We don't want libintl.a to depend on any other library.  So we
1041    avoid the non-standard function stpcpy.  In GNU C Library this
1042    function is available, though.  Also allow the symbol HAVE_STPCPY
1043    to be defined.  */
1044 #if !_LIBC && !HAVE_STPCPY
1045 static char *
1046 stpcpy (dest, src)
1047      char *dest;
1048      const char *src;
1049 {
1050   while ((*dest++ = *src++) != '\0')
1051     /* Do nothing. */ ;
1052   return dest - 1;
1053 }
1054 #endif
1055
1056 #if !_LIBC && !HAVE_MEMPCPY
1057 static void *
1058 mempcpy (dest, src, n)
1059      void *dest;
1060      const void *src;
1061      size_t n;
1062 {
1063   return (void *) ((char *) memcpy (dest, src, n) + n);
1064 }
1065 #endif
1066
1067
1068 #ifdef _LIBC
1069 /* If we want to free all resources we have to do some work at
1070    program's end.  */
1071 static void __attribute__ ((unused))
1072 free_mem (void)
1073 {
1074   struct binding *runp;
1075
1076   for (runp = _nl_domain_bindings; runp != NULL; runp = runp->next)
1077     {
1078       if (runp->dirname != _nl_default_dirname)
1079         /* Yes, this is a pointer comparison.  */
1080         free (runp->dirname);
1081       if (runp->codeset != NULL)
1082         free (runp->codeset);
1083     }
1084
1085   if (_nl_current_default_domain != _nl_default_default_domain)
1086     /* Yes, again a pointer comparison.  */
1087     free ((char *) _nl_current_default_domain);
1088
1089   /* Remove the search tree with the known translations.  */
1090   __tdestroy (root, free);
1091 }
1092
1093 text_set_element (__libc_subfreeres, free_mem);
1094 #endif