Implement sem_open, sem_close, and sem_unlink
[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       /* Protect against reallocation of the table.  */
854       __libc_rwlock_rdlock (domain->conversions_lock);
855
856       /* Search whether a table with converted translations for this
857          encoding has already been allocated.  */
858       size_t nconversions = domain->nconversions;
859       struct converted_domain *convd = NULL;
860       size_t i;
861
862       for (i = nconversions; i > 0; )
863         {
864           i--;
865           if (strcmp (domain->conversions[i].encoding, encoding) == 0)
866             {
867               convd = &domain->conversions[i];
868               break;
869             }
870         }
871
872       __libc_rwlock_unlock (domain->conversions_lock);
873
874       if (convd == NULL)
875         {
876           /* We have to allocate a new conversions table.  */
877           __libc_rwlock_wrlock (domain->conversions_lock);
878
879           /* Maybe in the meantime somebody added the translation.
880              Recheck.  */
881           for (i = nconversions; i > 0; )
882             {
883               i--;
884               if (strcmp (domain->conversions[i].encoding, encoding) == 0)
885                 {
886                   convd = &domain->conversions[i];
887                   goto found_convd;
888                 }
889             }
890
891           /* Allocate a table for the converted translations for this
892              encoding.  */
893           struct converted_domain *new_conversions =
894             (struct converted_domain *)
895             realloc (domain->conversions,
896                      (nconversions + 1) * sizeof (struct converted_domain));
897
898           if (__builtin_expect (new_conversions == NULL, 0))
899             {
900               /* Nothing we can do, no more memory.  We cannot use the
901                  translation because it might be encoded incorrectly.  */
902             unlock_fail:
903               __libc_rwlock_unlock (domain->conversions_lock);
904               return (char *) -1;
905             }
906
907           domain->conversions = new_conversions;
908
909           /* Copy the 'encoding' string to permanent storage.  */
910           encoding = strdup (encoding);
911           if (__builtin_expect (encoding == NULL, 0))
912             /* Nothing we can do, no more memory.  We cannot use the
913                translation because it might be encoded incorrectly.  */
914             goto unlock_fail;
915
916           convd = &new_conversions[nconversions];
917           convd->encoding = encoding;
918
919           /* Find out about the character set the file is encoded with.
920              This can be found (in textual form) in the entry "".  If this
921              entry does not exist or if this does not contain the 'charset='
922              information, we will assume the charset matches the one the
923              current locale and we don't have to perform any conversion.  */
924 # ifdef _LIBC
925           convd->conv = (__gconv_t) -1;
926 # else
927 #  if HAVE_ICONV
928           convd->conv = (iconv_t) -1;
929 #  endif
930 # endif
931           {
932             char *nullentry;
933             size_t nullentrylen;
934
935             /* Get the header entry.  This is a recursion, but it doesn't
936                reallocate domain->conversions because we pass convert = 0.  */
937             nullentry =
938               _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
939
940             if (nullentry != NULL)
941               {
942                 const char *charsetstr;
943
944                 charsetstr = strstr (nullentry, "charset=");
945                 if (charsetstr != NULL)
946                   {
947                     size_t len;
948                     char *charset;
949                     const char *outcharset;
950
951                     charsetstr += strlen ("charset=");
952                     len = strcspn (charsetstr, " \t\n");
953
954                     charset = (char *) alloca (len + 1);
955 # if defined _LIBC || HAVE_MEMPCPY
956                     *((char *) mempcpy (charset, charsetstr, len)) = '\0';
957 # else
958                     memcpy (charset, charsetstr, len);
959                     charset[len] = '\0';
960 # endif
961
962                     outcharset = encoding;
963
964 # ifdef _LIBC
965                     /* We always want to use transliteration.  */
966                     outcharset = norm_add_slashes (outcharset, "TRANSLIT");
967                     charset = norm_add_slashes (charset, "");
968                     int r = __gconv_open (outcharset, charset, &convd->conv,
969                                           GCONV_AVOID_NOCONV);
970                     if (__builtin_expect (r != __GCONV_OK, 0))
971                       {
972                         /* If the output encoding is the same there is
973                            nothing to do.  Otherwise do not use the
974                            translation at all.  */
975                         if (__builtin_expect (r != __GCONV_NULCONV, 1))
976                           {
977                             __libc_rwlock_unlock (domain->conversions_lock);
978                             free ((char *) encoding);
979                             return NULL;
980                           }
981
982                         convd->conv = (__gconv_t) -1;
983                       }
984 # else
985 #  if HAVE_ICONV
986                     /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
987                        we want to use transliteration.  */
988 #   if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
989        || _LIBICONV_VERSION >= 0x0105
990                     if (strchr (outcharset, '/') == NULL)
991                       {
992                         char *tmp;
993
994                         len = strlen (outcharset);
995                         tmp = (char *) alloca (len + 10 + 1);
996                         memcpy (tmp, outcharset, len);
997                         memcpy (tmp + len, "//TRANSLIT", 10 + 1);
998                         outcharset = tmp;
999
1000                         convd->conv = iconv_open (outcharset, charset);
1001
1002                         freea (outcharset);
1003                       }
1004                     else
1005 #   endif
1006                       convd->conv = iconv_open (outcharset, charset);
1007 #  endif
1008 # endif
1009
1010                     freea (charset);
1011                   }
1012               }
1013           }
1014           convd->conv_tab = NULL;
1015           /* Here domain->conversions is still == new_conversions.  */
1016           domain->nconversions++;
1017
1018         found_convd:
1019           __libc_rwlock_unlock (domain->conversions_lock);
1020         }
1021
1022       if (
1023 # ifdef _LIBC
1024           convd->conv != (__gconv_t) -1
1025 # else
1026 #  if HAVE_ICONV
1027           convd->conv != (iconv_t) -1
1028 #  endif
1029 # endif
1030           )
1031         {
1032           /* We are supposed to do a conversion.  First allocate an
1033              appropriate table with the same structure as the table
1034              of translations in the file, where we can put the pointers
1035              to the converted strings in.
1036              There is a slight complication with plural entries.  They
1037              are represented by consecutive NUL terminated strings.  We
1038              handle this case by converting RESULTLEN bytes, including
1039              NULs.  */
1040
1041           if (convd->conv_tab == NULL
1042               && ((convd->conv_tab =
1043                     (char **) calloc (nstrings + domain->n_sysdep_strings,
1044                                       sizeof (char *)))
1045                   == NULL))
1046             /* Mark that we didn't succeed allocating a table.  */
1047             convd->conv_tab = (char **) -1;
1048
1049           if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
1050             /* Nothing we can do, no more memory.  We cannot use the
1051                translation because it might be encoded incorrectly.  */
1052             return (char *) -1;
1053
1054           if (convd->conv_tab[act] == NULL)
1055             {
1056               /* We haven't used this string so far, so it is not
1057                  translated yet.  Do this now.  */
1058               /* We use a bit more efficient memory handling.
1059                  We allocate always larger blocks which get used over
1060                  time.  This is faster than many small allocations.   */
1061               __libc_lock_define_initialized (static, lock)
1062 # define INITIAL_BLOCK_SIZE     4080
1063               static unsigned char *freemem;
1064               static size_t freemem_size;
1065
1066               const unsigned char *inbuf;
1067               unsigned char *outbuf;
1068               int malloc_count;
1069 # ifndef _LIBC
1070               transmem_block_t *transmem_list = NULL;
1071 # endif
1072
1073               __libc_lock_lock (lock);
1074
1075               inbuf = (const unsigned char *) result;
1076               outbuf = freemem + sizeof (size_t);
1077
1078               malloc_count = 0;
1079               while (1)
1080                 {
1081                   transmem_block_t *newmem;
1082 # ifdef _LIBC
1083                   size_t non_reversible;
1084                   int res;
1085
1086                   if (freemem_size < sizeof (size_t))
1087                     goto resize_freemem;
1088
1089                   res = __gconv (convd->conv,
1090                                  &inbuf, inbuf + resultlen,
1091                                  &outbuf,
1092                                  outbuf + freemem_size - sizeof (size_t),
1093                                  &non_reversible);
1094
1095                   if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
1096                     break;
1097
1098                   if (res != __GCONV_FULL_OUTPUT)
1099                     {
1100                       /* We should not use the translation at all, it
1101                          is incorrectly encoded.  */
1102                       __libc_lock_unlock (lock);
1103                       return NULL;
1104                     }
1105
1106                   inbuf = (const unsigned char *) result;
1107 # else
1108 #  if HAVE_ICONV
1109                   const char *inptr = (const char *) inbuf;
1110                   size_t inleft = resultlen;
1111                   char *outptr = (char *) outbuf;
1112                   size_t outleft;
1113
1114                   if (freemem_size < sizeof (size_t))
1115                     goto resize_freemem;
1116
1117                   outleft = freemem_size - sizeof (size_t);
1118                   if (iconv (convd->conv,
1119                              (ICONV_CONST char **) &inptr, &inleft,
1120                              &outptr, &outleft)
1121                       != (size_t) (-1))
1122                     {
1123                       outbuf = (unsigned char *) outptr;
1124                       break;
1125                     }
1126                   if (errno != E2BIG)
1127                     {
1128                       __libc_lock_unlock (lock);
1129                       return NULL;
1130                     }
1131 #  endif
1132 # endif
1133
1134                 resize_freemem:
1135                   /* We must allocate a new buffer or resize the old one.  */
1136                   if (malloc_count > 0)
1137                     {
1138                       ++malloc_count;
1139                       freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
1140                       newmem = (transmem_block_t *) realloc (transmem_list,
1141                                                              freemem_size);
1142 # ifdef _LIBC
1143                       if (newmem != NULL)
1144                         transmem_list = transmem_list->next;
1145                       else
1146                         {
1147                           struct transmem_list *old = transmem_list;
1148
1149                           transmem_list = transmem_list->next;
1150                           free (old);
1151                         }
1152 # endif
1153                     }
1154                   else
1155                     {
1156                       malloc_count = 1;
1157                       freemem_size = INITIAL_BLOCK_SIZE;
1158                       newmem = (transmem_block_t *) malloc (freemem_size);
1159                     }
1160                   if (__builtin_expect (newmem == NULL, 0))
1161                     {
1162                       freemem = NULL;
1163                       freemem_size = 0;
1164                       __libc_lock_unlock (lock);
1165                       return (char *) -1;
1166                     }
1167
1168 # ifdef _LIBC
1169                   /* Add the block to the list of blocks we have to free
1170                      at some point.  */
1171                   newmem->next = transmem_list;
1172                   transmem_list = newmem;
1173
1174                   freemem = (unsigned char *) newmem->data;
1175                   freemem_size -= offsetof (struct transmem_list, data);
1176 # else
1177                   transmem_list = newmem;
1178                   freemem = newmem;
1179 # endif
1180
1181                   outbuf = freemem + sizeof (size_t);
1182                 }
1183
1184               /* We have now in our buffer a converted string.  Put this
1185                  into the table of conversions.  */
1186               *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
1187               convd->conv_tab[act] = (char *) freemem;
1188               /* Shrink freemem, but keep it aligned.  */
1189               freemem_size -= outbuf - freemem;
1190               freemem = outbuf;
1191               freemem += freemem_size & (alignof (size_t) - 1);
1192               freemem_size = freemem_size & ~ (alignof (size_t) - 1);
1193
1194               __libc_lock_unlock (lock);
1195             }
1196
1197           /* Now convd->conv_tab[act] contains the translation of all
1198              the plural variants.  */
1199           result = convd->conv_tab[act] + sizeof (size_t);
1200           resultlen = *(size_t *) convd->conv_tab[act];
1201         }
1202     }
1203
1204   /* The result string is converted.  */
1205
1206 #endif /* _LIBC || HAVE_ICONV */
1207
1208   *lengthp = resultlen;
1209   return result;
1210 }
1211
1212
1213 /* Look up a plural variant.  */
1214 static char *
1215 internal_function
1216 plural_lookup (domain, n, translation, translation_len)
1217      struct loaded_l10nfile *domain;
1218      unsigned long int n;
1219      const char *translation;
1220      size_t translation_len;
1221 {
1222   struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
1223   unsigned long int index;
1224   const char *p;
1225
1226   index = plural_eval (domaindata->plural, n);
1227   if (index >= domaindata->nplurals)
1228     /* This should never happen.  It means the plural expression and the
1229        given maximum value do not match.  */
1230     index = 0;
1231
1232   /* Skip INDEX strings at TRANSLATION.  */
1233   p = translation;
1234   while (index-- > 0)
1235     {
1236 #ifdef _LIBC
1237       p = __rawmemchr (p, '\0');
1238 #else
1239       p = strchr (p, '\0');
1240 #endif
1241       /* And skip over the NUL byte.  */
1242       p++;
1243
1244       if (p >= translation + translation_len)
1245         /* This should never happen.  It means the plural expression
1246            evaluated to a value larger than the number of variants
1247            available for MSGID1.  */
1248         return (char *) translation;
1249     }
1250   return (char *) p;
1251 }
1252
1253 #ifndef _LIBC
1254 /* Return string representation of locale CATEGORY.  */
1255 static const char *
1256 internal_function
1257 category_to_name (category)
1258      int category;
1259 {
1260   const char *retval;
1261
1262   switch (category)
1263   {
1264 #ifdef LC_COLLATE
1265   case LC_COLLATE:
1266     retval = "LC_COLLATE";
1267     break;
1268 #endif
1269 #ifdef LC_CTYPE
1270   case LC_CTYPE:
1271     retval = "LC_CTYPE";
1272     break;
1273 #endif
1274 #ifdef LC_MONETARY
1275   case LC_MONETARY:
1276     retval = "LC_MONETARY";
1277     break;
1278 #endif
1279 #ifdef LC_NUMERIC
1280   case LC_NUMERIC:
1281     retval = "LC_NUMERIC";
1282     break;
1283 #endif
1284 #ifdef LC_TIME
1285   case LC_TIME:
1286     retval = "LC_TIME";
1287     break;
1288 #endif
1289 #ifdef LC_MESSAGES
1290   case LC_MESSAGES:
1291     retval = "LC_MESSAGES";
1292     break;
1293 #endif
1294 #ifdef LC_RESPONSE
1295   case LC_RESPONSE:
1296     retval = "LC_RESPONSE";
1297     break;
1298 #endif
1299 #ifdef LC_ALL
1300   case LC_ALL:
1301     /* This might not make sense but is perhaps better than any other
1302        value.  */
1303     retval = "LC_ALL";
1304     break;
1305 #endif
1306   default:
1307     /* If you have a better idea for a default value let me know.  */
1308     retval = "LC_XXX";
1309   }
1310
1311   return retval;
1312 }
1313 #endif
1314
1315 /* Guess value of current locale from value of the environment variables.  */
1316 static const char *
1317 internal_function
1318 guess_category_value (category, categoryname)
1319      int category;
1320      const char *categoryname;
1321 {
1322   const char *language;
1323   const char *retval;
1324
1325   /* The highest priority value is the `LANGUAGE' environment
1326      variable.  But we don't use the value if the currently selected
1327      locale is the C locale.  This is a GNU extension.  */
1328   language = getenv ("LANGUAGE");
1329   if (language != NULL && language[0] == '\0')
1330     language = NULL;
1331
1332   /* We have to proceed with the POSIX methods of looking to `LC_ALL',
1333      `LC_xxx', and `LANG'.  On some systems this can be done by the
1334      `setlocale' function itself.  */
1335 #ifdef _LIBC
1336   retval = __current_locale_name (category);
1337 #else
1338   retval = _nl_locale_name (category, categoryname);
1339 #endif
1340
1341   return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
1342 }
1343
1344 #if defined _LIBC || HAVE_ICONV
1345 /* Returns the output charset.  */
1346 static const char *
1347 internal_function
1348 get_output_charset (domainbinding)
1349      struct binding *domainbinding;
1350 {
1351   /* The output charset should normally be determined by the locale.  But
1352      sometimes the locale is not used or not correctly set up, so we provide
1353      a possibility for the user to override this: the OUTPUT_CHARSET
1354      environment variable.  Moreover, the value specified through
1355      bind_textdomain_codeset overrides both.  */
1356   if (domainbinding != NULL && domainbinding->codeset != NULL)
1357     return domainbinding->codeset;
1358   else
1359     {
1360       /* For speed reasons, we look at the value of OUTPUT_CHARSET only
1361          once.  This is a user variable that is not supposed to change
1362          during a program run.  */
1363       static char *output_charset_cache;
1364       static int output_charset_cached;
1365
1366       if (!output_charset_cached)
1367         {
1368           const char *value = getenv ("OUTPUT_CHARSET");
1369
1370           if (value != NULL && value[0] != '\0')
1371             {
1372               size_t len = strlen (value) + 1;
1373               char *value_copy = (char *) malloc (len);
1374
1375               if (value_copy != NULL)
1376                 memcpy (value_copy, value, len);
1377               output_charset_cache = value_copy;
1378             }
1379           output_charset_cached = 1;
1380         }
1381
1382       if (output_charset_cache != NULL)
1383         return output_charset_cache;
1384       else
1385         {
1386 # ifdef _LIBC
1387           return _NL_CURRENT (LC_CTYPE, CODESET);
1388 # else
1389 #  if HAVE_ICONV
1390           extern const char *locale_charset PARAMS ((void);
1391           return locale_charset ();
1392 #  endif
1393 # endif
1394         }
1395     }
1396 }
1397 #endif
1398
1399 /* @@ begin of epilog @@ */
1400
1401 /* We don't want libintl.a to depend on any other library.  So we
1402    avoid the non-standard function stpcpy.  In GNU C Library this
1403    function is available, though.  Also allow the symbol HAVE_STPCPY
1404    to be defined.  */
1405 #if !_LIBC && !HAVE_STPCPY
1406 static char *
1407 stpcpy (dest, src)
1408      char *dest;
1409      const char *src;
1410 {
1411   while ((*dest++ = *src++) != '\0')
1412     /* Do nothing. */ ;
1413   return dest - 1;
1414 }
1415 #endif
1416
1417 #if !_LIBC && !HAVE_MEMPCPY
1418 static void *
1419 mempcpy (dest, src, n)
1420      void *dest;
1421      const void *src;
1422      size_t n;
1423 {
1424   return (void *) ((char *) memcpy (dest, src, n) + n);
1425 }
1426 #endif
1427
1428
1429 #ifdef _LIBC
1430 /* If we want to free all resources we have to do some work at
1431    program's end.  */
1432 libc_freeres_fn (free_mem)
1433 {
1434   void *old;
1435
1436   while (_nl_domain_bindings != NULL)
1437     {
1438       struct binding *oldp = _nl_domain_bindings;
1439       _nl_domain_bindings = _nl_domain_bindings->next;
1440       if (oldp->dirname != _nl_default_dirname)
1441         /* Yes, this is a pointer comparison.  */
1442         free (oldp->dirname);
1443       free (oldp->codeset);
1444       free (oldp);
1445     }
1446
1447   if (_nl_current_default_domain != _nl_default_default_domain)
1448     /* Yes, again a pointer comparison.  */
1449     free ((char *) _nl_current_default_domain);
1450
1451   /* Remove the search tree with the known translations.  */
1452   __tdestroy (root, free);
1453   root = NULL;
1454
1455   while (transmem_list != NULL)
1456     {
1457       old = transmem_list;
1458       transmem_list = transmem_list->next;
1459       free (old);
1460     }
1461 }
1462 #endif