Update.
[glibc.git] / intl / dcigettext.c
blobdd3a559f58d423d851a94aeae7fb0fbff013f2cd
1 /* Implementation of the internal dcigettext function.
2 Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
19 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
20 This must come before <config.h> because <config.h> may include
21 <features.h>, and once <features.h> has been included, it's too late. */
22 #ifndef _GNU_SOURCE
23 # define _GNU_SOURCE 1
24 #endif
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
30 #include <sys/types.h>
32 #if defined __GNUC__ && !defined C_ALLOCA
33 # define alloca __builtin_alloca
34 # define HAVE_ALLOCA 1
35 #else
36 # if (defined HAVE_ALLOCA_H || defined _LIBC) && !defined C_ALLOCA
37 # include <alloca.h>
38 # else
39 # ifdef _AIX
40 #pragma alloca
41 # else
42 # ifndef alloca
43 char *alloca ();
44 # endif
45 # endif
46 # endif
47 #endif
49 #include <errno.h>
50 #ifndef errno
51 extern int errno;
52 #endif
53 #ifndef __set_errno
54 # define __set_errno(val) errno = (val)
55 #endif
57 #if defined STDC_HEADERS || defined _LIBC
58 # include <stddef.h>
59 # include <stdlib.h>
60 #else
61 char *getenv ();
62 # ifdef HAVE_MALLOC_H
63 # include <malloc.h>
64 # else
65 void free ();
66 # endif
67 #endif
69 #if defined HAVE_STRING_H || defined _LIBC
70 # include <string.h>
71 #else
72 # include <strings.h>
73 #endif
74 #if !HAVE_STRCHR && !defined _LIBC
75 # ifndef strchr
76 # define strchr index
77 # endif
78 #endif
80 #if defined HAVE_UNISTD_H || defined _LIBC
81 # include <unistd.h>
82 #endif
84 #if defined HAVE_LOCALE_H || defined _LIBC
85 # include <locale.h>
86 #endif
88 #if defined HAVE_SYS_PARAM_H || defined _LIBC
89 # include <sys/param.h>
90 #endif
92 #include "gettext.h"
93 #include "gettextP.h"
94 #ifdef _LIBC
95 # include <libintl.h>
96 #else
97 # include "libgettext.h"
98 #endif
99 #include "hash-string.h"
101 /* Thread safetyness. */
102 #ifdef _LIBC
103 # include <bits/libc-lock.h>
104 #else
105 /* Provide dummy implementation if this is outside glibc. */
106 # define __libc_lock_define_initialized(CLASS, NAME)
107 # define __libc_lock_lock(NAME)
108 # define __libc_lock_unlock(NAME)
109 # define __libc_rwlock_define_initialized(CLASS, NAME)
110 # define __libc_rwlock_rdlock(NAME)
111 # define __libc_rwlock_unlock(NAME)
112 #endif
114 /* Alignment of types. */
115 #if defined __GNUC__ && __GNUC__ >= 2
116 # define alignof(TYPE) __alignof__ (TYPE)
117 #else
118 # define alignof(TYPE) \
119 ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
120 #endif
122 /* The internal variables in the standalone libintl.a must have different
123 names than the internal variables in GNU libc, otherwise programs
124 using libintl.a cannot be linked statically. */
125 #if !defined _LIBC
126 # define _nl_default_default_domain _nl_default_default_domain__
127 # define _nl_current_default_domain _nl_current_default_domain__
128 # define _nl_default_dirname _nl_default_dirname__
129 # define _nl_domain_bindings _nl_domain_bindings__
130 #endif
132 /* @@ end of prolog @@ */
134 #ifdef _LIBC
135 /* Rename the non ANSI C functions. This is required by the standard
136 because some ANSI C functions will require linking with this object
137 file and the name space must not be polluted. */
138 # define getcwd __getcwd
139 # ifndef stpcpy
140 # define stpcpy __stpcpy
141 # endif
142 # define tfind __tfind
143 #else
144 # if !defined HAVE_GETCWD
145 char *getwd ();
146 # define getcwd(buf, max) getwd (buf)
147 # else
148 char *getcwd ();
149 # endif
150 # ifndef HAVE_STPCPY
151 static char *stpcpy PARAMS ((char *dest, const char *src));
152 # endif
153 # ifndef HAVE_MEMPCPY
154 static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
155 # endif
156 #endif
158 /* Amount to increase buffer size by in each try. */
159 #define PATH_INCR 32
161 /* The following is from pathmax.h. */
162 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
163 PATH_MAX but might cause redefinition warnings when sys/param.h is
164 later included (as on MORE/BSD 4.3). */
165 #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
166 # include <limits.h>
167 #endif
169 #ifndef _POSIX_PATH_MAX
170 # define _POSIX_PATH_MAX 255
171 #endif
173 #if !defined PATH_MAX && defined _PC_PATH_MAX
174 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
175 #endif
177 /* Don't include sys/param.h if it already has been. */
178 #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
179 # include <sys/param.h>
180 #endif
182 #if !defined PATH_MAX && defined MAXPATHLEN
183 # define PATH_MAX MAXPATHLEN
184 #endif
186 #ifndef PATH_MAX
187 # define PATH_MAX _POSIX_PATH_MAX
188 #endif
190 /* XPG3 defines the result of `setlocale (category, NULL)' as:
191 ``Directs `setlocale()' to query `category' and return the current
192 setting of `local'.''
193 However it does not specify the exact format. And even worse: POSIX
194 defines this not at all. So we can use this feature only on selected
195 system (e.g. those using GNU C Library). */
196 #ifdef _LIBC
197 # define HAVE_LOCALE_NULL
198 #endif
200 /* We want to allocate a string at the end of the struct. gcc makes
201 this easy. */
202 #ifdef __GNUC__
203 # define ZERO 0
204 #else
205 # define ZERO 1
206 #endif
208 /* This is the type used for the search tree where known translations
209 are stored. */
210 struct known_translation_t
212 /* Domain in which to search. */
213 char *domain;
215 /* Plural index. */
216 unsigned long int plindex;
218 /* The category. */
219 int category;
221 /* State of the catalog counter at the point the string was found. */
222 int counter;
224 /* And finally the translation. */
225 const char *translation;
227 /* Pointer to the string in question. */
228 char msgid[ZERO];
231 /* Root of the search tree with known translations. We can use this
232 only if the system provides the `tsearch' function family. */
233 #if defined HAVE_TSEARCH || defined _LIBC
234 # include <search.h>
236 static void *root;
238 # ifdef _LIBC
239 # define tsearch __tsearch
240 # endif
242 /* Function to compare two entries in the table of known translations. */
243 static int
244 transcmp (const void *p1, const void *p2)
246 const struct known_translation_t *s1;
247 const struct known_translation_t *s2;
248 int result;
250 s1 = (const struct known_translation_t *) p1;
251 s2 = (const struct known_translation_t *) p2;
253 result = strcmp (s1->msgid, s2->msgid);
254 if (result == 0)
256 result = strcmp (s1->domain, s2->domain);
257 if (result == 0)
259 result = s1->plindex - s2->plindex;
260 if (result == 0)
261 /* We compare the category last (though this is the cheapest
262 operation) since it is hopefully always the same (namely
263 LC_MESSAGES). */
264 result = s1->category - s2->category;
268 return result;
270 #endif
272 /* Name of the default domain used for gettext(3) prior any call to
273 textdomain(3). The default value for this is "messages". */
274 const char _nl_default_default_domain[] = "messages";
276 /* Value used as the default domain for gettext(3). */
277 const char *_nl_current_default_domain = _nl_default_default_domain;
279 /* Contains the default location of the message catalogs. */
280 const char _nl_default_dirname[] = GNULOCALEDIR;
282 /* List with bindings of specific domains created by bindtextdomain()
283 calls. */
284 struct binding *_nl_domain_bindings;
286 /* Prototypes for local functions. */
287 static unsigned long int plural_eval (struct expression *pexp,
288 unsigned long int n) internal_function;
289 static const char *category_to_name PARAMS ((int category)) internal_function;
290 static const char *guess_category_value PARAMS ((int category,
291 const char *categoryname))
292 internal_function;
295 /* For those loosing systems which don't have `alloca' we have to add
296 some additional code emulating it. */
297 #ifdef HAVE_ALLOCA
298 /* Nothing has to be done. */
299 # define ADD_BLOCK(list, address) /* nothing */
300 # define FREE_BLOCKS(list) /* nothing */
301 #else
302 struct block_list
304 void *address;
305 struct block_list *next;
307 # define ADD_BLOCK(list, addr) \
308 do { \
309 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
310 /* If we cannot get a free block we cannot add the new element to \
311 the list. */ \
312 if (newp != NULL) { \
313 newp->address = (addr); \
314 newp->next = (list); \
315 (list) = newp; \
317 } while (0)
318 # define FREE_BLOCKS(list) \
319 do { \
320 while (list != NULL) { \
321 struct block_list *old = list; \
322 list = list->next; \
323 free (old); \
325 } while (0)
326 # undef alloca
327 # define alloca(size) (malloc (size))
328 #endif /* have alloca */
331 /* List of blocks allocated for translations. */
332 static struct transmem_list
334 struct transmem_list *next;
335 char data[0];
336 } *transmem_list;
339 /* Names for the libintl functions are a problem. They must not clash
340 with existing names and they should follow ANSI C. But this source
341 code is also used in GNU C Library where the names have a __
342 prefix. So we have to make a difference here. */
343 #ifdef _LIBC
344 # define DCIGETTEXT __dcigettext
345 #else
346 # define DCIGETTEXT dcigettext__
347 #endif
349 /* Lock variable to protect the global data in the gettext implementation. */
350 __libc_rwlock_define_initialized (, _nl_state_lock)
352 /* Checking whether the binaries runs SUID must be done and glibc provides
353 easier methods therefore we make a difference here. */
354 #ifdef _LIBC
355 # define ENABLE_SECURE __libc_enable_secure
356 # define DETERMINE_SECURE
357 #else
358 static int enable_secure;
359 # define ENABLE_SECURE (enable_secure == 1)
360 # define DETERMINE_SECURE \
361 if (enable_secure == 0) \
363 if (getuid () != geteuid () || getgid () != getegid ()) \
364 enable_secure = 1; \
365 else \
366 enable_secure = -1; \
368 #endif
370 /* Look up MSGID in the DOMAINNAME message catalog for the current
371 CATEGORY locale and, if PLURAL is nonzero, search over string
372 depending on the plural form determined by N. */
373 char *
374 DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
375 const char *domainname;
376 const char *msgid1;
377 const char *msgid2;
378 int plural;
379 unsigned long int n;
380 int category;
382 #ifndef HAVE_ALLOCA
383 struct block_list *block_list = NULL;
384 #endif
385 struct loaded_l10nfile *domain;
386 struct binding *binding;
387 const char *categoryname;
388 const char *categoryvalue;
389 char *dirname, *xdomainname;
390 char *single_locale;
391 char *retval;
392 int saved_errno;
393 #if defined HAVE_TSEARCH || defined _LIBC
394 struct known_translation_t *search;
395 struct known_translation_t **foundp = NULL;
396 size_t msgid_len;
397 #endif
398 size_t domainname_len;
400 /* If no real MSGID is given return NULL. */
401 if (msgid1 == NULL)
402 return NULL;
404 __libc_rwlock_rdlock (_nl_state_lock);
406 /* If DOMAINNAME is NULL, we are interested in the default domain. If
407 CATEGORY is not LC_MESSAGES this might not make much sense but the
408 definition left this undefined. */
409 if (domainname == NULL)
410 domainname = _nl_current_default_domain;
412 #if defined HAVE_TSEARCH || defined _LIBC
413 msgid_len = strlen (msgid1) + 1;
415 if (plural == 0)
417 /* Try to find the translation among those which we found at
418 some time. */
419 search = (struct known_translation_t *) alloca (sizeof (*search)
420 + msgid_len);
421 memcpy (search->msgid, msgid1, msgid_len);
422 search->domain = (char *) domainname;
423 search->plindex = 0;
424 search->category = category;
426 foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
427 if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
429 __libc_rwlock_unlock (_nl_state_lock);
430 return (char *) (*foundp)->translation;
433 #endif
435 /* Preserve the `errno' value. */
436 saved_errno = errno;
438 /* See whether this is a SUID binary or not. */
439 DETERMINE_SECURE;
441 /* First find matching binding. */
442 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
444 int compare = strcmp (domainname, binding->domainname);
445 if (compare == 0)
446 /* We found it! */
447 break;
448 if (compare < 0)
450 /* It is not in the list. */
451 binding = NULL;
452 break;
456 if (binding == NULL)
457 dirname = (char *) _nl_default_dirname;
458 else if (binding->dirname[0] == '/')
459 dirname = binding->dirname;
460 else
462 /* We have a relative path. Make it absolute now. */
463 size_t dirname_len = strlen (binding->dirname) + 1;
464 size_t path_max;
465 char *ret;
467 path_max = (unsigned int) PATH_MAX;
468 path_max += 2; /* The getcwd docs say to do this. */
470 dirname = (char *) alloca (path_max + dirname_len);
471 ADD_BLOCK (block_list, dirname);
473 __set_errno (0);
474 while ((ret = getcwd (dirname, path_max)) == NULL && errno == ERANGE)
476 path_max += PATH_INCR;
477 dirname = (char *) alloca (path_max + dirname_len);
478 ADD_BLOCK (block_list, dirname);
479 __set_errno (0);
482 if (ret == NULL)
484 /* We cannot get the current working directory. Don't signal an
485 error but simply return the default string. */
486 FREE_BLOCKS (block_list);
487 __set_errno (saved_errno);
488 return (plural == 0
489 ? (char *) msgid1
490 /* Use the Germanic plural rule. */
491 : n == 1 ? (char *) msgid1 : (char *) msgid2);
494 stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
497 /* Now determine the symbolic name of CATEGORY and its value. */
498 categoryname = category_to_name (category);
499 categoryvalue = guess_category_value (category, categoryname);
501 domainname_len = strlen (domainname);
502 xdomainname = (char *) alloca (strlen (categoryname)
503 + domainname_len + 5);
504 ADD_BLOCK (block_list, xdomainname);
506 stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
507 domainname, domainname_len),
508 ".mo");
510 /* Creating working area. */
511 single_locale = (char *) alloca (strlen (categoryvalue) + 1);
512 ADD_BLOCK (block_list, single_locale);
515 /* Search for the given string. This is a loop because we perhaps
516 got an ordered list of languages to consider for the translation. */
517 while (1)
519 /* Make CATEGORYVALUE point to the next element of the list. */
520 while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
521 ++categoryvalue;
522 if (categoryvalue[0] == '\0')
524 /* The whole contents of CATEGORYVALUE has been searched but
525 no valid entry has been found. We solve this situation
526 by implicitly appending a "C" entry, i.e. no translation
527 will take place. */
528 single_locale[0] = 'C';
529 single_locale[1] = '\0';
531 else
533 char *cp = single_locale;
534 while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
535 *cp++ = *categoryvalue++;
536 *cp = '\0';
538 /* When this is a SUID binary we must not allow accessing files
539 outside the dedicated directories. */
540 if (ENABLE_SECURE && strchr (single_locale, '/') != NULL)
541 /* Ingore this entry. */
542 continue;
545 /* If the current locale value is C (or POSIX) we don't load a
546 domain. Return the MSGID. */
547 if (strcmp (single_locale, "C") == 0
548 || strcmp (single_locale, "POSIX") == 0)
550 FREE_BLOCKS (block_list);
551 __libc_rwlock_unlock (_nl_state_lock);
552 __set_errno (saved_errno);
553 return (plural == 0
554 ? (char *) msgid1
555 /* Use the Germanic plural rule. */
556 : n == 1 ? (char *) msgid1 : (char *) msgid2);
560 /* Find structure describing the message catalog matching the
561 DOMAINNAME and CATEGORY. */
562 domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
564 if (domain != NULL)
566 unsigned long int index = 0;
568 if (plural != 0)
570 const struct loaded_domain *domaindata =
571 (const struct loaded_domain *) domain->data;
572 index = plural_eval (domaindata->plural, n);
573 if (index >= domaindata->nplurals)
574 /* This should never happen. It means the plural expression
575 and the given maximum value do not match. */
576 index = 0;
578 #if defined HAVE_TSEARCH || defined _LIBC
579 /* Try to find the translation among those which we
580 found at some time. */
581 search = (struct known_translation_t *) alloca (sizeof (*search)
582 + msgid_len);
583 memcpy (search->msgid, msgid1, msgid_len);
584 search->domain = (char *) domainname;
585 search->plindex = index;
586 search->category = category;
588 foundp = (struct known_translation_t **) tfind (search, &root,
589 transcmp);
590 if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
592 __libc_rwlock_unlock (_nl_state_lock);
593 return (char *) (*foundp)->translation;
595 #endif
598 retval = _nl_find_msg (domain, msgid1, index);
600 if (retval == NULL)
602 int cnt;
604 for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
606 retval = _nl_find_msg (domain->successor[cnt], msgid1,
607 index);
609 if (retval != NULL)
610 break;
614 if (retval != NULL)
616 FREE_BLOCKS (block_list);
617 __set_errno (saved_errno);
618 #if defined HAVE_TSEARCH || defined _LIBC
619 if (foundp == NULL)
621 /* Create a new entry and add it to the search tree. */
622 struct known_translation_t *newp;
624 newp = (struct known_translation_t *)
625 malloc (sizeof (*newp) + msgid_len
626 + domainname_len + 1 - ZERO);
627 if (newp != NULL)
629 newp->domain = mempcpy (newp->msgid, msgid1, msgid_len);
630 memcpy (newp->domain, domainname, domainname_len + 1);
631 newp->plindex = index;
632 newp->category = category;
633 newp->counter = _nl_msg_cat_cntr;
634 newp->translation = retval;
636 /* Insert the entry in the search tree. */
637 foundp = (struct known_translation_t **)
638 tsearch (newp, &root, transcmp);
639 if (foundp == NULL
640 || __builtin_expect (*foundp != newp, 0))
641 /* The insert failed. */
642 free (newp);
645 else
647 /* We can update the existing entry. */
648 (*foundp)->counter = _nl_msg_cat_cntr;
649 (*foundp)->translation = retval;
651 #endif
652 __libc_rwlock_unlock (_nl_state_lock);
653 return retval;
657 /* NOTREACHED */
661 char *
662 internal_function
663 _nl_find_msg (domain_file, msgid, index)
664 struct loaded_l10nfile *domain_file;
665 const char *msgid;
666 unsigned long int index;
668 const struct loaded_domain *domain;
669 size_t act;
670 char *result;
672 if (domain_file->decided == 0)
673 _nl_load_domain (domain_file);
675 if (domain_file->data == NULL)
676 return NULL;
678 domain = (const struct loaded_domain *) domain_file->data;
680 /* Locate the MSGID and its translation. */
681 if (domain->hash_size > 2 && domain->hash_tab != NULL)
683 /* Use the hashing table. */
684 nls_uint32 len = strlen (msgid);
685 nls_uint32 hash_val = hash_string (msgid);
686 nls_uint32 idx = hash_val % domain->hash_size;
687 nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
688 nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
690 if (nstr == 0)
691 /* Hash table entry is empty. */
692 return NULL;
694 if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
695 && strcmp (msgid,
696 domain->data + W (domain->must_swap,
697 domain->orig_tab[nstr - 1].offset)) == 0)
699 act = nstr - 1;
700 goto found;
703 while (1)
705 if (idx >= domain->hash_size - incr)
706 idx -= domain->hash_size - incr;
707 else
708 idx += incr;
710 nstr = W (domain->must_swap, domain->hash_tab[idx]);
711 if (nstr == 0)
712 /* Hash table entry is empty. */
713 return NULL;
715 if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
716 && (strcmp (msgid,
717 domain->data + W (domain->must_swap,
718 domain->orig_tab[nstr - 1].offset))
719 == 0))
721 act = nstr - 1;
722 goto found;
725 /* NOTREACHED */
727 else
729 /* Try the default method: binary search in the sorted array of
730 messages. */
731 size_t top, bottom;
733 bottom = 0;
734 top = domain->nstrings;
735 while (bottom < top)
737 int cmp_val;
739 act = (bottom + top) / 2;
740 cmp_val = strcmp (msgid, (domain->data
741 + W (domain->must_swap,
742 domain->orig_tab[act].offset)));
743 if (cmp_val < 0)
744 top = act;
745 else if (cmp_val > 0)
746 bottom = act + 1;
747 else
748 goto found;
750 /* No translation was found. */
751 return NULL;
754 found:
755 /* The translation was found at index ACT. If we have to convert the
756 string to use a different character set, this is the time. */
757 result = ((char *) domain->data
758 + W (domain->must_swap, domain->trans_tab[act].offset));
760 #if defined _LIBC || HAVE_ICONV
761 if (
762 # ifdef _LIBC
763 domain->conv != (__gconv_t) -1
764 # else
765 # if HAVE_ICONV
766 domain->conv != (iconv_t) -1
767 # endif
768 # endif
771 /* We are supposed to do a conversion. First allocate an
772 appropriate table with the same structure as the table
773 of translations in the file, where we can put the pointers
774 to the converted strings in.
775 There is a slight complication with the INDEX: We don't know
776 a priori which entries are plural entries. Therefore at any
777 moment we can only translate the variants 0 .. INDEX. */
779 if (domain->conv_tab == NULL
780 && ((domain->conv_tab = (char **) calloc (domain->nstrings,
781 sizeof (char *)))
782 == NULL))
783 /* Mark that we didn't succeed allocating a table. */
784 domain->conv_tab = (char **) -1;
786 if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
787 /* Nothing we can do, no more memory. */
788 goto converted;
790 if (domain->conv_tab[act] == NULL
791 || *(nls_uint32 *) domain->conv_tab[act] < index)
793 /* We haven't used this string so far, so it is not
794 translated yet. Do this now. */
795 /* We use a bit more efficient memory handling.
796 We allocate always larger blocks which get used over
797 time. This is faster than many small allocations. */
798 __libc_lock_define_initialized (static, lock)
799 #define INITIAL_BLOCK_SIZE 4080
800 static unsigned char *freemem;
801 static size_t freemem_size;
803 size_t resultlen;
804 const unsigned char *inbuf;
805 unsigned char *outbuf;
806 int malloc_count;
808 /* Note that we translate (index + 1) consecutive strings at
809 once, including the final NUL byte. */
811 unsigned long int i = index;
812 char *p = result;
814 p += strlen (p) + 1;
815 while (i-- > 0);
816 resultlen = p - result;
819 __libc_lock_lock (lock);
821 inbuf = result;
822 outbuf = freemem + sizeof (nls_uint32);
824 malloc_count = 0;
825 while (1)
827 # ifdef _LIBC
828 struct transmem_list *newmem;
829 size_t non_reversible;
830 int res;
832 if (freemem_size < 4)
833 goto resize_freemem;
835 res = __gconv (domain->conv,
836 &inbuf, inbuf + resultlen,
837 &outbuf,
838 outbuf + freemem_size - sizeof (nls_uint32),
839 &non_reversible);
841 if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
842 break;
844 if (res != __GCONV_FULL_OUTPUT)
846 __libc_lock_unlock (lock);
847 goto converted;
850 inbuf = result;
851 # else
852 # if HAVE_ICONV
853 # define transmem freemem
854 const char *inptr = (const char *) inbuf;
855 size_t inleft = resultlen;
856 char *outptr = (char *) outbuf;
857 size_t outleft;
859 if (freemem_size < 4)
860 goto resize_freemem;
862 outleft = freemem_size - 4;
863 if (iconv (domain->conv, &inptr, &inleft, &outptr, &outleft)
864 != (size_t) (-1))
866 outbuf = (unsigned char *) outptr;
867 break;
869 if (errno != E2BIG)
871 __libc_lock_unlock (lock);
872 goto converted;
874 # else
875 # define transmem freemem
876 # endif
877 # endif
879 resize_freemem:
880 /* We must allocate a new buffer of resize the old one. */
881 if (malloc_count > 0)
883 struct transmem_list *next = transmem_list->next;
885 ++malloc_count;
886 freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
887 newmem = (struct transmem_list *) realloc (transmem_list,
888 freemem_size);
890 if (newmem != NULL)
891 transmem_list = next;
893 else
895 malloc_count = 1;
896 freemem_size = INITIAL_BLOCK_SIZE;
897 newmem = (struct transmem_list *) malloc (freemem_size);
899 if (__builtin_expect (newmem == NULL, 0))
901 freemem = NULL;
902 freemem_size = 0;
903 __libc_lock_unlock (lock);
904 goto converted;
907 # ifdef _LIBC
908 /* Add the block to the list of blocks we have to free
909 at some point. */
910 newmem->next = transmem_list;
911 transmem_list = newmem;
913 freemem = newmem->data;
914 freemem_size -= offsetof (struct transmem_list, data);
915 # endif
917 outbuf = freemem + sizeof (nls_uint32);
920 /* We have now in our buffer a converted string. Put this
921 into the table of conversions. */
922 *(nls_uint32 *) freemem = index;
923 domain->conv_tab[act] = freemem;
924 /* Shrink freemem, but keep it aligned. */
925 freemem_size -= outbuf - freemem;
926 freemem = outbuf;
927 freemem += freemem_size & (alignof (nls_uint32) - 1);
928 freemem_size = freemem_size & ~ (alignof (nls_uint32) - 1);
930 __libc_lock_unlock (lock);
933 /* Now domain->conv_tab[act] contains the translation of at least
934 the variants 0 .. INDEX. */
935 result = domain->conv_tab[act] + sizeof (nls_uint32);
938 converted:
939 /* The result string is converted. */
941 #endif /* _LIBC || HAVE_ICONV */
943 /* Now skip some strings. How much depends on the index passed in. */
944 while (index-- > 0)
946 #ifdef _LIBC
947 result = __rawmemchr (result, '\0');
948 #else
949 result = strchr (result, '\0');
950 #endif
951 /* And skip over the NUL byte. */
952 ++result;
955 return result;
959 /* Function to evaluate the plural expression and return an index value. */
960 static unsigned long int
961 internal_function
962 plural_eval (struct expression *pexp, unsigned long int n)
964 switch (pexp->operation)
966 case var:
967 return n;
968 case num:
969 return pexp->val.num;
970 case mult:
971 return (plural_eval (pexp->val.args2.left, n)
972 * plural_eval (pexp->val.args2.right, n));
973 case divide:
974 return (plural_eval (pexp->val.args2.left, n)
975 / plural_eval (pexp->val.args2.right, n));
976 case module:
977 return (plural_eval (pexp->val.args2.left, n)
978 % plural_eval (pexp->val.args2.right, n));
979 case plus:
980 return (plural_eval (pexp->val.args2.left, n)
981 + plural_eval (pexp->val.args2.right, n));
982 case minus:
983 return (plural_eval (pexp->val.args2.left, n)
984 - plural_eval (pexp->val.args2.right, n));
985 case equal:
986 return (plural_eval (pexp->val.args2.left, n)
987 == plural_eval (pexp->val.args2.right, n));
988 case not_equal:
989 return (plural_eval (pexp->val.args2.left, n)
990 != plural_eval (pexp->val.args2.right, n));
991 case land:
992 return (plural_eval (pexp->val.args2.left, n)
993 && plural_eval (pexp->val.args2.right, n));
994 case lor:
995 return (plural_eval (pexp->val.args2.left, n)
996 || plural_eval (pexp->val.args2.right, n));
997 case qmop:
998 return (plural_eval (pexp->val.args3.bexp, n)
999 ? plural_eval (pexp->val.args3.tbranch, n)
1000 : plural_eval (pexp->val.args3.fbranch, n));
1002 /* NOTREACHED */
1003 return 0;
1007 /* Return string representation of locale CATEGORY. */
1008 static const char *
1009 internal_function
1010 category_to_name (category)
1011 int category;
1013 const char *retval;
1015 switch (category)
1017 #ifdef LC_COLLATE
1018 case LC_COLLATE:
1019 retval = "LC_COLLATE";
1020 break;
1021 #endif
1022 #ifdef LC_CTYPE
1023 case LC_CTYPE:
1024 retval = "LC_CTYPE";
1025 break;
1026 #endif
1027 #ifdef LC_MONETARY
1028 case LC_MONETARY:
1029 retval = "LC_MONETARY";
1030 break;
1031 #endif
1032 #ifdef LC_NUMERIC
1033 case LC_NUMERIC:
1034 retval = "LC_NUMERIC";
1035 break;
1036 #endif
1037 #ifdef LC_TIME
1038 case LC_TIME:
1039 retval = "LC_TIME";
1040 break;
1041 #endif
1042 #ifdef LC_MESSAGES
1043 case LC_MESSAGES:
1044 retval = "LC_MESSAGES";
1045 break;
1046 #endif
1047 #ifdef LC_RESPONSE
1048 case LC_RESPONSE:
1049 retval = "LC_RESPONSE";
1050 break;
1051 #endif
1052 #ifdef LC_ALL
1053 case LC_ALL:
1054 /* This might not make sense but is perhaps better than any other
1055 value. */
1056 retval = "LC_ALL";
1057 break;
1058 #endif
1059 default:
1060 /* If you have a better idea for a default value let me know. */
1061 retval = "LC_XXX";
1064 return retval;
1067 /* Guess value of current locale from value of the environment variables. */
1068 static const char *
1069 internal_function
1070 guess_category_value (category, categoryname)
1071 int category;
1072 const char *categoryname;
1074 const char *retval;
1076 /* The highest priority value is the `LANGUAGE' environment
1077 variable. This is a GNU extension. */
1078 retval = getenv ("LANGUAGE");
1079 if (retval != NULL && retval[0] != '\0')
1080 return retval;
1082 /* `LANGUAGE' is not set. So we have to proceed with the POSIX
1083 methods of looking to `LC_ALL', `LC_xxx', and `LANG'. On some
1084 systems this can be done by the `setlocale' function itself. */
1085 #if defined _LIBC || (defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL)
1086 return setlocale (category, NULL);
1087 #else
1088 /* Setting of LC_ALL overwrites all other. */
1089 retval = getenv ("LC_ALL");
1090 if (retval != NULL && retval[0] != '\0')
1091 return retval;
1093 /* Next comes the name of the desired category. */
1094 retval = getenv (categoryname);
1095 if (retval != NULL && retval[0] != '\0')
1096 return retval;
1098 /* Last possibility is the LANG environment variable. */
1099 retval = getenv ("LANG");
1100 if (retval != NULL && retval[0] != '\0')
1101 return retval;
1103 /* We use C as the default domain. POSIX says this is implementation
1104 defined. */
1105 return "C";
1106 #endif
1109 /* @@ begin of epilog @@ */
1111 /* We don't want libintl.a to depend on any other library. So we
1112 avoid the non-standard function stpcpy. In GNU C Library this
1113 function is available, though. Also allow the symbol HAVE_STPCPY
1114 to be defined. */
1115 #if !_LIBC && !HAVE_STPCPY
1116 static char *
1117 stpcpy (dest, src)
1118 char *dest;
1119 const char *src;
1121 while ((*dest++ = *src++) != '\0')
1122 /* Do nothing. */ ;
1123 return dest - 1;
1125 #endif
1127 #if !_LIBC && !HAVE_MEMPCPY
1128 static void *
1129 mempcpy (dest, src, n)
1130 void *dest;
1131 const void *src;
1132 size_t n;
1134 return (void *) ((char *) memcpy (dest, src, n) + n);
1136 #endif
1139 #ifdef _LIBC
1140 /* If we want to free all resources we have to do some work at
1141 program's end. */
1142 static void __attribute__ ((unused))
1143 free_mem (void)
1145 void *old;
1147 while (_nl_domain_bindings != NULL)
1149 struct binding *oldp = _nl_domain_bindings;
1150 _nl_domain_bindings = _nl_domain_bindings->next;
1151 if (oldp->dirname != _nl_default_dirname)
1152 /* Yes, this is a pointer comparison. */
1153 free (oldp->dirname);
1154 free (oldp->codeset);
1155 free (oldp);
1158 if (_nl_current_default_domain != _nl_default_default_domain)
1159 /* Yes, again a pointer comparison. */
1160 free ((char *) _nl_current_default_domain);
1162 /* Remove the search tree with the known translations. */
1163 __tdestroy (root, free);
1164 root = NULL;
1166 while (transmem_list != NULL)
1168 old = transmem_list;
1169 transmem_list = transmem_list->next;
1170 free (old);
1174 text_set_element (__libc_subfreeres, free_mem);
1175 #endif