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