Unify use of function aliases to make more compact PLT.
[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
528               && (memchr (single_locale, '/',
529                           _nl_find_language (single_locale) - single_locale)
530                   != NULL))
531             /* Ingore this entry.  */
532             continue;
533         }
534
535       /* If the current locale value is C (or POSIX) we don't load a
536          domain.  Return the MSGID.  */
537       if (strcmp (single_locale, "C") == 0
538           || strcmp (single_locale, "POSIX") == 0)
539         {
540           FREE_BLOCKS (block_list);
541           __libc_rwlock_unlock (_nl_state_lock);
542           __set_errno (saved_errno);
543           return (plural == 0
544                   ? (char *) msgid1
545                   /* Use the Germanic plural rule.  */
546                   : n == 1 ? (char *) msgid1 : (char *) msgid2);
547         }
548
549
550       /* Find structure describing the message catalog matching the
551          DOMAINNAME and CATEGORY.  */
552       domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
553
554       if (domain != NULL)
555         {
556           unsigned long int index = 0;
557
558           if (plural != 0)
559             {
560               struct loaded_domain *domaindata =
561                 (struct loaded_domain *) domain->data;
562               index = plural_eval (domaindata->plural, n);
563               if (index >= domaindata->nplurals)
564                 /* This should never happen.  It means the plural expression
565                    and the given maximum value do not match.  */
566                 index = 0;
567
568 #if defined HAVE_TSEARCH || defined _LIBC
569               /* Try to find the translation among those which we
570                  found at some time.  */
571               search = (struct known_translation_t *) alloca (sizeof (*search)
572                                                               + msgid_len);
573               memcpy (search->msgid, msgid1, msgid_len);
574               search->domain = (char *) domainname;
575               search->plindex = index;
576               search->category = category;
577
578               foundp = (struct known_translation_t **) tfind (search, &root,
579                                                               transcmp);
580               if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
581                 {
582                   __libc_rwlock_unlock (_nl_state_lock);
583                   return (char *) (*foundp)->translation;
584                 }
585 #endif
586             }
587
588           retval = _nl_find_msg (domain, msgid1, index);
589
590           if (retval == NULL)
591             {
592               int cnt;
593
594               for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
595                 {
596                   retval = _nl_find_msg (domain->successor[cnt], msgid1,
597                                          index);
598
599                   if (retval != NULL)
600                     break;
601                 }
602             }
603
604           if (retval != NULL)
605             {
606               FREE_BLOCKS (block_list);
607               __set_errno (saved_errno);
608 #if defined HAVE_TSEARCH || defined _LIBC
609               if (foundp == NULL)
610                 {
611                   /* Create a new entry and add it to the search tree.  */
612                   struct known_translation_t *newp;
613
614                   newp = (struct known_translation_t *)
615                     malloc (sizeof (*newp) + msgid_len
616                             + domainname_len + 1 - ZERO);
617                   if (newp != NULL)
618                     {
619                       newp->domain = mempcpy (newp->msgid, msgid1, msgid_len);
620                       memcpy (newp->domain, domainname, domainname_len + 1);
621                       newp->plindex = index;
622                       newp->category = category;
623                       newp->counter = _nl_msg_cat_cntr;
624                       newp->translation = retval;
625
626                       /* Insert the entry in the search tree.  */
627                       foundp = (struct known_translation_t **)
628                         tsearch (newp, &root, transcmp);
629                       if (foundp == NULL
630                           || __builtin_expect (*foundp != newp, 0))
631                         /* The insert failed.  */
632                         free (newp);
633                     }
634                 }
635               else
636                 {
637                   /* We can update the existing entry.  */
638                   (*foundp)->counter = _nl_msg_cat_cntr;
639                   (*foundp)->translation = retval;
640                 }
641 #endif
642               __libc_rwlock_unlock (_nl_state_lock);
643               return retval;
644             }
645         }
646     }
647   /* NOTREACHED */
648 }
649
650
651 char *
652 internal_function
653 _nl_find_msg (domain_file, msgid, index)
654      struct loaded_l10nfile *domain_file;
655      const char *msgid;
656      unsigned long int index;
657 {
658   struct loaded_domain *domain;
659   size_t act;
660   char *result;
661
662   if (domain_file->decided == 0)
663     _nl_load_domain (domain_file);
664
665   if (domain_file->data == NULL)
666     return NULL;
667
668   domain = (struct loaded_domain *) domain_file->data;
669
670   /* Locate the MSGID and its translation.  */
671   if (domain->hash_size > 2 && domain->hash_tab != NULL)
672     {
673       /* Use the hashing table.  */
674       nls_uint32 len = strlen (msgid);
675       nls_uint32 hash_val = hash_string (msgid);
676       nls_uint32 idx = hash_val % domain->hash_size;
677       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
678       nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
679
680       if (nstr == 0)
681         /* Hash table entry is empty.  */
682         return NULL;
683
684       if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
685           && strcmp (msgid,
686                      domain->data + W (domain->must_swap,
687                                        domain->orig_tab[nstr - 1].offset)) == 0)
688         {
689           act = nstr - 1;
690           goto found;
691         }
692
693       while (1)
694         {
695           if (idx >= domain->hash_size - incr)
696             idx -= domain->hash_size - incr;
697           else
698             idx += incr;
699
700           nstr = W (domain->must_swap, domain->hash_tab[idx]);
701           if (nstr == 0)
702             /* Hash table entry is empty.  */
703             return NULL;
704
705           if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
706               && (strcmp (msgid,
707                           domain->data + W (domain->must_swap,
708                                             domain->orig_tab[nstr - 1].offset))
709                   == 0))
710             {
711               act = nstr - 1;
712               goto found;
713             }
714         }
715       /* NOTREACHED */
716     }
717   else
718     {
719       /* Try the default method:  binary search in the sorted array of
720          messages.  */
721       size_t top, bottom;
722
723       bottom = 0;
724       top = domain->nstrings;
725       while (bottom < top)
726         {
727           int cmp_val;
728
729           act = (bottom + top) / 2;
730           cmp_val = strcmp (msgid, (domain->data
731                                     + W (domain->must_swap,
732                                          domain->orig_tab[act].offset)));
733           if (cmp_val < 0)
734             top = act;
735           else if (cmp_val > 0)
736             bottom = act + 1;
737           else
738             goto found;
739         }
740       /* No translation was found.  */
741       return NULL;
742     }
743
744  found:
745   /* The translation was found at index ACT.  If we have to convert the
746      string to use a different character set, this is the time.  */
747   result = ((char *) domain->data
748             + W (domain->must_swap, domain->trans_tab[act].offset));
749
750 #if defined _LIBC || HAVE_ICONV
751   if (
752 # ifdef _LIBC
753       domain->conv != (__gconv_t) -1
754 # else
755 #  if HAVE_ICONV
756       domain->conv != (iconv_t) -1
757 #  endif
758 # endif
759       )
760     {
761       /* We are supposed to do a conversion.  First allocate an
762          appropriate table with the same structure as the table
763          of translations in the file, where we can put the pointers
764          to the converted strings in.
765          There is a slight complication with the INDEX: We don't know
766          a priori which entries are plural entries. Therefore at any
767          moment we can only translate the variants 0 .. INDEX.  */
768
769       if (domain->conv_tab == NULL
770           && ((domain->conv_tab = (char **) calloc (domain->nstrings,
771                                                     sizeof (char *)))
772               == NULL))
773         /* Mark that we didn't succeed allocating a table.  */
774         domain->conv_tab = (char **) -1;
775
776       if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
777         /* Nothing we can do, no more memory.  */
778         goto converted;
779
780       if (domain->conv_tab[act] == NULL
781           || *(nls_uint32 *) domain->conv_tab[act] < index)
782         {
783           /* We haven't used this string so far, so it is not
784              translated yet.  Do this now.  */
785           /* We use a bit more efficient memory handling.
786              We allocate always larger blocks which get used over
787              time.  This is faster than many small allocations.   */
788           __libc_lock_define_initialized (static, lock)
789 #define INITIAL_BLOCK_SIZE      4080
790           static unsigned char *freemem;
791           static size_t freemem_size;
792
793           size_t resultlen;
794           const unsigned char *inbuf;
795           unsigned char *outbuf;
796           int malloc_count;
797
798           /* Note that we translate (index + 1) consecutive strings at
799              once, including the final NUL byte.  */
800           {
801             unsigned long int i = index;
802             char *p = result;
803             do
804               p += strlen (p) + 1;
805             while (i-- > 0);
806             resultlen = p - result;
807           }
808
809           __libc_lock_lock (lock);
810
811           inbuf = result;
812           outbuf = freemem + sizeof (nls_uint32);
813
814           malloc_count = 0;
815           while (1)
816             {
817 # ifdef _LIBC
818               struct transmem_list *newmem;
819               size_t non_reversible;
820               int res;
821
822               if (freemem_size < 4)
823                 goto resize_freemem;
824
825               res = __gconv (domain->conv,
826                              &inbuf, inbuf + resultlen,
827                              &outbuf,
828                              outbuf + freemem_size - sizeof (nls_uint32),
829                              &non_reversible);
830
831               if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
832                 break;
833
834               if (res != __GCONV_FULL_OUTPUT)
835                 {
836                   __libc_lock_unlock (lock);
837                   goto converted;
838                 }
839
840               inbuf = result;
841 # else
842 #  if HAVE_ICONV
843 #   define transmem freemem
844               const char *inptr = (const char *) inbuf;
845               size_t inleft = resultlen;
846               char *outptr = (char *) outbuf;
847               size_t outleft;
848
849               if (freemem_size < 4)
850                 goto resize_freemem;
851
852               outleft = freemem_size - 4;
853               if (iconv (domain->conv, &inptr, &inleft, &outptr, &outleft)
854                   != (size_t) (-1))
855                 {
856                   outbuf = (unsigned char *) outptr;
857                   break;
858                 }
859               if (errno != E2BIG)
860                 {
861                   __libc_lock_unlock (lock);
862                   goto converted;
863                 }
864 #  else
865 #   define transmem freemem
866 #  endif
867 # endif
868
869             resize_freemem:
870               /* We must allocate a new buffer of resize the old one.  */
871               if (malloc_count > 0)
872                 {
873                   struct transmem_list *next = transmem_list->next;
874
875                   ++malloc_count;
876                   freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
877                   newmem = (struct transmem_list *) realloc (transmem_list,
878                                                              freemem_size);
879
880                   if (newmem != NULL)
881                     transmem_list = next;
882                 }
883               else
884                 {
885                   malloc_count = 1;
886                   freemem_size = INITIAL_BLOCK_SIZE;
887                   newmem = (struct transmem_list *) malloc (freemem_size);
888                 }
889               if (__builtin_expect (newmem == NULL, 0))
890                 {
891                   freemem = NULL;
892                   freemem_size = 0;
893                   __libc_lock_unlock (lock);
894                   goto converted;
895                 }
896
897 # ifdef _LIBC
898               /* Add the block to the list of blocks we have to free
899                  at some point.  */
900               newmem->next = transmem_list;
901               transmem_list = newmem;
902
903               freemem = newmem->data;
904               freemem_size -= offsetof (struct transmem_list, data);
905 # endif
906
907               outbuf = freemem + sizeof (nls_uint32);
908             }
909
910           /* We have now in our buffer a converted string.  Put this
911              into the table of conversions.  */
912           *(nls_uint32 *) freemem = index;
913           domain->conv_tab[act] = freemem;
914           /* Shrink freemem, but keep it aligned.  */
915           freemem_size -= outbuf - freemem;
916           freemem = outbuf;
917           freemem += freemem_size & (alignof (nls_uint32) - 1);
918           freemem_size = freemem_size & ~ (alignof (nls_uint32) - 1);
919
920           __libc_lock_unlock (lock);
921         }
922
923       /* Now domain->conv_tab[act] contains the translation of at least
924          the variants 0 .. INDEX.  */
925       result = domain->conv_tab[act] + sizeof (nls_uint32);
926     }
927
928  converted:
929   /* The result string is converted.  */
930
931 #endif /* _LIBC || HAVE_ICONV */
932
933   /* Now skip some strings.  How much depends on the index passed in.  */
934   while (index-- > 0)
935     {
936 #ifdef _LIBC
937       result = __rawmemchr (result, '\0');
938 #else
939       result = strchr (result, '\0');
940 #endif
941       /* And skip over the NUL byte.  */
942       ++result;
943     }
944
945   return result;
946 }
947
948
949 /* Function to evaluate the plural expression and return an index value.  */
950 static unsigned long int
951 internal_function
952 plural_eval (struct expression *pexp, unsigned long int n)
953 {
954   switch (pexp->operation)
955     {
956     case var:
957       return n;
958     case num:
959       return pexp->val.num;
960     case mult:
961       return (plural_eval (pexp->val.args2.left, n)
962               * plural_eval (pexp->val.args2.right, n));
963     case divide:
964       return (plural_eval (pexp->val.args2.left, n)
965               / plural_eval (pexp->val.args2.right, n));
966     case module:
967       return (plural_eval (pexp->val.args2.left, n)
968               % plural_eval (pexp->val.args2.right, n));
969     case plus:
970       return (plural_eval (pexp->val.args2.left, n)
971               + plural_eval (pexp->val.args2.right, n));
972     case minus:
973       return (plural_eval (pexp->val.args2.left, n)
974               - plural_eval (pexp->val.args2.right, n));
975     case equal:
976       return (plural_eval (pexp->val.args2.left, n)
977               == plural_eval (pexp->val.args2.right, n));
978     case not_equal:
979       return (plural_eval (pexp->val.args2.left, n)
980               != plural_eval (pexp->val.args2.right, n));
981     case land:
982       return (plural_eval (pexp->val.args2.left, n)
983               && plural_eval (pexp->val.args2.right, n));
984     case lor:
985       return (plural_eval (pexp->val.args2.left, n)
986               || plural_eval (pexp->val.args2.right, n));
987     case qmop:
988       return (plural_eval (pexp->val.args3.bexp, n)
989               ? plural_eval (pexp->val.args3.tbranch, n)
990               : plural_eval (pexp->val.args3.fbranch, n));
991     }
992   /* NOTREACHED */
993   return 0;
994 }
995
996
997 /* Return string representation of locale CATEGORY.  */
998 static const char *
999 internal_function
1000 category_to_name (category)
1001      int category;
1002 {
1003   const char *retval;
1004
1005   switch (category)
1006   {
1007 #ifdef LC_COLLATE
1008   case LC_COLLATE:
1009     retval = "LC_COLLATE";
1010     break;
1011 #endif
1012 #ifdef LC_CTYPE
1013   case LC_CTYPE:
1014     retval = "LC_CTYPE";
1015     break;
1016 #endif
1017 #ifdef LC_MONETARY
1018   case LC_MONETARY:
1019     retval = "LC_MONETARY";
1020     break;
1021 #endif
1022 #ifdef LC_NUMERIC
1023   case LC_NUMERIC:
1024     retval = "LC_NUMERIC";
1025     break;
1026 #endif
1027 #ifdef LC_TIME
1028   case LC_TIME:
1029     retval = "LC_TIME";
1030     break;
1031 #endif
1032 #ifdef LC_MESSAGES
1033   case LC_MESSAGES:
1034     retval = "LC_MESSAGES";
1035     break;
1036 #endif
1037 #ifdef LC_RESPONSE
1038   case LC_RESPONSE:
1039     retval = "LC_RESPONSE";
1040     break;
1041 #endif
1042 #ifdef LC_ALL
1043   case LC_ALL:
1044     /* This might not make sense but is perhaps better than any other
1045        value.  */
1046     retval = "LC_ALL";
1047     break;
1048 #endif
1049   default:
1050     /* If you have a better idea for a default value let me know.  */
1051     retval = "LC_XXX";
1052   }
1053
1054   return retval;
1055 }
1056
1057 /* Guess value of current locale from value of the environment variables.  */
1058 static const char *
1059 internal_function
1060 guess_category_value (category, categoryname)
1061      int category;
1062      const char *categoryname;
1063 {
1064   const char *retval;
1065
1066   /* The highest priority value is the `LANGUAGE' environment
1067      variable.  This is a GNU extension.  */
1068   retval = getenv ("LANGUAGE");
1069   if (retval != NULL && retval[0] != '\0')
1070     return retval;
1071
1072   /* `LANGUAGE' is not set.  So we have to proceed with the POSIX
1073      methods of looking to `LC_ALL', `LC_xxx', and `LANG'.  On some
1074      systems this can be done by the `setlocale' function itself.  */
1075 #if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
1076   return setlocale (category, NULL);
1077 #else
1078   /* Setting of LC_ALL overwrites all other.  */
1079   retval = getenv ("LC_ALL");
1080   if (retval != NULL && retval[0] != '\0')
1081     return retval;
1082
1083   /* Next comes the name of the desired category.  */
1084   retval = getenv (categoryname);
1085   if (retval != NULL && retval[0] != '\0')
1086     return retval;
1087
1088   /* Last possibility is the LANG environment variable.  */
1089   retval = getenv ("LANG");
1090   if (retval != NULL && retval[0] != '\0')
1091     return retval;
1092
1093   /* We use C as the default domain.  POSIX says this is implementation
1094      defined.  */
1095   return "C";
1096 #endif
1097 }
1098
1099 /* @@ begin of epilog @@ */
1100
1101 /* We don't want libintl.a to depend on any other library.  So we
1102    avoid the non-standard function stpcpy.  In GNU C Library this
1103    function is available, though.  Also allow the symbol HAVE_STPCPY
1104    to be defined.  */
1105 #if !_LIBC && !HAVE_STPCPY
1106 static char *
1107 stpcpy (dest, src)
1108      char *dest;
1109      const char *src;
1110 {
1111   while ((*dest++ = *src++) != '\0')
1112     /* Do nothing. */ ;
1113   return dest - 1;
1114 }
1115 #endif
1116
1117 #if !_LIBC && !HAVE_MEMPCPY
1118 static void *
1119 mempcpy (dest, src, n)
1120      void *dest;
1121      const void *src;
1122      size_t n;
1123 {
1124   return (void *) ((char *) memcpy (dest, src, n) + n);
1125 }
1126 #endif
1127
1128
1129 #ifdef _LIBC
1130 /* If we want to free all resources we have to do some work at
1131    program's end.  */
1132 static void __attribute__ ((unused))
1133 free_mem (void)
1134 {
1135   struct binding *runp;
1136   void *old;
1137
1138   for (runp = _nl_domain_bindings; runp != NULL; runp = runp->next)
1139     {
1140       if (runp->dirname != _nl_default_dirname)
1141         /* Yes, this is a pointer comparison.  */
1142         free (runp->dirname);
1143       if (runp->codeset != NULL)
1144         free (runp->codeset);
1145     }
1146
1147   if (_nl_current_default_domain != _nl_default_default_domain)
1148     /* Yes, again a pointer comparison.  */
1149     free ((char *) _nl_current_default_domain);
1150
1151   /* Remove the search tree with the known translations.  */
1152   __tdestroy (root, free);
1153
1154   while (transmem_list != NULL)
1155     {
1156       old = transmem_list;
1157       transmem_list = transmem_list->next;
1158       free (old);
1159     }
1160 }
1161
1162 text_set_element (__libc_subfreeres, free_mem);
1163 #endif