(struct loaded_domain): Change plural to const struct expression *.
[kopensolaris-gnu/glibc.git] / intl / dcigettext.c
1 /* Implementation of the internal dcigettext function.
2    Copyright (C) 1995-2005, 2006, 2007 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
21    This must come before <config.h> because <config.h> may include
22    <features.h>, and once <features.h> has been included, it's too late.  */
23 #ifndef _GNU_SOURCE
24 # define _GNU_SOURCE    1
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 # include <config.h>
29 #endif
30
31 #include <sys/types.h>
32
33 #ifdef __GNUC__
34 # define alloca __builtin_alloca
35 # define HAVE_ALLOCA 1
36 #else
37 # if defined HAVE_ALLOCA_H || defined _LIBC
38 #  include <alloca.h>
39 # else
40 #  ifdef _AIX
41  #pragma alloca
42 #  else
43 #   ifndef alloca
44 char *alloca ();
45 #   endif
46 #  endif
47 # endif
48 #endif
49
50 #include <errno.h>
51 #ifndef errno
52 extern int errno;
53 #endif
54 #ifndef __set_errno
55 # define __set_errno(val) errno = (val)
56 #endif
57
58 #include <stddef.h>
59 #include <stdlib.h>
60 #include <string.h>
61
62 #if defined HAVE_UNISTD_H || defined _LIBC
63 # include <unistd.h>
64 #endif
65
66 #include <locale.h>
67
68 #if defined HAVE_SYS_PARAM_H || defined _LIBC
69 # include <sys/param.h>
70 #endif
71
72 #include "gettextP.h"
73 #include "plural-exp.h"
74 #ifdef _LIBC
75 # include <libintl.h>
76 #else
77 # include "libgnuintl.h"
78 #endif
79 #include "hash-string.h"
80
81 /* Thread safetyness.  */
82 #ifdef _LIBC
83 # include <bits/libc-lock.h>
84 #else
85 /* Provide dummy implementation if this is outside glibc.  */
86 # define __libc_lock_define_initialized(CLASS, NAME)
87 # define __libc_lock_lock(NAME)
88 # define __libc_lock_unlock(NAME)
89 # define __libc_rwlock_define_initialized(CLASS, NAME)
90 # define __libc_rwlock_rdlock(NAME)
91 # define __libc_rwlock_unlock(NAME)
92 #endif
93
94 /* Alignment of types.  */
95 #if defined __GNUC__ && __GNUC__ >= 2
96 # define alignof(TYPE) __alignof__ (TYPE)
97 #else
98 # define alignof(TYPE) \
99     ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
100 #endif
101
102 /* The internal variables in the standalone libintl.a must have different
103    names than the internal variables in GNU libc, otherwise programs
104    using libintl.a cannot be linked statically.  */
105 #if !defined _LIBC
106 # define _nl_default_default_domain libintl_nl_default_default_domain
107 # define _nl_current_default_domain libintl_nl_current_default_domain
108 # define _nl_default_dirname libintl_nl_default_dirname
109 # define _nl_domain_bindings libintl_nl_domain_bindings
110 #endif
111
112 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
113 #ifndef offsetof
114 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
115 #endif
116
117 /* @@ end of prolog @@ */
118
119 #ifdef _LIBC
120 /* Rename the non ANSI C functions.  This is required by the standard
121    because some ANSI C functions will require linking with this object
122    file and the name space must not be polluted.  */
123 # define getcwd __getcwd
124 # ifndef stpcpy
125 #  define stpcpy __stpcpy
126 # endif
127 # define tfind __tfind
128 #else
129 # if !defined HAVE_GETCWD
130 char *getwd ();
131 #  define getcwd(buf, max) getwd (buf)
132 # else
133 char *getcwd ();
134 # endif
135 # ifndef HAVE_STPCPY
136 static char *stpcpy PARAMS ((char *dest, const char *src));
137 # endif
138 # ifndef HAVE_MEMPCPY
139 static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
140 # endif
141 #endif
142
143 /* Amount to increase buffer size by in each try.  */
144 #define PATH_INCR 32
145
146 /* The following is from pathmax.h.  */
147 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
148    PATH_MAX but might cause redefinition warnings when sys/param.h is
149    later included (as on MORE/BSD 4.3).  */
150 #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
151 # include <limits.h>
152 #endif
153
154 #ifndef _POSIX_PATH_MAX
155 # define _POSIX_PATH_MAX 255
156 #endif
157
158 #if !defined PATH_MAX && defined _PC_PATH_MAX
159 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
160 #endif
161
162 /* Don't include sys/param.h if it already has been.  */
163 #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
164 # include <sys/param.h>
165 #endif
166
167 #if !defined PATH_MAX && defined MAXPATHLEN
168 # define PATH_MAX MAXPATHLEN
169 #endif
170
171 #ifndef PATH_MAX
172 # define PATH_MAX _POSIX_PATH_MAX
173 #endif
174
175 /* Whether to support different locales in different threads.  */
176 #if defined _LIBC || HAVE_NL_LOCALE_NAME
177 # define HAVE_PER_THREAD_LOCALE
178 #endif
179
180 /* This is the type used for the search tree where known translations
181    are stored.  */
182 struct known_translation_t
183 {
184   /* Domain in which to search.  */
185   const char *domainname;
186
187   /* The category.  */
188   int category;
189
190 #ifdef HAVE_PER_THREAD_LOCALE
191   /* Name of the relevant locale category, or "" for the global locale.  */
192   const char *localename;
193 #endif
194
195   /* State of the catalog counter at the point the string was found.  */
196   int counter;
197
198   /* Catalog where the string was found.  */
199   struct loaded_l10nfile *domain;
200
201   /* And finally the translation.  */
202   const char *translation;
203   size_t translation_length;
204
205   /* Pointer to the string in question.  */
206   char msgid[ZERO];
207 };
208
209 /* Root of the search tree with known translations.  We can use this
210    only if the system provides the `tsearch' function family.  */
211 #if defined HAVE_TSEARCH || defined _LIBC
212 # include <search.h>
213
214 static void *root;
215
216 # ifdef _LIBC
217 #  define tsearch __tsearch
218 # endif
219
220 /* Function to compare two entries in the table of known translations.  */
221 static int transcmp PARAMS ((const void *p1, const void *p2));
222 static int
223 transcmp (p1, p2)
224      const void *p1;
225      const void *p2;
226 {
227   const struct known_translation_t *s1;
228   const struct known_translation_t *s2;
229   int result;
230
231   s1 = (const struct known_translation_t *) p1;
232   s2 = (const struct known_translation_t *) p2;
233
234   result = strcmp (s1->msgid, s2->msgid);
235   if (result == 0)
236     {
237       result = strcmp (s1->domainname, s2->domainname);
238       if (result == 0)
239         {
240 #ifdef HAVE_PER_THREAD_LOCALE
241           result = strcmp (s1->localename, s2->localename);
242           if (result == 0)
243 #endif
244             /* We compare the category last (though this is the cheapest
245                operation) since it is hopefully always the same (namely
246                LC_MESSAGES).  */
247             result = s1->category - s2->category;
248         }
249     }
250
251   return result;
252 }
253 #endif
254
255 /* Name of the default domain used for gettext(3) prior any call to
256    textdomain(3).  The default value for this is "messages".  */
257 const char _nl_default_default_domain[] attribute_hidden = "messages";
258
259 /* Value used as the default domain for gettext(3).  */
260 const char *_nl_current_default_domain attribute_hidden
261      = _nl_default_default_domain;
262
263 /* Contains the default location of the message catalogs.  */
264
265 #ifdef _LIBC
266 extern const char _nl_default_dirname[];
267 libc_hidden_proto (_nl_default_dirname)
268 #endif
269 const char _nl_default_dirname[] = LOCALEDIR;
270 #ifdef _LIBC
271 libc_hidden_data_def (_nl_default_dirname)
272 #endif
273
274 /* List with bindings of specific domains created by bindtextdomain()
275    calls.  */
276 struct binding *_nl_domain_bindings;
277
278 /* Prototypes for local functions.  */
279 static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
280                                     unsigned long int n,
281                                     const char *translation,
282                                     size_t translation_len))
283      internal_function;
284 static const char *guess_category_value PARAMS ((int category,
285                                                  const char *categoryname))
286      internal_function;
287 #ifdef _LIBC
288 # include "../locale/localeinfo.h"
289 # define category_to_name(category) \
290   _nl_category_names.str + _nl_category_name_idxs[category]
291 #else
292 static const char *category_to_name PARAMS ((int category)) internal_function;
293 #endif
294
295
296 /* For those loosing systems which don't have `alloca' we have to add
297    some additional code emulating it.  */
298 #ifdef HAVE_ALLOCA
299 /* Nothing has to be done.  */
300 # define freea(p) /* nothing */
301 # define ADD_BLOCK(list, address) /* nothing */
302 # define FREE_BLOCKS(list) /* nothing */
303 #else
304 struct block_list
305 {
306   void *address;
307   struct block_list *next;
308 };
309 # define ADD_BLOCK(list, addr)                                                \
310   do {                                                                        \
311     struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
312     /* If we cannot get a free block we cannot add the new element to         \
313        the list.  */                                                          \
314     if (newp != NULL) {                                                       \
315       newp->address = (addr);                                                 \
316       newp->next = (list);                                                    \
317       (list) = newp;                                                          \
318     }                                                                         \
319   } while (0)
320 # define FREE_BLOCKS(list)                                                    \
321   do {                                                                        \
322     while (list != NULL) {                                                    \
323       struct block_list *old = list;                                          \
324       list = list->next;                                                      \
325       free (old->address);                                                    \
326       free (old);                                                             \
327     }                                                                         \
328   } while (0)
329 # undef alloca
330 # define alloca(size) (malloc (size))
331 # define freea(p) free (p)
332 #endif  /* have alloca */
333
334
335 #ifdef _LIBC
336 /* List of blocks allocated for translations.  */
337 typedef struct transmem_list
338 {
339   struct transmem_list *next;
340   char data[ZERO];
341 } transmem_block_t;
342 static struct transmem_list *transmem_list;
343 #else
344 typedef unsigned char transmem_block_t;
345 #endif
346 #if defined _LIBC || HAVE_ICONV
347 static const char *get_output_charset PARAMS ((struct binding *domainbinding))
348      internal_function;
349 #endif
350
351
352 /* Names for the libintl functions are a problem.  They must not clash
353    with existing names and they should follow ANSI C.  But this source
354    code is also used in GNU C Library where the names have a __
355    prefix.  So we have to make a difference here.  */
356 #ifdef _LIBC
357 # define DCIGETTEXT __dcigettext
358 #else
359 # define DCIGETTEXT libintl_dcigettext
360 #endif
361
362 /* Lock variable to protect the global data in the gettext implementation.  */
363 #ifdef _LIBC
364 __libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
365 #endif
366
367 /* Checking whether the binaries runs SUID must be done and glibc provides
368    easier methods therefore we make a difference here.  */
369 #ifdef _LIBC
370 # define ENABLE_SECURE __libc_enable_secure
371 # define DETERMINE_SECURE
372 #else
373 # ifndef HAVE_GETUID
374 #  define getuid() 0
375 # endif
376 # ifndef HAVE_GETGID
377 #  define getgid() 0
378 # endif
379 # ifndef HAVE_GETEUID
380 #  define geteuid() getuid()
381 # endif
382 # ifndef HAVE_GETEGID
383 #  define getegid() getgid()
384 # endif
385 static int enable_secure;
386 # define ENABLE_SECURE (enable_secure == 1)
387 # define DETERMINE_SECURE \
388   if (enable_secure == 0)                                                     \
389     {                                                                         \
390       if (getuid () != geteuid () || getgid () != getegid ())                 \
391         enable_secure = 1;                                                    \
392       else                                                                    \
393         enable_secure = -1;                                                   \
394     }
395 #endif
396
397 /* Get the function to evaluate the plural expression.  */
398 #include "plural-eval.c"
399
400 /* Look up MSGID in the DOMAINNAME message catalog for the current
401    CATEGORY locale and, if PLURAL is nonzero, search over string
402    depending on the plural form determined by N.  */
403 char *
404 DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
405      const char *domainname;
406      const char *msgid1;
407      const char *msgid2;
408      int plural;
409      unsigned long int n;
410      int category;
411 {
412 #ifndef HAVE_ALLOCA
413   struct block_list *block_list = NULL;
414 #endif
415   struct loaded_l10nfile *domain;
416   struct binding *binding;
417   const char *categoryname;
418   const char *categoryvalue;
419   char *dirname, *xdomainname;
420   char *single_locale;
421   char *retval;
422   size_t retlen;
423   int saved_errno;
424 #if defined HAVE_TSEARCH || defined _LIBC
425   struct known_translation_t *search;
426   struct known_translation_t **foundp = NULL;
427   size_t msgid_len;
428 # ifdef HAVE_PER_THREAD_LOCALE
429   const char *localename;
430 # endif
431 #endif
432   size_t domainname_len;
433
434   /* If no real MSGID is given return NULL.  */
435   if (msgid1 == NULL)
436     return NULL;
437
438 #ifdef _LIBC
439   if (category < 0 || category >= __LC_LAST || category == LC_ALL)
440     /* Bogus.  */
441     return (plural == 0
442             ? (char *) msgid1
443             /* Use the Germanic plural rule.  */
444             : n == 1 ? (char *) msgid1 : (char *) msgid2);
445 #endif
446
447   __libc_rwlock_rdlock (_nl_state_lock);
448
449   /* If DOMAINNAME is NULL, we are interested in the default domain.  If
450      CATEGORY is not LC_MESSAGES this might not make much sense but the
451      definition left this undefined.  */
452   if (domainname == NULL)
453     domainname = _nl_current_default_domain;
454
455 #if defined HAVE_TSEARCH || defined _LIBC
456   msgid_len = strlen (msgid1) + 1;
457
458   /* Try to find the translation among those which we found at
459      some time.  */
460   search = (struct known_translation_t *)
461            alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
462   memcpy (search->msgid, msgid1, msgid_len);
463   search->domainname = domainname;
464   search->category = category;
465 # ifdef HAVE_PER_THREAD_LOCALE
466 #  ifdef _LIBC
467   localename = __current_locale_name (category);
468 #  endif
469   search->localename = localename;
470 # endif
471
472   /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
473      tsearch calls can be fatal.  */
474   __libc_rwlock_define_initialized (static, tree_lock);
475   __libc_rwlock_rdlock (tree_lock);
476
477   foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
478
479   __libc_rwlock_unlock (tree_lock);
480
481   freea (search);
482   if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
483     {
484       /* Now deal with plural.  */
485       if (plural)
486         retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
487                                 (*foundp)->translation_length);
488       else
489         retval = (char *) (*foundp)->translation;
490
491       __libc_rwlock_unlock (_nl_state_lock);
492       return retval;
493     }
494 #endif
495
496   /* Preserve the `errno' value.  */
497   saved_errno = errno;
498
499   /* See whether this is a SUID binary or not.  */
500   DETERMINE_SECURE;
501
502   /* First find matching binding.  */
503   for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
504     {
505       int compare = strcmp (domainname, binding->domainname);
506       if (compare == 0)
507         /* We found it!  */
508         break;
509       if (compare < 0)
510         {
511           /* It is not in the list.  */
512           binding = NULL;
513           break;
514         }
515     }
516
517   if (binding == NULL)
518     dirname = (char *) _nl_default_dirname;
519   else if (binding->dirname[0] == '/')
520     dirname = binding->dirname;
521   else
522     {
523       /* We have a relative path.  Make it absolute now.  */
524       size_t dirname_len = strlen (binding->dirname) + 1;
525       size_t path_max;
526       char *ret;
527
528       path_max = (unsigned int) PATH_MAX;
529       path_max += 2;            /* The getcwd docs say to do this.  */
530
531       for (;;)
532         {
533           dirname = (char *) alloca (path_max + dirname_len);
534           ADD_BLOCK (block_list, dirname);
535
536           __set_errno (0);
537           ret = getcwd (dirname, path_max);
538           if (ret != NULL || errno != ERANGE)
539             break;
540
541           path_max += path_max / 2;
542           path_max += PATH_INCR;
543         }
544
545       if (ret == NULL)
546         {
547           /* We cannot get the current working directory.  Don't signal an
548              error but simply return the default string.  */
549           FREE_BLOCKS (block_list);
550           __libc_rwlock_unlock (_nl_state_lock);
551           __set_errno (saved_errno);
552           return (plural == 0
553                   ? (char *) msgid1
554                   /* Use the Germanic plural rule.  */
555                   : n == 1 ? (char *) msgid1 : (char *) msgid2);
556         }
557
558       stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
559     }
560
561   /* Now determine the symbolic name of CATEGORY and its value.  */
562   categoryname = category_to_name (category);
563   categoryvalue = guess_category_value (category, categoryname);
564
565   domainname_len = strlen (domainname);
566   xdomainname = (char *) alloca (strlen (categoryname)
567                                  + domainname_len + 5);
568   ADD_BLOCK (block_list, xdomainname);
569
570   stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
571                   domainname, domainname_len),
572           ".mo");
573
574   /* Creating working area.  */
575   single_locale = (char *) alloca (strlen (categoryvalue) + 1);
576   ADD_BLOCK (block_list, single_locale);
577
578
579   /* Search for the given string.  This is a loop because we perhaps
580      got an ordered list of languages to consider for the translation.  */
581   while (1)
582     {
583       /* Make CATEGORYVALUE point to the next element of the list.  */
584       while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
585         ++categoryvalue;
586       if (categoryvalue[0] == '\0')
587         {
588           /* The whole contents of CATEGORYVALUE has been searched but
589              no valid entry has been found.  We solve this situation
590              by implicitly appending a "C" entry, i.e. no translation
591              will take place.  */
592           single_locale[0] = 'C';
593           single_locale[1] = '\0';
594         }
595       else
596         {
597           char *cp = single_locale;
598           while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
599             *cp++ = *categoryvalue++;
600           *cp = '\0';
601
602           /* When this is a SUID binary we must not allow accessing files
603              outside the dedicated directories.  */
604           if (ENABLE_SECURE && strchr (single_locale, '/') != NULL)
605             /* Ingore this entry.  */
606             continue;
607         }
608
609       /* If the current locale value is C (or POSIX) we don't load a
610          domain.  Return the MSGID.  */
611       if (strcmp (single_locale, "C") == 0
612           || strcmp (single_locale, "POSIX") == 0)
613         {
614         no_translation:
615           FREE_BLOCKS (block_list);
616           __libc_rwlock_unlock (_nl_state_lock);
617           __set_errno (saved_errno);
618           return (plural == 0
619                   ? (char *) msgid1
620                   /* Use the Germanic plural rule.  */
621                   : n == 1 ? (char *) msgid1 : (char *) msgid2);
622         }
623
624
625       /* Find structure describing the message catalog matching the
626          DOMAINNAME and CATEGORY.  */
627       domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
628
629       if (domain != NULL)
630         {
631           retval = _nl_find_msg (domain, binding, msgid1, 1, &retlen);
632
633           if (retval == NULL)
634             {
635               int cnt;
636
637               for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
638                 {
639                   retval = _nl_find_msg (domain->successor[cnt], binding,
640                                          msgid1, 1, &retlen);
641
642                   if (retval != NULL)
643                     {
644                       domain = domain->successor[cnt];
645                       break;
646                     }
647                 }
648             }
649
650           /* Returning -1 means that some resource problem exists
651              (likely memory) and that the strings could not be
652              converted.  Return the original strings.  */
653           if (__builtin_expect (retval == (char *) -1, 0))
654             goto no_translation;
655
656           if (retval != NULL)
657             {
658               /* Found the translation of MSGID1 in domain DOMAIN:
659                  starting at RETVAL, RETLEN bytes.  */
660               FREE_BLOCKS (block_list);
661 #if defined HAVE_TSEARCH || defined _LIBC
662               if (foundp == NULL)
663                 {
664                   /* Create a new entry and add it to the search tree.  */
665                   size_t size;
666                   struct known_translation_t *newp;
667
668                   size = offsetof (struct known_translation_t, msgid)
669                          + msgid_len + domainname_len + 1;
670 # ifdef HAVE_PER_THREAD_LOCALE
671                   size += strlen (localename) + 1;
672 # endif
673                   newp = (struct known_translation_t *) malloc (size);
674                   if (newp != NULL)
675                     {
676                       char *new_domainname;
677 # ifdef HAVE_PER_THREAD_LOCALE
678                       char *new_localename;
679 # endif
680
681                       new_domainname = mempcpy (newp->msgid, msgid1, msgid_len);
682                       memcpy (new_domainname, domainname, domainname_len + 1);
683 # ifdef HAVE_PER_THREAD_LOCALE
684                       new_localename = new_domainname + domainname_len + 1;
685                       strcpy (new_localename, localename);
686 # endif
687                       newp->domainname = new_domainname;
688                       newp->category = category;
689 # ifdef HAVE_PER_THREAD_LOCALE
690                       newp->localename = new_localename;
691 # endif
692                       newp->counter = _nl_msg_cat_cntr;
693                       newp->domain = domain;
694                       newp->translation = retval;
695                       newp->translation_length = retlen;
696
697                       __libc_rwlock_wrlock (tree_lock);
698
699                       /* Insert the entry in the search tree.  */
700                       foundp = (struct known_translation_t **)
701                         tsearch (newp, &root, transcmp);
702
703                       __libc_rwlock_unlock (tree_lock);
704
705                       if (foundp == NULL
706                           || __builtin_expect (*foundp != newp, 0))
707                         /* The insert failed.  */
708                         free (newp);
709                     }
710                 }
711               else
712                 {
713                   /* We can update the existing entry.  */
714                   (*foundp)->counter = _nl_msg_cat_cntr;
715                   (*foundp)->domain = domain;
716                   (*foundp)->translation = retval;
717                   (*foundp)->translation_length = retlen;
718                 }
719 #endif
720               __set_errno (saved_errno);
721
722               /* Now deal with plural.  */
723               if (plural)
724                 retval = plural_lookup (domain, n, retval, retlen);
725
726               __libc_rwlock_unlock (_nl_state_lock);
727               return retval;
728             }
729         }
730     }
731   /* NOTREACHED */
732 }
733
734
735 char *
736 internal_function
737 _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
738      struct loaded_l10nfile *domain_file;
739      struct binding *domainbinding;
740      const char *msgid;
741      int convert;
742      size_t *lengthp;
743 {
744   struct loaded_domain *domain;
745   nls_uint32 nstrings;
746   size_t act;
747   char *result;
748   size_t resultlen;
749
750   if (domain_file->decided <= 0)
751     _nl_load_domain (domain_file, domainbinding);
752
753   if (domain_file->data == NULL)
754     return NULL;
755
756   domain = (struct loaded_domain *) domain_file->data;
757
758   nstrings = domain->nstrings;
759
760   /* Locate the MSGID and its translation.  */
761   if (domain->hash_tab != NULL)
762     {
763       /* Use the hashing table.  */
764       nls_uint32 len = strlen (msgid);
765       nls_uint32 hash_val = __hash_string (msgid);
766       nls_uint32 idx = hash_val % domain->hash_size;
767       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
768
769       while (1)
770         {
771           nls_uint32 nstr =
772             W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
773
774           if (nstr == 0)
775             /* Hash table entry is empty.  */
776             return NULL;
777
778           nstr--;
779
780           /* Compare msgid with the original string at index nstr.
781              We compare the lengths with >=, not ==, because plural entries
782              are represented by strings with an embedded NUL.  */
783           if (nstr < nstrings
784               ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
785                 && (strcmp (msgid,
786                             domain->data + W (domain->must_swap,
787                                               domain->orig_tab[nstr].offset))
788                     == 0)
789               : domain->orig_sysdep_tab[nstr - nstrings].length > len
790                 && (strcmp (msgid,
791                             domain->orig_sysdep_tab[nstr - nstrings].pointer)
792                     == 0))
793             {
794               act = nstr;
795               goto found;
796             }
797
798           if (idx >= domain->hash_size - incr)
799             idx -= domain->hash_size - incr;
800           else
801             idx += incr;
802         }
803       /* NOTREACHED */
804     }
805   else
806     {
807       /* Try the default method:  binary search in the sorted array of
808          messages.  */
809       size_t top, bottom;
810
811       bottom = 0;
812       top = nstrings;
813       while (bottom < top)
814         {
815           int cmp_val;
816
817           act = (bottom + top) / 2;
818           cmp_val = strcmp (msgid, (domain->data
819                                     + W (domain->must_swap,
820                                          domain->orig_tab[act].offset)));
821           if (cmp_val < 0)
822             top = act;
823           else if (cmp_val > 0)
824             bottom = act + 1;
825           else
826             goto found;
827         }
828       /* No translation was found.  */
829       return NULL;
830     }
831
832  found:
833   /* The translation was found at index ACT.  If we have to convert the
834      string to use a different character set, this is the time.  */
835   if (act < nstrings)
836     {
837       result = (char *)
838         (domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
839       resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
840     }
841   else
842     {
843       result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
844       resultlen = domain->trans_sysdep_tab[act - nstrings].length;
845     }
846
847 #if defined _LIBC || HAVE_ICONV
848   if (convert)
849     {
850       /* We are supposed to do a conversion.  */
851       const char *encoding = get_output_charset (domainbinding);
852
853       /* Search whether a table with converted translations for this
854          encoding has already been allocated.  */
855       size_t nconversions = domain->nconversions;
856       struct converted_domain *convd = NULL;
857       size_t i;
858
859       for (i = nconversions; i > 0; )
860         {
861           i--;
862           if (strcmp (domain->conversions[i].encoding, encoding) == 0)
863             {
864               convd = &domain->conversions[i];
865               break;
866             }
867         }
868
869       if (convd == NULL)
870         {
871           /* Allocate a table for the converted translations for this
872              encoding.  */
873           struct converted_domain *new_conversions =
874             (struct converted_domain *)
875             realloc (domain->conversions,
876                      (nconversions + 1) * sizeof (struct converted_domain));
877
878           if (__builtin_expect (new_conversions == NULL, 0))
879             /* Nothing we can do, no more memory.  We cannot use the
880                translation because it might be encoded incorrectly.  */
881             return (char *) -1;
882
883           domain->conversions = new_conversions;
884
885           /* Copy the 'encoding' string to permanent storage.  */
886           encoding = strdup (encoding);
887           if (__builtin_expect (encoding == NULL, 0))
888             /* Nothing we can do, no more memory.  We cannot use the
889                translation because it might be encoded incorrectly.  */
890             return (char *) -1;
891
892           convd = &new_conversions[nconversions];
893           convd->encoding = encoding;
894
895           /* Find out about the character set the file is encoded with.
896              This can be found (in textual form) in the entry "".  If this
897              entry does not exist or if this does not contain the 'charset='
898              information, we will assume the charset matches the one the
899              current locale and we don't have to perform any conversion.  */
900 # ifdef _LIBC
901           convd->conv = (__gconv_t) -1;
902 # else
903 #  if HAVE_ICONV
904           convd->conv = (iconv_t) -1;
905 #  endif
906 # endif
907           {
908             char *nullentry;
909             size_t nullentrylen;
910
911             /* Get the header entry.  This is a recursion, but it doesn't
912                reallocate domain->conversions because we pass convert = 0.  */
913             nullentry =
914               _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
915
916             if (nullentry != NULL)
917               {
918                 const char *charsetstr;
919
920                 charsetstr = strstr (nullentry, "charset=");
921                 if (charsetstr != NULL)
922                   {
923                     size_t len;
924                     char *charset;
925                     const char *outcharset;
926
927                     charsetstr += strlen ("charset=");
928                     len = strcspn (charsetstr, " \t\n");
929
930                     charset = (char *) alloca (len + 1);
931 # if defined _LIBC || HAVE_MEMPCPY
932                     *((char *) mempcpy (charset, charsetstr, len)) = '\0';
933 # else
934                     memcpy (charset, charsetstr, len);
935                     charset[len] = '\0';
936 # endif
937
938                     outcharset = encoding;
939
940 # ifdef _LIBC
941                     /* We always want to use transliteration.  */
942                     outcharset = norm_add_slashes (outcharset, "TRANSLIT");
943                     charset = norm_add_slashes (charset, "");
944                     int r = __gconv_open (outcharset, charset, &convd->conv,
945                                           GCONV_AVOID_NOCONV);
946                     if (__builtin_expect (r != __GCONV_OK, 0))
947                       {
948                         /* If the output encoding is the same there is
949                            nothing to do.  Otherwise do not use the
950                            translation at all.  */
951                         if (__builtin_expect (r != __GCONV_NULCONV, 1))
952                           return NULL;
953
954                         convd->conv = (__gconv_t) -1;
955                       }
956 # else
957 #  if HAVE_ICONV
958                     /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
959                        we want to use transliteration.  */
960 #   if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
961        || _LIBICONV_VERSION >= 0x0105
962                     if (strchr (outcharset, '/') == NULL)
963                       {
964                         char *tmp;
965
966                         len = strlen (outcharset);
967                         tmp = (char *) alloca (len + 10 + 1);
968                         memcpy (tmp, outcharset, len);
969                         memcpy (tmp + len, "//TRANSLIT", 10 + 1);
970                         outcharset = tmp;
971
972                         convd->conv = iconv_open (outcharset, charset);
973
974                         freea (outcharset);
975                       }
976                     else
977 #   endif
978                       convd->conv = iconv_open (outcharset, charset);
979 #  endif
980 # endif
981
982                     freea (charset);
983                   }
984               }
985           }
986           convd->conv_tab = NULL;
987           /* Here domain->conversions is still == new_conversions.  */
988           domain->nconversions++;
989         }
990
991       if (
992 # ifdef _LIBC
993           convd->conv != (__gconv_t) -1
994 # else
995 #  if HAVE_ICONV
996           convd->conv != (iconv_t) -1
997 #  endif
998 # endif
999           )
1000         {
1001           /* We are supposed to do a conversion.  First allocate an
1002              appropriate table with the same structure as the table
1003              of translations in the file, where we can put the pointers
1004              to the converted strings in.
1005              There is a slight complication with plural entries.  They
1006              are represented by consecutive NUL terminated strings.  We
1007              handle this case by converting RESULTLEN bytes, including
1008              NULs.  */
1009
1010           if (convd->conv_tab == NULL
1011               && ((convd->conv_tab =
1012                     (char **) calloc (nstrings + domain->n_sysdep_strings,
1013                                       sizeof (char *)))
1014                   == NULL))
1015             /* Mark that we didn't succeed allocating a table.  */
1016             convd->conv_tab = (char **) -1;
1017
1018           if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
1019             /* Nothing we can do, no more memory.  We cannot use the
1020                translation because it might be encoded incorrectly.  */
1021             return (char *) -1;
1022
1023           if (convd->conv_tab[act] == NULL)
1024             {
1025               /* We haven't used this string so far, so it is not
1026                  translated yet.  Do this now.  */
1027               /* We use a bit more efficient memory handling.
1028                  We allocate always larger blocks which get used over
1029                  time.  This is faster than many small allocations.   */
1030               __libc_lock_define_initialized (static, lock)
1031 # define INITIAL_BLOCK_SIZE     4080
1032               static unsigned char *freemem;
1033               static size_t freemem_size;
1034
1035               const unsigned char *inbuf;
1036               unsigned char *outbuf;
1037               int malloc_count;
1038 # ifndef _LIBC
1039               transmem_block_t *transmem_list = NULL;
1040 # endif
1041
1042               __libc_lock_lock (lock);
1043
1044               inbuf = (const unsigned char *) result;
1045               outbuf = freemem + sizeof (size_t);
1046
1047               malloc_count = 0;
1048               while (1)
1049                 {
1050                   transmem_block_t *newmem;
1051 # ifdef _LIBC
1052                   size_t non_reversible;
1053                   int res;
1054
1055                   if (freemem_size < sizeof (size_t))
1056                     goto resize_freemem;
1057
1058                   res = __gconv (convd->conv,
1059                                  &inbuf, inbuf + resultlen,
1060                                  &outbuf,
1061                                  outbuf + freemem_size - sizeof (size_t),
1062                                  &non_reversible);
1063
1064                   if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
1065                     break;
1066
1067                   if (res != __GCONV_FULL_OUTPUT)
1068                     {
1069                       /* We should not use the translation at all, it
1070                          is incorrectly encoded.  */
1071                       __libc_lock_unlock (lock);
1072                       return NULL;
1073                     }
1074
1075                   inbuf = (const unsigned char *) result;
1076 # else
1077 #  if HAVE_ICONV
1078                   const char *inptr = (const char *) inbuf;
1079                   size_t inleft = resultlen;
1080                   char *outptr = (char *) outbuf;
1081                   size_t outleft;
1082
1083                   if (freemem_size < sizeof (size_t))
1084                     goto resize_freemem;
1085
1086                   outleft = freemem_size - sizeof (size_t);
1087                   if (iconv (convd->conv,
1088                              (ICONV_CONST char **) &inptr, &inleft,
1089                              &outptr, &outleft)
1090                       != (size_t) (-1))
1091                     {
1092                       outbuf = (unsigned char *) outptr;
1093                       break;
1094                     }
1095                   if (errno != E2BIG)
1096                     {
1097                       __libc_lock_unlock (lock);
1098                       return NULL;
1099                     }
1100 #  endif
1101 # endif
1102
1103                 resize_freemem:
1104                   /* We must allocate a new buffer or resize the old one.  */
1105                   if (malloc_count > 0)
1106                     {
1107                       ++malloc_count;
1108                       freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
1109                       newmem = (transmem_block_t *) realloc (transmem_list,
1110                                                              freemem_size);
1111 # ifdef _LIBC
1112                       if (newmem != NULL)
1113                         transmem_list = transmem_list->next;
1114                       else
1115                         {
1116                           struct transmem_list *old = transmem_list;
1117
1118                           transmem_list = transmem_list->next;
1119                           free (old);
1120                         }
1121 # endif
1122                     }
1123                   else
1124                     {
1125                       malloc_count = 1;
1126                       freemem_size = INITIAL_BLOCK_SIZE;
1127                       newmem = (transmem_block_t *) malloc (freemem_size);
1128                     }
1129                   if (__builtin_expect (newmem == NULL, 0))
1130                     {
1131                       freemem = NULL;
1132                       freemem_size = 0;
1133                       __libc_lock_unlock (lock);
1134                       return (char *) -1;
1135                     }
1136
1137 # ifdef _LIBC
1138                   /* Add the block to the list of blocks we have to free
1139                      at some point.  */
1140                   newmem->next = transmem_list;
1141                   transmem_list = newmem;
1142
1143                   freemem = (unsigned char *) newmem->data;
1144                   freemem_size -= offsetof (struct transmem_list, data);
1145 # else
1146                   transmem_list = newmem;
1147                   freemem = newmem;
1148 # endif
1149
1150                   outbuf = freemem + sizeof (size_t);
1151                 }
1152
1153               /* We have now in our buffer a converted string.  Put this
1154                  into the table of conversions.  */
1155               *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
1156               convd->conv_tab[act] = (char *) freemem;
1157               /* Shrink freemem, but keep it aligned.  */
1158               freemem_size -= outbuf - freemem;
1159               freemem = outbuf;
1160               freemem += freemem_size & (alignof (size_t) - 1);
1161               freemem_size = freemem_size & ~ (alignof (size_t) - 1);
1162
1163               __libc_lock_unlock (lock);
1164             }
1165
1166           /* Now convd->conv_tab[act] contains the translation of all
1167              the plural variants.  */
1168           result = convd->conv_tab[act] + sizeof (size_t);
1169           resultlen = *(size_t *) convd->conv_tab[act];
1170         }
1171     }
1172
1173   /* The result string is converted.  */
1174
1175 #endif /* _LIBC || HAVE_ICONV */
1176
1177   *lengthp = resultlen;
1178   return result;
1179 }
1180
1181
1182 /* Look up a plural variant.  */
1183 static char *
1184 internal_function
1185 plural_lookup (domain, n, translation, translation_len)
1186      struct loaded_l10nfile *domain;
1187      unsigned long int n;
1188      const char *translation;
1189      size_t translation_len;
1190 {
1191   struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
1192   unsigned long int index;
1193   const char *p;
1194
1195   index = plural_eval (domaindata->plural, n);
1196   if (index >= domaindata->nplurals)
1197     /* This should never happen.  It means the plural expression and the
1198        given maximum value do not match.  */
1199     index = 0;
1200
1201   /* Skip INDEX strings at TRANSLATION.  */
1202   p = translation;
1203   while (index-- > 0)
1204     {
1205 #ifdef _LIBC
1206       p = __rawmemchr (p, '\0');
1207 #else
1208       p = strchr (p, '\0');
1209 #endif
1210       /* And skip over the NUL byte.  */
1211       p++;
1212
1213       if (p >= translation + translation_len)
1214         /* This should never happen.  It means the plural expression
1215            evaluated to a value larger than the number of variants
1216            available for MSGID1.  */
1217         return (char *) translation;
1218     }
1219   return (char *) p;
1220 }
1221
1222 #ifndef _LIBC
1223 /* Return string representation of locale CATEGORY.  */
1224 static const char *
1225 internal_function
1226 category_to_name (category)
1227      int category;
1228 {
1229   const char *retval;
1230
1231   switch (category)
1232   {
1233 #ifdef LC_COLLATE
1234   case LC_COLLATE:
1235     retval = "LC_COLLATE";
1236     break;
1237 #endif
1238 #ifdef LC_CTYPE
1239   case LC_CTYPE:
1240     retval = "LC_CTYPE";
1241     break;
1242 #endif
1243 #ifdef LC_MONETARY
1244   case LC_MONETARY:
1245     retval = "LC_MONETARY";
1246     break;
1247 #endif
1248 #ifdef LC_NUMERIC
1249   case LC_NUMERIC:
1250     retval = "LC_NUMERIC";
1251     break;
1252 #endif
1253 #ifdef LC_TIME
1254   case LC_TIME:
1255     retval = "LC_TIME";
1256     break;
1257 #endif
1258 #ifdef LC_MESSAGES
1259   case LC_MESSAGES:
1260     retval = "LC_MESSAGES";
1261     break;
1262 #endif
1263 #ifdef LC_RESPONSE
1264   case LC_RESPONSE:
1265     retval = "LC_RESPONSE";
1266     break;
1267 #endif
1268 #ifdef LC_ALL
1269   case LC_ALL:
1270     /* This might not make sense but is perhaps better than any other
1271        value.  */
1272     retval = "LC_ALL";
1273     break;
1274 #endif
1275   default:
1276     /* If you have a better idea for a default value let me know.  */
1277     retval = "LC_XXX";
1278   }
1279
1280   return retval;
1281 }
1282 #endif
1283
1284 /* Guess value of current locale from value of the environment variables.  */
1285 static const char *
1286 internal_function
1287 guess_category_value (category, categoryname)
1288      int category;
1289      const char *categoryname;
1290 {
1291   const char *language;
1292   const char *retval;
1293
1294   /* The highest priority value is the `LANGUAGE' environment
1295      variable.  But we don't use the value if the currently selected
1296      locale is the C locale.  This is a GNU extension.  */
1297   language = getenv ("LANGUAGE");
1298   if (language != NULL && language[0] == '\0')
1299     language = NULL;
1300
1301   /* We have to proceed with the POSIX methods of looking to `LC_ALL',
1302      `LC_xxx', and `LANG'.  On some systems this can be done by the
1303      `setlocale' function itself.  */
1304 #ifdef _LIBC
1305   retval = __current_locale_name (category);
1306 #else
1307   retval = _nl_locale_name (category, categoryname);
1308 #endif
1309
1310   return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
1311 }
1312
1313 #if defined _LIBC || HAVE_ICONV
1314 /* Returns the output charset.  */
1315 static const char *
1316 internal_function
1317 get_output_charset (domainbinding)
1318      struct binding *domainbinding;
1319 {
1320   /* The output charset should normally be determined by the locale.  But
1321      sometimes the locale is not used or not correctly set up, so we provide
1322      a possibility for the user to override this: the OUTPUT_CHARSET
1323      environment variable.  Moreover, the value specified through
1324      bind_textdomain_codeset overrides both.  */
1325   if (domainbinding != NULL && domainbinding->codeset != NULL)
1326     return domainbinding->codeset;
1327   else
1328     {
1329       /* For speed reasons, we look at the value of OUTPUT_CHARSET only
1330          once.  This is a user variable that is not supposed to change
1331          during a program run.  */
1332       static char *output_charset_cache;
1333       static int output_charset_cached;
1334
1335       if (!output_charset_cached)
1336         {
1337           const char *value = getenv ("OUTPUT_CHARSET");
1338
1339           if (value != NULL && value[0] != '\0')
1340             {
1341               size_t len = strlen (value) + 1;
1342               char *value_copy = (char *) malloc (len);
1343
1344               if (value_copy != NULL)
1345                 memcpy (value_copy, value, len);
1346               output_charset_cache = value_copy;
1347             }
1348           output_charset_cached = 1;
1349         }
1350
1351       if (output_charset_cache != NULL)
1352         return output_charset_cache;
1353       else
1354         {
1355 # ifdef _LIBC
1356           return _NL_CURRENT (LC_CTYPE, CODESET);
1357 # else
1358 #  if HAVE_ICONV
1359           extern const char *locale_charset PARAMS ((void);
1360           return locale_charset ();
1361 #  endif
1362 # endif
1363         }
1364     }
1365 }
1366 #endif
1367
1368 /* @@ begin of epilog @@ */
1369
1370 /* We don't want libintl.a to depend on any other library.  So we
1371    avoid the non-standard function stpcpy.  In GNU C Library this
1372    function is available, though.  Also allow the symbol HAVE_STPCPY
1373    to be defined.  */
1374 #if !_LIBC && !HAVE_STPCPY
1375 static char *
1376 stpcpy (dest, src)
1377      char *dest;
1378      const char *src;
1379 {
1380   while ((*dest++ = *src++) != '\0')
1381     /* Do nothing. */ ;
1382   return dest - 1;
1383 }
1384 #endif
1385
1386 #if !_LIBC && !HAVE_MEMPCPY
1387 static void *
1388 mempcpy (dest, src, n)
1389      void *dest;
1390      const void *src;
1391      size_t n;
1392 {
1393   return (void *) ((char *) memcpy (dest, src, n) + n);
1394 }
1395 #endif
1396
1397
1398 #ifdef _LIBC
1399 /* If we want to free all resources we have to do some work at
1400    program's end.  */
1401 libc_freeres_fn (free_mem)
1402 {
1403   void *old;
1404
1405   while (_nl_domain_bindings != NULL)
1406     {
1407       struct binding *oldp = _nl_domain_bindings;
1408       _nl_domain_bindings = _nl_domain_bindings->next;
1409       if (oldp->dirname != _nl_default_dirname)
1410         /* Yes, this is a pointer comparison.  */
1411         free (oldp->dirname);
1412       free (oldp->codeset);
1413       free (oldp);
1414     }
1415
1416   if (_nl_current_default_domain != _nl_default_default_domain)
1417     /* Yes, again a pointer comparison.  */
1418     free ((char *) _nl_current_default_domain);
1419
1420   /* Remove the search tree with the known translations.  */
1421   __tdestroy (root, free);
1422   root = NULL;
1423
1424   while (transmem_list != NULL)
1425     {
1426       old = transmem_list;
1427       transmem_list = transmem_list->next;
1428       free (old);
1429     }
1430 }
1431 #endif