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