OSDN Git Service

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