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