Some bug fixes and document updates.
[make.git] / gettext.c
blobb97df8dbf1846e20b9a04da7dfd01b9d0f845da2
1 /* Begin of l10nflist.c */
3 /* Handle list of needed message catalogs
4 Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
5 Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #if HAVE_CONFIG_H
22 # include <config.h>
23 #endif
25 #ifdef __GNUC__
26 # define alloca __builtin_alloca
27 # define HAVE_ALLOCA 1
28 #else
29 # if defined HAVE_ALLOCA_H || defined _LIBC
30 # include <alloca.h>
31 # else
32 # ifdef _AIX
33 #pragma alloca
34 # else
35 # ifndef alloca
36 char *alloca ();
37 # endif
38 # endif
39 # endif
40 #endif
42 #if defined HAVE_STRING_H || defined _LIBC
43 # ifndef _GNU_SOURCE
44 # define _GNU_SOURCE 1
45 # endif
46 # include <string.h>
47 #else
48 # include <strings.h>
49 # ifndef memcpy
50 # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
51 # endif
52 #endif
53 #if !HAVE_STRCHR && !defined _LIBC
54 # ifndef strchr
55 # define strchr index
56 # endif
57 #endif
59 #if defined STDC_HEADERS || defined _LIBC
60 #else
61 char *getenv ();
62 # ifdef HAVE_MALLOC_H
63 # else
64 void free ();
65 # endif
66 #endif
68 #if defined _LIBC || defined HAVE_ARGZ_H
69 # include <argz.h>
70 #endif
71 #include <ctype.h>
72 #include <sys/types.h>
74 #if defined STDC_HEADERS || defined _LIBC
75 # include <stdlib.h>
76 #else
77 # ifdef HAVE_MEMORY_H
78 # include <memory.h>
79 # endif
80 #endif
82 /* Interrupt of l10nflist.c */
84 /* Begin of loadinfo.h */
86 /* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
87 This file is part of the GNU C Library.
88 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. */
90 #ifndef PARAMS
91 # if __STDC__
92 # define PARAMS(args) args
93 # else
94 # define PARAMS(args) ()
95 # endif
96 #endif
98 /* Encoding of locale name parts. */
99 #define CEN_REVISION 1
100 #define CEN_SPONSOR 2
101 #define CEN_SPECIAL 4
102 #define XPG_NORM_CODESET 8
103 #define XPG_CODESET 16
104 #define TERRITORY 32
105 #define CEN_AUDIENCE 64
106 #define XPG_MODIFIER 128
108 #define CEN_SPECIFIC (CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE)
109 #define XPG_SPECIFIC (XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER)
111 struct loaded_l10nfile
113 const char *filename;
114 int decided;
116 const void *data;
118 struct loaded_l10nfile *next;
119 struct loaded_l10nfile *successor[1];
122 static const char *_nl_normalize_codeset PARAMS ((const unsigned char *codeset,
123 size_t name_len));
125 static struct loaded_l10nfile *
126 _nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list,
127 const char *dirlist, size_t dirlist_len, int mask,
128 const char *language, const char *territory,
129 const char *codeset,
130 const char *normalized_codeset,
131 const char *modifier, const char *special,
132 const char *sponsor, const char *revision,
133 const char *filename, int do_allocate));
135 static const char *_nl_expand_alias PARAMS ((const char *name));
137 static int _nl_explode_name PARAMS ((char *name, const char **language,
138 const char **modifier,
139 const char **territory,
140 const char **codeset,
141 const char **normalized_codeset,
142 const char **special,
143 const char **sponsor,
144 const char **revision));
146 /* End of loadinfo.h */
148 /* Resume of l10nflist.c */
150 /* On some strange systems still no definition of NULL is found. Sigh! */
151 #ifndef NULL
152 # if defined __STDC__ && __STDC__
153 # define NULL ((void *) 0)
154 # else
155 # define NULL 0
156 # endif
157 #endif
159 #ifdef _LIBC
160 /* Rename the non ANSI C functions. This is required by the standard
161 because some ANSI C functions will require linking with this object
162 file and the name space must not be polluted. */
163 # ifndef stpcpy
164 # define stpcpy(dest, src) __stpcpy(dest, src)
165 # endif
166 #else
167 # ifndef HAVE_STPCPY
168 static char *stpcpy PARAMS ((char *dest, const char *src));
169 # endif
170 #endif
172 /* Define function which are usually not available. */
174 #if !defined _LIBC && !defined HAVE___ARGZ_COUNT
175 /* Returns the number of strings in ARGZ. */
176 static size_t argz_count__ PARAMS ((const char *argz, size_t len));
178 static size_t
179 argz_count__ (argz, len)
180 const char *argz;
181 size_t len;
183 size_t count = 0;
184 while (len > 0)
186 size_t part_len = strlen (argz);
187 argz += part_len + 1;
188 len -= part_len + 1;
189 count++;
191 return count;
193 # undef __argz_count
194 # define __argz_count(argz, len) argz_count__ (argz, len)
195 #endif /* !_LIBC && !HAVE___ARGZ_COUNT */
197 #if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
198 /* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
199 except the last into the character SEP. */
200 static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
202 static void
203 argz_stringify__ (argz, len, sep)
204 char *argz;
205 size_t len;
206 int sep;
208 while (len > 0)
210 size_t part_len = strlen (argz);
211 argz += part_len;
212 len -= part_len + 1;
213 if (len > 0)
214 *argz++ = sep;
217 # undef __argz_stringify
218 # define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
219 #endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */
221 #if !defined _LIBC && !defined HAVE___ARGZ_NEXT
222 static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
223 const char *entry));
225 static char *
226 argz_next__ (argz, argz_len, entry)
227 char *argz;
228 size_t argz_len;
229 const char *entry;
231 if (entry)
233 if (entry < argz + argz_len)
234 entry = strchr (entry, '\0') + 1;
236 return entry >= argz + argz_len ? NULL : (char *) entry;
238 else
239 if (argz_len > 0)
240 return argz;
241 else
242 return 0;
244 # undef __argz_next
245 # define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
246 #endif /* !_LIBC && !HAVE___ARGZ_NEXT */
248 /* Return number of bits set in X. */
249 static int pop PARAMS ((int x));
251 static inline int
252 pop (x)
253 int x;
255 /* We assume that no more than 16 bits are used. */
256 x = ((x & ~0x5555) >> 1) + (x & 0x5555);
257 x = ((x & ~0x3333) >> 2) + (x & 0x3333);
258 x = ((x >> 4) + x) & 0x0f0f;
259 x = ((x >> 8) + x) & 0xff;
261 return x;
264 static struct loaded_l10nfile *
265 _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
266 territory, codeset, normalized_codeset, modifier, special,
267 sponsor, revision, filename, do_allocate)
268 struct loaded_l10nfile **l10nfile_list;
269 const char *dirlist;
270 size_t dirlist_len;
271 int mask;
272 const char *language;
273 const char *territory;
274 const char *codeset;
275 const char *normalized_codeset;
276 const char *modifier;
277 const char *special;
278 const char *sponsor;
279 const char *revision;
280 const char *filename;
281 int do_allocate;
283 char *abs_filename;
284 struct loaded_l10nfile *last = NULL;
285 struct loaded_l10nfile *retval;
286 char *cp;
287 size_t entries;
288 int cnt;
290 /* Allocate room for the full file name. */
291 abs_filename = (char *) malloc (dirlist_len
292 + strlen (language)
293 + ((mask & TERRITORY) != 0
294 ? strlen (territory) + 1 : 0)
295 + ((mask & XPG_CODESET) != 0
296 ? strlen (codeset) + 1 : 0)
297 + ((mask & XPG_NORM_CODESET) != 0
298 ? strlen (normalized_codeset) + 1 : 0)
299 + (((mask & XPG_MODIFIER) != 0
300 || (mask & CEN_AUDIENCE) != 0)
301 ? strlen (modifier) + 1 : 0)
302 + ((mask & CEN_SPECIAL) != 0
303 ? strlen (special) + 1 : 0)
304 + (((mask & CEN_SPONSOR) != 0
305 || (mask & CEN_REVISION) != 0)
306 ? (1 + ((mask & CEN_SPONSOR) != 0
307 ? strlen (sponsor) + 1 : 0)
308 + ((mask & CEN_REVISION) != 0
309 ? strlen (revision) + 1 : 0)) : 0)
310 + 1 + strlen (filename) + 1);
312 if (abs_filename == NULL)
313 return NULL;
315 retval = NULL;
316 last = NULL;
318 /* Construct file name. */
319 memcpy (abs_filename, dirlist, dirlist_len);
320 __argz_stringify (abs_filename, dirlist_len, ':');
321 cp = abs_filename + (dirlist_len - 1);
322 *cp++ = '/';
323 cp = stpcpy (cp, language);
325 if ((mask & TERRITORY) != 0)
327 *cp++ = '_';
328 cp = stpcpy (cp, territory);
330 if ((mask & XPG_CODESET) != 0)
332 *cp++ = '.';
333 cp = stpcpy (cp, codeset);
335 if ((mask & XPG_NORM_CODESET) != 0)
337 *cp++ = '.';
338 cp = stpcpy (cp, normalized_codeset);
340 if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
342 /* This component can be part of both syntaces but has different
343 leading characters. For CEN we use `+', else `@'. */
344 *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
345 cp = stpcpy (cp, modifier);
347 if ((mask & CEN_SPECIAL) != 0)
349 *cp++ = '+';
350 cp = stpcpy (cp, special);
352 if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0)
354 *cp++ = ',';
355 if ((mask & CEN_SPONSOR) != 0)
356 cp = stpcpy (cp, sponsor);
357 if ((mask & CEN_REVISION) != 0)
359 *cp++ = '_';
360 cp = stpcpy (cp, revision);
364 *cp++ = '/';
365 stpcpy (cp, filename);
367 /* Look in list of already loaded domains whether it is already
368 available. */
369 last = NULL;
370 for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
371 if (retval->filename != NULL)
373 int compare = strcmp (retval->filename, abs_filename);
374 if (compare == 0)
375 /* We found it! */
376 break;
377 if (compare < 0)
379 /* It's not in the list. */
380 retval = NULL;
381 break;
384 last = retval;
387 if (retval != NULL || do_allocate == 0)
389 free (abs_filename);
390 return retval;
393 retval = (struct loaded_l10nfile *)
394 malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len)
395 * (1 << pop (mask))
396 * sizeof (struct loaded_l10nfile *)));
397 if (retval == NULL)
398 return NULL;
400 retval->filename = abs_filename;
401 retval->decided = (__argz_count (dirlist, dirlist_len) != 1
402 || ((mask & XPG_CODESET) != 0
403 && (mask & XPG_NORM_CODESET) != 0));
404 retval->data = NULL;
406 if (last == NULL)
408 retval->next = *l10nfile_list;
409 *l10nfile_list = retval;
411 else
413 retval->next = last->next;
414 last->next = retval;
417 entries = 0;
418 /* If the DIRLIST is a real list the RETVAL entry corresponds not to
419 a real file. So we have to use the DIRLIST separation mechanism
420 of the inner loop. */
421 cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask;
422 for (; cnt >= 0; --cnt)
423 if ((cnt & ~mask) == 0
424 && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
425 && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
427 /* Iterate over all elements of the DIRLIST. */
428 char *dir = NULL;
430 while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
431 != NULL)
432 retval->successor[entries++]
433 = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
434 language, territory, codeset,
435 normalized_codeset, modifier, special,
436 sponsor, revision, filename, 1);
438 retval->successor[entries] = NULL;
440 return retval;
443 /* Normalize codeset name. There is no standard for the codeset
444 names. Normalization allows the user to use any of the common
445 names. */
446 static const char *
447 _nl_normalize_codeset (codeset, name_len)
448 const unsigned char *codeset;
449 size_t name_len;
451 int len = 0;
452 int only_digit = 1;
453 char *retval;
454 char *wp;
455 size_t cnt;
457 for (cnt = 0; cnt < name_len; ++cnt)
458 if (isalnum (codeset[cnt]))
460 ++len;
462 if (isalpha (codeset[cnt]))
463 only_digit = 0;
466 retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
468 if (retval != NULL)
470 if (only_digit)
471 wp = stpcpy (retval, "iso");
472 else
473 wp = retval;
475 for (cnt = 0; cnt < name_len; ++cnt)
476 if (isalpha (codeset[cnt]))
477 *wp++ = tolower (codeset[cnt]);
478 else if (isdigit (codeset[cnt]))
479 *wp++ = codeset[cnt];
481 *wp = '\0';
484 return (const char *) retval;
487 /* End of l10nflist.c */
489 /* Begin of explodename.c */
491 /* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
492 Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
494 #if defined STDC_HEADERS || defined _LIBC
495 #endif
497 #if defined HAVE_STRING_H || defined _LIBC
498 #else
499 #endif
501 static int
502 _nl_explode_name (name, language, modifier, territory, codeset,
503 normalized_codeset, special, sponsor, revision)
504 char *name;
505 const char **language;
506 const char **modifier;
507 const char **territory;
508 const char **codeset;
509 const char **normalized_codeset;
510 const char **special;
511 const char **sponsor;
512 const char **revision;
514 enum { undecided, xpg, cen } syntax;
515 char *cp;
516 int mask;
518 *modifier = NULL;
519 *territory = NULL;
520 *codeset = NULL;
521 *normalized_codeset = NULL;
522 *special = NULL;
523 *sponsor = NULL;
524 *revision = NULL;
526 /* Now we determine the single parts of the locale name. First
527 look for the language. Termination symbols are `_' and `@' if
528 we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */
529 mask = 0;
530 syntax = undecided;
531 *language = cp = name;
532 while (cp[0] != '\0' && cp[0] != '_' && cp[0] != '@'
533 && cp[0] != '+' && cp[0] != ',')
534 ++cp;
536 if (*language == cp)
537 /* This does not make sense: language has to be specified. Use
538 this entry as it is without exploding. Perhaps it is an alias. */
539 cp = strchr (*language, '\0');
540 else if (cp[0] == '_')
542 /* Next is the territory. */
543 cp[0] = '\0';
544 *territory = ++cp;
546 while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@'
547 && cp[0] != '+' && cp[0] != ',' && cp[0] != '_')
548 ++cp;
550 mask |= TERRITORY;
552 if (cp[0] == '.')
554 /* Next is the codeset. */
555 syntax = xpg;
556 cp[0] = '\0';
557 *codeset = ++cp;
559 while (cp[0] != '\0' && cp[0] != '@')
560 ++cp;
562 mask |= XPG_CODESET;
564 if (*codeset != cp && (*codeset)[0] != '\0')
566 *normalized_codeset = _nl_normalize_codeset ((const unsigned
567 char *)*codeset,
568 cp - *codeset);
569 if (strcmp (*codeset, *normalized_codeset) == 0)
570 free ((char *) *normalized_codeset);
571 else
572 mask |= XPG_NORM_CODESET;
577 if (cp[0] == '@' || (syntax != xpg && cp[0] == '+'))
579 /* Next is the modifier. */
580 syntax = cp[0] == '@' ? xpg : cen;
581 cp[0] = '\0';
582 *modifier = ++cp;
584 while (syntax == cen && cp[0] != '\0' && cp[0] != '+'
585 && cp[0] != ',' && cp[0] != '_')
586 ++cp;
588 mask |= XPG_MODIFIER | CEN_AUDIENCE;
591 if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_'))
593 syntax = cen;
595 if (cp[0] == '+')
597 /* Next is special application (CEN syntax). */
598 cp[0] = '\0';
599 *special = ++cp;
601 while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_')
602 ++cp;
604 mask |= CEN_SPECIAL;
607 if (cp[0] == ',')
609 /* Next is sponsor (CEN syntax). */
610 cp[0] = '\0';
611 *sponsor = ++cp;
613 while (cp[0] != '\0' && cp[0] != '_')
614 ++cp;
616 mask |= CEN_SPONSOR;
619 if (cp[0] == '_')
621 /* Next is revision (CEN syntax). */
622 cp[0] = '\0';
623 *revision = ++cp;
625 mask |= CEN_REVISION;
629 /* For CEN syntax values it might be important to have the
630 separator character in the file name, not for XPG syntax. */
631 if (syntax == xpg)
633 if (*territory != NULL && (*territory)[0] == '\0')
634 mask &= ~TERRITORY;
636 if (*codeset != NULL && (*codeset)[0] == '\0')
637 mask &= ~XPG_CODESET;
639 if (*modifier != NULL && (*modifier)[0] == '\0')
640 mask &= ~XPG_MODIFIER;
643 return mask;
646 /* End of explodename.c */
648 /* Begin of loadmsgcat.c */
650 /* Load needed message catalogs.
651 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. */
653 #include <fcntl.h>
654 #include <sys/stat.h>
656 #if defined STDC_HEADERS || defined _LIBC
657 #endif
659 #if defined HAVE_UNISTD_H || defined _LIBC
660 # include <unistd.h>
661 #endif
663 #if (defined HAVE_MMAP && defined HAVE_MUNMAP) || defined _LIBC
664 # include <sys/mman.h>
665 #endif
667 /* Interrupt of loadmsgcat.c */
669 /* Begin of gettext.h */
671 /* Internal header for GNU gettext internationalization functions.
672 Copyright (C) 1995, 1997 Free Software Foundation, Inc. */
674 #include <stdio.h>
676 #if HAVE_LIMITS_H || _LIBC
677 # include <limits.h>
678 #endif
680 /* The magic number of the GNU message catalog format. */
681 #define _MAGIC 0x950412de
682 #define _MAGIC_SWAPPED 0xde120495
684 /* Revision number of the currently used .mo (binary) file format. */
685 #define MO_REVISION_NUMBER 0
687 /* The following contortions are an attempt to use the C preprocessor
688 to determine an unsigned integral type that is 32 bits wide. An
689 alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
690 doing that would require that the configure script compile and *run*
691 the resulting executable. Locally running cross-compiled executables
692 is usually not possible. */
694 #if __STDC__
695 # define UINT_MAX_32_BITS 4294967295U
696 #else
697 # define UINT_MAX_32_BITS 0xFFFFFFFF
698 #endif
700 /* If UINT_MAX isn't defined, assume it's a 32-bit type.
701 This should be valid for all systems GNU cares about because
702 that doesn't include 16-bit systems, and only modern systems
703 (that certainly have <limits.h>) have 64+-bit integral types. */
705 #ifndef UINT_MAX
706 # define UINT_MAX UINT_MAX_32_BITS
707 #endif
709 #if UINT_MAX == UINT_MAX_32_BITS
710 typedef unsigned nls_uint32;
711 #else
712 # if USHRT_MAX == UINT_MAX_32_BITS
713 typedef unsigned short nls_uint32;
714 # else
715 # if ULONG_MAX == UINT_MAX_32_BITS
716 typedef unsigned long nls_uint32;
717 # else
718 /* The following line is intended to throw an error. Using #error is
719 not portable enough. */
720 "Cannot determine unsigned 32-bit data type."
721 # endif
722 # endif
723 #endif
725 /* Header for binary .mo file format. */
726 struct mo_file_header
728 /* The magic number. */
729 nls_uint32 magic;
730 /* The revision number of the file format. */
731 nls_uint32 revision;
732 /* The number of strings pairs. */
733 nls_uint32 nstrings;
734 /* Offset of table with start offsets of original strings. */
735 nls_uint32 orig_tab_offset;
736 /* Offset of table with start offsets of translation strings. */
737 nls_uint32 trans_tab_offset;
738 /* Size of hashing table. */
739 nls_uint32 hash_tab_size;
740 /* Offset of first hashing entry. */
741 nls_uint32 hash_tab_offset;
744 struct string_desc
746 /* Length of addressed string. */
747 nls_uint32 length;
748 /* Offset of string in file. */
749 nls_uint32 offset;
752 /* End of gettext.h */
754 /* Resume of loadmsgcat.c */
756 /* Interrupt of loadmsgcat.c */
758 /* Begin of gettextP.h */
760 /* Header describing internals of gettext library
761 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
762 Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
764 #ifndef _GETTEXTP_H
765 #define _GETTEXTP_H
767 #ifndef PARAMS
768 # if __STDC__
769 # define PARAMS(args) args
770 # else
771 # define PARAMS(args) ()
772 # endif
773 #endif
775 #ifndef internal_function
776 # define internal_function
777 #endif
779 #ifndef W
780 # define W(flag, data) ((flag) ? SWAP (data) : (data))
781 #endif
783 #ifdef _LIBC
784 # include <byteswap.h>
785 # define SWAP(i) bswap_32 (i)
786 #else
787 static nls_uint32 SWAP PARAMS ((nls_uint32 i));
789 /* Apparently on some (non-32-bit?) systems it's important to use the right
790 prototype. Reported for a CRAY T3E. */
791 static inline nls_uint32
792 #if __STDC__
793 SWAP (nls_uint32 i)
794 #else
795 SWAP (i) nls_uint32 i;
796 #endif
798 return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
800 #endif
802 struct loaded_domain
804 const char *data;
805 int use_mmap;
806 size_t mmap_size;
807 int must_swap;
808 nls_uint32 nstrings;
809 struct string_desc *orig_tab;
810 struct string_desc *trans_tab;
811 nls_uint32 hash_size;
812 nls_uint32 *hash_tab;
815 struct binding
817 struct binding *next;
818 char *domainname;
819 char *dirname;
822 static struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
823 char *__locale,
824 const char *__domainname))
825 internal_function;
826 static void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain))
827 internal_function;
828 static void _nl_unload_domain PARAMS ((struct loaded_domain *__domain))
829 internal_function;
831 #endif /* gettextP.h */
833 /* End of gettextP.h */
835 /* Resume of loadmsgcat.c */
837 #ifdef _LIBC
838 /* Rename the non ISO C functions. This is required by the standard
839 because some ISO C functions will require linking with this object
840 file and the name space must not be polluted. */
841 # define open __open
842 # define close __close
843 # define read __read
844 # define mmap __mmap
845 # define munmap __munmap
846 #endif
848 /* We need a sign, whether a new catalog was loaded, which can be associated
849 with all translations. This is important if the translations are
850 cached by one of GCC's features. */
851 int _nl_msg_cat_cntr = 0;
853 /* Load the message catalogs specified by FILENAME. If it is no valid
854 message catalog do nothing. */
855 static void
856 internal_function
857 _nl_load_domain (domain_file)
858 struct loaded_l10nfile *domain_file;
860 int fd;
861 size_t size;
862 struct stat st;
863 struct mo_file_header *data = (struct mo_file_header *) -1;
864 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
865 || defined _LIBC
866 int use_mmap = 0;
867 #endif
868 struct loaded_domain *domain;
870 domain_file->decided = 1;
871 domain_file->data = NULL;
873 /* If the record does not represent a valid locale the FILENAME
874 might be NULL. This can happen when according to the given
875 specification the locale file name is different for XPG and CEN
876 syntax. */
877 if (domain_file->filename == NULL)
878 return;
880 /* Try to open the addressed file. */
881 fd = open (domain_file->filename, O_RDONLY);
882 if (fd == -1)
883 return;
885 /* We must know about the size of the file. */
886 if (fstat (fd, &st) != 0
887 || (size = (size_t) st.st_size) != st.st_size
888 || size < sizeof (struct mo_file_header))
890 /* Something went wrong. */
891 close (fd);
892 return;
895 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
896 || defined _LIBC
897 /* Now we are ready to load the file. If mmap() is available we try
898 this first. If not available or it failed we try to load it. */
899 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
900 MAP_PRIVATE, fd, 0);
902 if (data != (struct mo_file_header *) -1)
904 /* mmap() call was successful. */
905 close (fd);
906 use_mmap = 1;
908 #endif
910 /* If the data is not yet available (i.e. mmap'ed) we try to load
911 it manually. */
912 if (data == (struct mo_file_header *) -1)
914 size_t to_read;
915 char *read_ptr;
917 data = (struct mo_file_header *) malloc (size);
918 if (data == NULL)
919 return;
921 to_read = size;
922 read_ptr = (char *) data;
925 long int nb = (long int) read (fd, read_ptr, to_read);
926 if (nb == -1)
928 close (fd);
929 return;
932 read_ptr += nb;
933 to_read -= nb;
935 while (to_read > 0);
937 close (fd);
940 /* Using the magic number we can test whether it really is a message
941 catalog file. */
942 if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED)
944 /* The magic number is wrong: not a message catalog file. */
945 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
946 || defined _LIBC
947 if (use_mmap)
948 munmap ((caddr_t) data, size);
949 else
950 #endif
951 free (data);
952 return;
955 domain_file->data
956 = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
957 if (domain_file->data == NULL)
958 return;
960 domain = (struct loaded_domain *) domain_file->data;
961 domain->data = (char *) data;
962 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
963 || defined _LIBC
964 domain->use_mmap = use_mmap;
965 #endif
966 domain->mmap_size = size;
967 domain->must_swap = data->magic != _MAGIC;
969 /* Fill in the information about the available tables. */
970 switch (W (domain->must_swap, data->revision))
972 case 0:
973 domain->nstrings = W (domain->must_swap, data->nstrings);
974 domain->orig_tab = (struct string_desc *)
975 ((char *) data + W (domain->must_swap, data->orig_tab_offset));
976 domain->trans_tab = (struct string_desc *)
977 ((char *) data + W (domain->must_swap, data->trans_tab_offset));
978 domain->hash_size = W (domain->must_swap, data->hash_tab_size);
979 domain->hash_tab = (nls_uint32 *)
980 ((char *) data + W (domain->must_swap, data->hash_tab_offset));
981 break;
982 default:
983 /* This is an illegal revision. */
984 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
985 || defined _LIBC
986 if (use_mmap)
987 munmap ((caddr_t) data, size);
988 else
989 #endif
990 free (data);
991 free (domain);
992 domain_file->data = NULL;
993 return;
996 /* Show that one domain is changed. This might make some cached
997 translations invalid. */
998 ++_nl_msg_cat_cntr;
1001 #ifdef _LIBC
1002 static void
1003 internal_function
1004 _nl_unload_domain (domain)
1005 struct loaded_domain *domain;
1007 if (domain->use_mmap)
1008 munmap ((caddr_t) domain->data, domain->mmap_size);
1009 else
1010 free ((void *) domain->data);
1012 free (domain);
1014 #endif
1016 /* End of loadmsgcat.c */
1018 /* Begin of localealias.c */
1020 /* Handle aliases for locale names.
1021 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
1022 Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
1024 #if defined STDC_HEADERS || defined _LIBC
1025 #else
1026 char *getenv ();
1027 # ifdef HAVE_MALLOC_H
1028 # include <malloc.h>
1029 # else
1030 void free ();
1031 # endif
1032 #endif
1034 #if defined HAVE_STRING_H || defined _LIBC
1035 # ifndef _GNU_SOURCE
1036 # define _GNU_SOURCE 1
1037 # endif
1038 #else
1039 # ifndef memcpy
1040 # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
1041 # endif
1042 #endif
1043 #if !HAVE_STRCHR && !defined _LIBC
1044 # ifndef strchr
1045 # define strchr index
1046 # endif
1047 #endif
1049 #ifdef _LIBC
1050 /* Rename the non ANSI C functions. This is required by the standard
1051 because some ANSI C functions will require linking with this object
1052 file and the name space must not be polluted. */
1053 # define strcasecmp __strcasecmp
1055 # define mempcpy __mempcpy
1056 # define HAVE_MEMPCPY 1
1058 /* We need locking here since we can be called from different places. */
1059 # include <bits/libc-lock.h>
1061 __libc_lock_define_initialized (static, lock);
1062 #endif
1064 /* For those loosing systems which don't have `alloca' we have to add
1065 some additional code emulating it. */
1066 #ifdef HAVE_ALLOCA
1067 /* Nothing has to be done. */
1068 # define ADD_BLOCK(list, address) /* nothing */
1069 # define FREE_BLOCKS(list) /* nothing */
1070 #else
1071 struct block_list
1073 void *address;
1074 struct block_list *next;
1076 # define ADD_BLOCK(list, addr) \
1077 do { \
1078 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
1079 /* If we cannot get a free block we cannot add the new element to \
1080 the list. */ \
1081 if (newp != NULL) { \
1082 newp->address = (addr); \
1083 newp->next = (list); \
1084 (list) = newp; \
1086 } while (0)
1087 # define FREE_BLOCKS(list) \
1088 do { \
1089 while (list != NULL) { \
1090 struct block_list *old = list; \
1091 list = list->next; \
1092 free (old); \
1094 } while (0)
1095 # undef alloca
1096 # define alloca(size) (malloc (size))
1097 #endif /* have alloca */
1099 struct alias_map
1101 const char *alias;
1102 const char *value;
1105 static char *string_space = NULL;
1106 static size_t string_space_act = 0;
1107 static size_t string_space_max = 0;
1108 static struct alias_map *map;
1109 static size_t nmap = 0;
1110 static size_t maxmap = 0;
1112 /* Prototypes for local functions. */
1113 static size_t read_alias_file PARAMS ((const char *fname, int fname_len))
1114 internal_function;
1115 static void extend_alias_table PARAMS ((void));
1116 static int alias_compare PARAMS ((const struct alias_map *map1,
1117 const struct alias_map *map2));
1119 static const char *
1120 _nl_expand_alias (name)
1121 const char *name;
1123 static const char *locale_alias_path = ALIASPATH;
1124 struct alias_map *retval;
1125 const char *result = NULL;
1126 size_t added;
1128 #ifdef _LIBC
1129 __libc_lock_lock (lock);
1130 #endif
1134 struct alias_map item;
1136 item.alias = name;
1138 if (nmap > 0)
1139 retval = (struct alias_map *) bsearch (&item, map, nmap,
1140 sizeof (struct alias_map),
1141 (int (*) PARAMS ((const void *,
1142 const void *))
1143 ) alias_compare);
1144 else
1145 retval = NULL;
1147 /* We really found an alias. Return the value. */
1148 if (retval != NULL)
1150 result = retval->value;
1151 break;
1154 /* Perhaps we can find another alias file. */
1155 added = 0;
1156 while (added == 0 && locale_alias_path[0] != '\0')
1158 const char *start;
1160 while (locale_alias_path[0] == ':')
1161 ++locale_alias_path;
1162 start = locale_alias_path;
1164 while (locale_alias_path[0] != '\0' && locale_alias_path[0] != ':')
1165 ++locale_alias_path;
1167 if (start < locale_alias_path)
1168 added = read_alias_file (start, locale_alias_path - start);
1171 while (added != 0);
1173 #ifdef _LIBC
1174 __libc_lock_unlock (lock);
1175 #endif
1177 return result;
1180 static size_t
1181 internal_function
1182 read_alias_file (fname, fname_len)
1183 const char *fname;
1184 int fname_len;
1186 #ifndef HAVE_ALLOCA
1187 struct block_list *block_list = NULL;
1188 #endif
1189 FILE *fp;
1190 char *full_fname;
1191 size_t added;
1192 static const char aliasfile[] = "/locale.alias";
1194 full_fname = (char *) alloca (fname_len + sizeof aliasfile);
1195 ADD_BLOCK (block_list, full_fname);
1196 #ifdef HAVE_MEMPCPY
1197 mempcpy (mempcpy (full_fname, fname, fname_len),
1198 aliasfile, sizeof aliasfile);
1199 #else
1200 memcpy (full_fname, fname, fname_len);
1201 memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
1202 #endif
1204 fp = fopen (full_fname, "r");
1205 if (fp == NULL)
1207 FREE_BLOCKS (block_list);
1208 return 0;
1211 added = 0;
1212 while (!feof (fp))
1214 /* It is a reasonable approach to use a fix buffer here because
1215 a) we are only interested in the first two fields
1216 b) these fields must be usable as file names and so must not
1217 be that long
1219 unsigned char buf[BUFSIZ];
1220 unsigned char *alias;
1221 unsigned char *value;
1222 unsigned char *cp;
1224 if (fgets ((char *)buf, sizeof buf, fp) == NULL)
1225 /* EOF reached. */
1226 break;
1228 /* Possibly not the whole line fits into the buffer. Ignore
1229 the rest of the line. */
1230 if (strchr ((char *)buf, '\n') == NULL)
1232 char altbuf[BUFSIZ];
1234 if (fgets (altbuf, sizeof altbuf, fp) == NULL)
1235 /* Make sure the inner loop will be left. The outer loop
1236 will exit at the `feof' test. */
1237 break;
1238 while (strchr (altbuf, '\n') == NULL);
1241 cp = buf;
1242 /* Ignore leading white space. */
1243 while (isspace (cp[0]))
1244 ++cp;
1246 /* A leading '#' signals a comment line. */
1247 if (cp[0] != '\0' && cp[0] != '#')
1249 alias = cp++;
1250 while (cp[0] != '\0' && !isspace (cp[0]))
1251 ++cp;
1252 /* Terminate alias name. */
1253 if (cp[0] != '\0')
1254 *cp++ = '\0';
1256 /* Now look for the beginning of the value. */
1257 while (isspace (cp[0]))
1258 ++cp;
1260 if (cp[0] != '\0')
1262 size_t alias_len;
1263 size_t value_len;
1265 value = cp++;
1266 while (cp[0] != '\0' && !isspace (cp[0]))
1267 ++cp;
1268 /* Terminate value. */
1269 if (cp[0] == '\n')
1271 /* This has to be done to make the following test
1272 for the end of line possible. We are looking for
1273 the terminating '\n' which do not overwrite here. */
1274 *cp++ = '\0';
1275 *cp = '\n';
1277 else if (cp[0] != '\0')
1278 *cp++ = '\0';
1280 if (nmap >= maxmap)
1281 extend_alias_table ();
1283 alias_len = strlen ((char *)alias) + 1;
1284 value_len = strlen ((char *)value) + 1;
1286 if (string_space_act + alias_len + value_len > string_space_max)
1288 /* Increase size of memory pool. */
1289 size_t new_size = (string_space_max
1290 + (alias_len + value_len > 1024
1291 ? alias_len + value_len : 1024));
1292 char *new_pool = (char *) realloc (string_space, new_size);
1293 if (new_pool == NULL)
1295 FREE_BLOCKS (block_list);
1296 return added;
1298 string_space = new_pool;
1299 string_space_max = new_size;
1302 map[nmap].alias = memcpy (&string_space[string_space_act],
1303 alias, alias_len);
1304 string_space_act += alias_len;
1306 map[nmap].value = memcpy (&string_space[string_space_act],
1307 value, value_len);
1308 string_space_act += value_len;
1310 ++nmap;
1311 ++added;
1316 /* Should we test for ferror()? I think we have to silently ignore
1317 errors. --drepper */
1318 fclose (fp);
1320 if (added > 0)
1321 qsort (map, nmap, sizeof (struct alias_map),
1322 (int (*) PARAMS ((const void *, const void *))) alias_compare);
1324 FREE_BLOCKS (block_list);
1325 return added;
1328 static void
1329 extend_alias_table ()
1331 size_t new_size;
1332 struct alias_map *new_map;
1334 new_size = maxmap == 0 ? 100 : 2 * maxmap;
1335 new_map = (struct alias_map *) realloc (map, (new_size
1336 * sizeof (struct alias_map)));
1337 if (new_map == NULL)
1338 /* Simply don't extend: we don't have any more core. */
1339 return;
1341 map = new_map;
1342 maxmap = new_size;
1345 #ifdef _LIBC
1346 static void __attribute__ ((unused))
1347 free_mem (void)
1349 if (string_space != NULL)
1350 free (string_space);
1351 if (map != NULL)
1352 free (map);
1354 text_set_element (__libc_subfreeres, free_mem);
1355 #endif
1357 static int
1358 alias_compare (map1, map2)
1359 const struct alias_map *map1;
1360 const struct alias_map *map2;
1362 #if defined _LIBC || defined HAVE_STRCASECMP
1363 return strcasecmp (map1->alias, map2->alias);
1364 #else
1365 const unsigned char *p1 = (const unsigned char *) map1->alias;
1366 const unsigned char *p2 = (const unsigned char *) map2->alias;
1367 unsigned char c1, c2;
1369 if (p1 == p2)
1370 return 0;
1374 /* I know this seems to be odd but the tolower() function in
1375 some systems libc cannot handle nonalpha characters. */
1376 c1 = isupper (*p1) ? tolower (*p1) : *p1;
1377 c2 = isupper (*p2) ? tolower (*p2) : *p2;
1378 if (c1 == '\0')
1379 break;
1380 ++p1;
1381 ++p2;
1383 while (c1 == c2);
1385 return c1 - c2;
1386 #endif
1389 /* End of localealias.c */
1391 /* Begin of finddomain.c */
1393 /* Handle list of needed message catalogs
1394 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
1395 Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
1397 #include <errno.h>
1399 #if defined STDC_HEADERS || defined _LIBC
1400 #else
1401 # ifdef HAVE_MALLOC_H
1402 # else
1403 void free ();
1404 # endif
1405 #endif
1407 #if defined HAVE_STRING_H || defined _LIBC
1408 #else
1409 # ifndef memcpy
1410 # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
1411 # endif
1412 #endif
1413 #if !HAVE_STRCHR && !defined _LIBC
1414 # ifndef strchr
1415 # define strchr index
1416 # endif
1417 #endif
1419 #if defined HAVE_UNISTD_H || defined _LIBC
1420 #endif
1422 #ifdef _LIBC
1423 # include <libintl.h>
1424 #else
1425 # include "gettext.h"
1426 #endif
1428 /* List of already loaded domains. */
1429 static struct loaded_l10nfile *_nl_loaded_domains;
1431 /* Return a data structure describing the message catalog described by
1432 the DOMAINNAME and CATEGORY parameters with respect to the currently
1433 established bindings. */
1434 static struct loaded_l10nfile *
1435 internal_function
1436 _nl_find_domain (dirname, locale, domainname)
1437 const char *dirname;
1438 char *locale;
1439 const char *domainname;
1441 struct loaded_l10nfile *retval;
1442 const char *language;
1443 const char *modifier;
1444 const char *territory;
1445 const char *codeset;
1446 const char *normalized_codeset;
1447 const char *special;
1448 const char *sponsor;
1449 const char *revision;
1450 const char *alias_value;
1451 int mask;
1453 /* LOCALE can consist of up to four recognized parts for the XPG syntax:
1455 language[_territory[.codeset]][@modifier]
1457 and six parts for the CEN syntax:
1459 language[_territory][+audience][+special][,[sponsor][_revision]]
1461 Beside the first part all of them are allowed to be missing. If
1462 the full specified locale is not found, the less specific one are
1463 looked for. The various parts will be stripped off according to
1464 the following order:
1465 (1) revision
1466 (2) sponsor
1467 (3) special
1468 (4) codeset
1469 (5) normalized codeset
1470 (6) territory
1471 (7) audience/modifier
1474 /* If we have already tested for this locale entry there has to
1475 be one data set in the list of loaded domains. */
1476 retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
1477 strlen (dirname) + 1, 0, locale, NULL, NULL,
1478 NULL, NULL, NULL, NULL, NULL, domainname, 0);
1479 if (retval != NULL)
1481 /* We know something about this locale. */
1482 int cnt;
1484 if (retval->decided == 0)
1485 _nl_load_domain (retval);
1487 if (retval->data != NULL)
1488 return retval;
1490 for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
1492 if (retval->successor[cnt]->decided == 0)
1493 _nl_load_domain (retval->successor[cnt]);
1495 if (retval->successor[cnt]->data != NULL)
1496 break;
1498 return cnt >= 0 ? retval : NULL;
1499 /* NOTREACHED */
1502 /* See whether the locale value is an alias. If yes its value
1503 *overwrites* the alias name. No test for the original value is
1504 done. */
1505 alias_value = _nl_expand_alias (locale);
1506 if (alias_value != NULL)
1508 #if defined _LIBC || defined HAVE_STRDUP
1509 locale = strdup (alias_value);
1510 if (locale == NULL)
1511 return NULL;
1512 #else
1513 size_t len = strlen (alias_value) + 1;
1514 locale = (char *) malloc (len);
1515 if (locale == NULL)
1516 return NULL;
1518 memcpy (locale, alias_value, len);
1519 #endif
1522 /* Now we determine the single parts of the locale name. First
1523 look for the language. Termination symbols are `_' and `@' if
1524 we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */
1525 mask = _nl_explode_name (locale, &language, &modifier, &territory,
1526 &codeset, &normalized_codeset, &special,
1527 &sponsor, &revision);
1529 /* Create all possible locale entries which might be interested in
1530 generalization. */
1531 retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
1532 strlen (dirname) + 1, mask, language, territory,
1533 codeset, normalized_codeset, modifier, special,
1534 sponsor, revision, domainname, 1);
1535 if (retval == NULL)
1536 /* This means we are out of core. */
1537 return NULL;
1539 if (retval->decided == 0)
1540 _nl_load_domain (retval);
1541 if (retval->data == NULL)
1543 int cnt;
1544 for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
1546 if (retval->successor[cnt]->decided == 0)
1547 _nl_load_domain (retval->successor[cnt]);
1548 if (retval->successor[cnt]->data != NULL)
1549 break;
1553 /* The room for an alias was dynamically allocated. Free it now. */
1554 if (alias_value != NULL)
1555 free (locale);
1557 return retval;
1560 #ifdef _LIBC
1561 static void __attribute__ ((unused))
1562 free_mem (void)
1564 struct loaded_l10nfile *runp = _nl_loaded_domains;
1566 while (runp != NULL)
1568 struct loaded_l10nfile *here = runp;
1569 if (runp->data != NULL)
1570 _nl_unload_domain ((struct loaded_domain *) runp->data);
1571 runp = runp->next;
1572 free (here);
1576 text_set_element (__libc_subfreeres, free_mem);
1577 #endif
1579 /* End of finddomain.c */
1581 /* Begin of dcgettext.c */
1583 /* Implementation of the dcgettext(3) function.
1584 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. */
1586 #ifndef errno
1587 extern int errno;
1588 #endif
1589 #ifndef __set_errno
1590 # define __set_errno(val) errno = (val)
1591 #endif
1593 #if defined STDC_HEADERS || defined _LIBC
1594 #else
1595 char *getenv ();
1596 # ifdef HAVE_MALLOC_H
1597 # else
1598 void free ();
1599 # endif
1600 #endif
1602 #if defined HAVE_STRING_H || defined _LIBC
1603 # ifndef _GNU_SOURCE
1604 # define _GNU_SOURCE 1
1605 # endif
1606 #else
1607 #endif
1608 #if !HAVE_STRCHR && !defined _LIBC
1609 # ifndef strchr
1610 # define strchr index
1611 # endif
1612 #endif
1614 #if defined HAVE_UNISTD_H || defined _LIBC
1615 #endif
1617 #ifdef _LIBC
1618 #else
1619 #endif
1621 /* Interrupt of dcgettext.c */
1623 /* Begin of hash-string.h */
1625 /* Implements a string hashing function.
1626 Copyright (C) 1995, 1997 Free Software Foundation, Inc. */
1628 #ifndef PARAMS
1629 # if __STDC__
1630 # define PARAMS(Args) Args
1631 # else
1632 # define PARAMS(Args) ()
1633 # endif
1634 #endif
1636 /* We assume to have `unsigned long int' value with at least 32 bits. */
1637 #define HASHWORDBITS 32
1639 /* Defines the so called `hashpjw' function by P.J. Weinberger
1640 [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
1641 1986, 1987 Bell Telephone Laboratories, Inc.] */
1642 static unsigned long hash_string PARAMS ((const char *__str_param));
1644 static inline unsigned long
1645 hash_string (str_param)
1646 const char *str_param;
1648 unsigned long int hval, g;
1649 const char *str = str_param;
1651 /* Compute the hash value for the given string. */
1652 hval = 0;
1653 while (*str != '\0')
1655 hval <<= 4;
1656 hval += (unsigned long) *str++;
1657 g = hval & ((unsigned long) 0xf << (HASHWORDBITS - 4));
1658 if (g != 0)
1660 hval ^= g >> (HASHWORDBITS - 8);
1661 hval ^= g;
1664 return hval;
1667 /* End of hash-string.h */
1669 /* Resume of dcgettext.c */
1671 #ifdef _LIBC
1672 /* Rename the non ANSI C functions. This is required by the standard
1673 because some ANSI C functions will require linking with this object
1674 file and the name space must not be polluted. */
1675 # define getcwd __getcwd
1676 # ifndef stpcpy
1677 # define stpcpy __stpcpy
1678 # endif
1679 #else
1680 # if !defined HAVE_GETCWD
1681 char *getwd ();
1682 # define getcwd(buf, max) getwd (buf)
1683 # else
1684 char *getcwd ();
1685 # endif
1686 # ifndef HAVE_STPCPY
1687 static char *stpcpy PARAMS ((char *dest, const char *src));
1688 # endif
1689 #endif
1691 /* Amount to increase buffer size by in each try. */
1692 #define PATH_INCR 32
1694 /* The following is from pathmax.h. */
1695 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
1696 PATH_MAX but might cause redefinition warnings when sys/param.h is
1697 later included (as on MORE/BSD 4.3). */
1698 #if defined(_POSIX_VERSION) || (defined(HAVE_LIMITS_H) && !defined(__GNUC__))
1699 #endif
1701 #ifndef _POSIX_PATH_MAX
1702 # define _POSIX_PATH_MAX 255
1703 #endif
1705 #if !defined(PATH_MAX) && defined(_PC_PATH_MAX)
1706 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
1707 #endif
1709 /* Don't include sys/param.h if it already has been. */
1710 #if defined(HAVE_SYS_PARAM_H) && !defined(PATH_MAX) && !defined(MAXPATHLEN)
1711 # include <sys/param.h>
1712 #endif
1714 #if !defined(PATH_MAX) && defined(MAXPATHLEN)
1715 # define PATH_MAX MAXPATHLEN
1716 #endif
1718 #ifndef PATH_MAX
1719 # define PATH_MAX _POSIX_PATH_MAX
1720 #endif
1722 /* XPG3 defines the result of `setlocale (category, NULL)' as:
1723 ``Directs `setlocale()' to query `category' and return the current
1724 setting of `local'.''
1725 However it does not specify the exact format. And even worse: POSIX
1726 defines this not at all. So we can use this feature only on selected
1727 system (e.g. those using GNU C Library). */
1728 #ifdef _LIBC
1729 # define HAVE_LOCALE_NULL
1730 #endif
1732 /* Name of the default domain used for gettext(3) prior any call to
1733 textdomain(3). The default value for this is "messages". */
1734 static const char _nl_default_default_domain[] = "messages";
1736 /* Value used as the default domain for gettext(3). */
1737 static const char *_nl_current_default_domain = _nl_default_default_domain;
1739 /* Contains the default location of the message catalogs. */
1740 static const char _nl_default_dirname[] = LOCALEDIR;
1742 /* List with bindings of specific domains created by bindtextdomain()
1743 calls. */
1744 static struct binding *_nl_domain_bindings;
1746 /* Prototypes for local functions. */
1747 static char *find_msg PARAMS ((struct loaded_l10nfile *domain_file,
1748 const char *msgid)) internal_function;
1749 static const char *category_to_name PARAMS ((int category)) internal_function;
1750 static const char *guess_category_value PARAMS ((int category,
1751 const char *categoryname))
1752 internal_function;
1754 /* Names for the libintl functions are a problem. They must not clash
1755 with existing names and they should follow ANSI C. But this source
1756 code is also used in GNU C Library where the names have a __
1757 prefix. So we have to make a difference here. */
1758 #ifdef _LIBC
1759 # define DCGETTEXT __dcgettext
1760 #else
1761 # define DCGETTEXT dcgettext__
1762 #endif
1764 /* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
1765 locale. */
1766 char *
1767 DCGETTEXT (domainname, msgid, category)
1768 const char *domainname;
1769 const char *msgid;
1770 int category;
1772 #ifndef HAVE_ALLOCA
1773 struct block_list *block_list = NULL;
1774 #endif
1775 struct loaded_l10nfile *domain;
1776 struct binding *binding;
1777 const char *categoryname;
1778 const char *categoryvalue;
1779 char *dirname, *xdomainname;
1780 char *single_locale;
1781 char *retval;
1782 int saved_errno = errno;
1784 /* If no real MSGID is given return NULL. */
1785 if (msgid == NULL)
1786 return NULL;
1788 /* If DOMAINNAME is NULL, we are interested in the default domain. If
1789 CATEGORY is not LC_MESSAGES this might not make much sense but the
1790 defintion left this undefined. */
1791 if (domainname == NULL)
1792 domainname = _nl_current_default_domain;
1794 /* First find matching binding. */
1795 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
1797 int compare = strcmp (domainname, binding->domainname);
1798 if (compare == 0)
1799 /* We found it! */
1800 break;
1801 if (compare < 0)
1803 /* It is not in the list. */
1804 binding = NULL;
1805 break;
1809 if (binding == NULL)
1810 dirname = (char *) _nl_default_dirname;
1811 else if (binding->dirname[0] == '/')
1812 dirname = binding->dirname;
1813 else
1815 /* We have a relative path. Make it absolute now. */
1816 size_t dirname_len = strlen (binding->dirname) + 1;
1817 size_t path_max;
1818 char *ret;
1820 path_max = (unsigned) PATH_MAX;
1821 path_max += 2; /* The getcwd docs say to do this. */
1823 dirname = (char *) alloca (path_max + dirname_len);
1824 ADD_BLOCK (block_list, dirname);
1826 __set_errno (0);
1827 while ((ret = getcwd (dirname, path_max)) == NULL && errno == ERANGE)
1829 path_max += PATH_INCR;
1830 dirname = (char *) alloca (path_max + dirname_len);
1831 ADD_BLOCK (block_list, dirname);
1832 __set_errno (0);
1835 if (ret == NULL)
1837 /* We cannot get the current working directory. Don't signal an
1838 error but simply return the default string. */
1839 FREE_BLOCKS (block_list);
1840 __set_errno (saved_errno);
1841 return (char *) msgid;
1844 stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
1847 /* Now determine the symbolic name of CATEGORY and its value. */
1848 categoryname = category_to_name (category);
1849 categoryvalue = guess_category_value (category, categoryname);
1851 xdomainname = (char *) alloca (strlen (categoryname)
1852 + strlen (domainname) + 5);
1853 ADD_BLOCK (block_list, xdomainname);
1855 stpcpy (stpcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
1856 domainname),
1857 ".mo");
1859 /* Creating working area. */
1860 single_locale = (char *) alloca (strlen (categoryvalue) + 1);
1861 ADD_BLOCK (block_list, single_locale);
1863 /* Search for the given string. This is a loop because we perhaps
1864 got an ordered list of languages to consider for th translation. */
1865 while (1)
1867 /* Make CATEGORYVALUE point to the next element of the list. */
1868 while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
1869 ++categoryvalue;
1870 if (categoryvalue[0] == '\0')
1872 /* The whole contents of CATEGORYVALUE has been searched but
1873 no valid entry has been found. We solve this situation
1874 by implicitly appending a "C" entry, i.e. no translation
1875 will take place. */
1876 single_locale[0] = 'C';
1877 single_locale[1] = '\0';
1879 else
1881 char *cp = single_locale;
1882 while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
1883 *cp++ = *categoryvalue++;
1884 *cp = '\0';
1887 /* If the current locale value is C (or POSIX) we don't load a
1888 domain. Return the MSGID. */
1889 if (strcmp (single_locale, "C") == 0
1890 || strcmp (single_locale, "POSIX") == 0)
1892 FREE_BLOCKS (block_list);
1893 __set_errno (saved_errno);
1894 return (char *) msgid;
1897 /* Find structure describing the message catalog matching the
1898 DOMAINNAME and CATEGORY. */
1899 domain = _nl_find_domain (dirname, single_locale, xdomainname);
1901 if (domain != NULL)
1903 retval = find_msg (domain, msgid);
1905 if (retval == NULL)
1907 int cnt;
1909 for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
1911 retval = find_msg (domain->successor[cnt], msgid);
1913 if (retval != NULL)
1914 break;
1918 if (retval != NULL)
1920 FREE_BLOCKS (block_list);
1921 __set_errno (saved_errno);
1922 return retval;
1926 /* NOTREACHED */
1929 #ifdef _LIBC
1930 /* Alias for function name in GNU C Library. */
1931 #endif
1933 static char *
1934 internal_function
1935 find_msg (domain_file, msgid)
1936 struct loaded_l10nfile *domain_file;
1937 const char *msgid;
1939 size_t top, act, bottom;
1940 struct loaded_domain *domain;
1942 if (domain_file->decided == 0)
1943 _nl_load_domain (domain_file);
1945 if (domain_file->data == NULL)
1946 return NULL;
1948 domain = (struct loaded_domain *) domain_file->data;
1950 /* Locate the MSGID and its translation. */
1951 if (domain->hash_size > 2 && domain->hash_tab != NULL)
1953 /* Use the hashing table. */
1954 nls_uint32 len = strlen (msgid);
1955 nls_uint32 hash_val = hash_string (msgid);
1956 nls_uint32 idx = hash_val % domain->hash_size;
1957 nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
1958 nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
1960 if (nstr == 0)
1961 /* Hash table entry is empty. */
1962 return NULL;
1964 if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
1965 && strcmp (msgid,
1966 domain->data + W (domain->must_swap,
1967 domain->orig_tab[nstr - 1].offset)) == 0)
1968 return (char *) domain->data + W (domain->must_swap,
1969 domain->trans_tab[nstr - 1].offset);
1971 while (1)
1973 if (idx >= domain->hash_size - incr)
1974 idx -= domain->hash_size - incr;
1975 else
1976 idx += incr;
1978 nstr = W (domain->must_swap, domain->hash_tab[idx]);
1979 if (nstr == 0)
1980 /* Hash table entry is empty. */
1981 return NULL;
1983 if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
1984 && strcmp (msgid,
1985 domain->data + W (domain->must_swap,
1986 domain->orig_tab[nstr - 1].offset))
1987 == 0)
1988 return (char *) domain->data
1989 + W (domain->must_swap, domain->trans_tab[nstr - 1].offset);
1991 /* NOTREACHED */
1994 /* Now we try the default method: binary search in the sorted
1995 array of messages. */
1996 bottom = 0;
1997 top = domain->nstrings;
1998 while (bottom < top)
2000 int cmp_val;
2002 act = (bottom + top) / 2;
2003 cmp_val = strcmp (msgid, domain->data
2004 + W (domain->must_swap,
2005 domain->orig_tab[act].offset));
2006 if (cmp_val < 0)
2007 top = act;
2008 else if (cmp_val > 0)
2009 bottom = act + 1;
2010 else
2011 break;
2014 /* If an translation is found return this. */
2015 return bottom >= top ? NULL : (char *) domain->data
2016 + W (domain->must_swap,
2017 domain->trans_tab[act].offset);
2020 /* Return string representation of locale CATEGORY. */
2021 static const char *
2022 internal_function
2023 category_to_name (category)
2024 int category;
2026 const char *retval;
2028 switch (category)
2030 #ifdef LC_COLLATE
2031 case LC_COLLATE:
2032 retval = "LC_COLLATE";
2033 break;
2034 #endif
2035 #ifdef LC_CTYPE
2036 case LC_CTYPE:
2037 retval = "LC_CTYPE";
2038 break;
2039 #endif
2040 #ifdef LC_MONETARY
2041 case LC_MONETARY:
2042 retval = "LC_MONETARY";
2043 break;
2044 #endif
2045 #ifdef LC_NUMERIC
2046 case LC_NUMERIC:
2047 retval = "LC_NUMERIC";
2048 break;
2049 #endif
2050 #ifdef LC_TIME
2051 case LC_TIME:
2052 retval = "LC_TIME";
2053 break;
2054 #endif
2055 #ifdef LC_MESSAGES
2056 case LC_MESSAGES:
2057 retval = "LC_MESSAGES";
2058 break;
2059 #endif
2060 #ifdef LC_RESPONSE
2061 case LC_RESPONSE:
2062 retval = "LC_RESPONSE";
2063 break;
2064 #endif
2065 #ifdef LC_ALL
2066 case LC_ALL:
2067 /* This might not make sense but is perhaps better than any other
2068 value. */
2069 retval = "LC_ALL";
2070 break;
2071 #endif
2072 default:
2073 /* If you have a better idea for a default value let me know. */
2074 retval = "LC_XXX";
2077 return retval;
2080 /* Guess value of current locale from value of the environment variables. */
2081 static const char *
2082 internal_function
2083 guess_category_value (category, categoryname)
2084 int category;
2085 const char *categoryname;
2087 const char *retval;
2089 /* The highest priority value is the `LANGUAGE' environment
2090 variable. This is a GNU extension. */
2091 retval = getenv ("LANGUAGE");
2092 if (retval != NULL && retval[0] != '\0')
2093 return retval;
2095 /* `LANGUAGE' is not set. So we have to proceed with the POSIX
2096 methods of looking to `LC_ALL', `LC_xxx', and `LANG'. On some
2097 systems this can be done by the `setlocale' function itself. */
2098 #if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
2099 return setlocale (category, NULL);
2100 #else
2101 /* Setting of LC_ALL overwrites all other. */
2102 retval = getenv ("LC_ALL");
2103 if (retval != NULL && retval[0] != '\0')
2104 return retval;
2106 /* Next comes the name of the desired category. */
2107 retval = getenv (categoryname);
2108 if (retval != NULL && retval[0] != '\0')
2109 return retval;
2111 /* Last possibility is the LANG environment variable. */
2112 retval = getenv ("LANG");
2113 if (retval != NULL && retval[0] != '\0')
2114 return retval;
2116 /* We use C as the default domain. POSIX says this is implementation
2117 defined. */
2118 return "C";
2119 #endif
2122 /* We don't want libintl.a to depend on any other library. So we
2123 avoid the non-standard function stpcpy. In GNU C Library this
2124 function is available, though. Also allow the symbol HAVE_STPCPY
2125 to be defined. */
2126 #if !_LIBC && !HAVE_STPCPY
2127 static char *
2128 stpcpy (dest, src)
2129 char *dest;
2130 const char *src;
2132 while ((*dest++ = *src++) != '\0')
2133 /* Do nothing. */ ;
2134 return dest - 1;
2136 #endif
2138 #ifdef _LIBC
2139 /* If we want to free all resources we have to do some work at
2140 program's end. */
2141 static void __attribute__ ((unused))
2142 free_mem (void)
2144 struct binding *runp;
2146 for (runp = _nl_domain_bindings; runp != NULL; runp = runp->next)
2148 free (runp->domainname);
2149 if (runp->dirname != _nl_default_dirname)
2150 /* Yes, this is a pointer comparison. */
2151 free (runp->dirname);
2154 if (_nl_current_default_domain != _nl_default_default_domain)
2155 /* Yes, again a pointer comparison. */
2156 free ((char *) _nl_current_default_domain);
2159 text_set_element (__libc_subfreeres, free_mem);
2160 #endif
2162 /* End of dcgettext.c */
2164 /* Begin of bindtextdom.c */
2166 /* Implementation of the bindtextdomain(3) function
2167 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. */
2169 #if defined STDC_HEADERS || defined _LIBC
2170 #else
2171 # ifdef HAVE_MALLOC_H
2172 # else
2173 void free ();
2174 # endif
2175 #endif
2177 #if defined HAVE_STRING_H || defined _LIBC
2178 #else
2179 # ifndef memcpy
2180 # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
2181 # endif
2182 #endif
2184 #ifdef _LIBC
2185 #else
2186 #endif
2188 /* Contains the default location of the message catalogs. */
2189 /* static const char _nl_default_dirname[]; */
2191 /* List with bindings of specific domains. */
2192 /* static struct binding *_nl_domain_bindings; */
2194 /* Names for the libintl functions are a problem. They must not clash
2195 with existing names and they should follow ANSI C. But this source
2196 code is also used in GNU C Library where the names have a __
2197 prefix. So we have to make a difference here. */
2198 #ifdef _LIBC
2199 # define BINDTEXTDOMAIN __bindtextdomain
2200 # ifndef strdup
2201 # define strdup(str) __strdup (str)
2202 # endif
2203 #else
2204 # define BINDTEXTDOMAIN bindtextdomain__
2205 #endif
2207 /* Specify that the DOMAINNAME message catalog will be found
2208 in DIRNAME rather than in the system locale data base. */
2209 static char *
2210 BINDTEXTDOMAIN (domainname, dirname)
2211 const char *domainname;
2212 const char *dirname;
2214 struct binding *binding;
2216 /* Some sanity checks. */
2217 if (domainname == NULL || domainname[0] == '\0')
2218 return NULL;
2220 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
2222 int compare = strcmp (domainname, binding->domainname);
2223 if (compare == 0)
2224 /* We found it! */
2225 break;
2226 if (compare < 0)
2228 /* It is not in the list. */
2229 binding = NULL;
2230 break;
2234 if (dirname == NULL)
2235 /* The current binding has be to returned. */
2236 return binding == NULL ? (char *) _nl_default_dirname : binding->dirname;
2238 if (binding != NULL)
2240 /* The domain is already bound. If the new value and the old
2241 one are equal we simply do nothing. Otherwise replace the
2242 old binding. */
2243 if (strcmp (dirname, binding->dirname) != 0)
2245 char *new_dirname;
2247 if (strcmp (dirname, _nl_default_dirname) == 0)
2248 new_dirname = (char *) _nl_default_dirname;
2249 else
2251 #if defined _LIBC || defined HAVE_STRDUP
2252 new_dirname = strdup (dirname);
2253 if (new_dirname == NULL)
2254 return NULL;
2255 #else
2256 size_t len = strlen (dirname) + 1;
2257 new_dirname = (char *) malloc (len);
2258 if (new_dirname == NULL)
2259 return NULL;
2261 memcpy (new_dirname, dirname, len);
2262 #endif
2265 if (binding->dirname != _nl_default_dirname)
2266 free (binding->dirname);
2268 binding->dirname = new_dirname;
2271 else
2273 /* We have to create a new binding. */
2274 #if !defined _LIBC && !defined HAVE_STRDUP
2275 size_t len;
2276 #endif
2277 struct binding *new_binding =
2278 (struct binding *) malloc (sizeof (*new_binding));
2280 if (new_binding == NULL)
2281 return NULL;
2283 #if defined _LIBC || defined HAVE_STRDUP
2284 new_binding->domainname = strdup (domainname);
2285 if (new_binding->domainname == NULL)
2286 return NULL;
2287 #else
2288 len = strlen (domainname) + 1;
2289 new_binding->domainname = (char *) malloc (len);
2290 if (new_binding->domainname == NULL)
2291 return NULL;
2292 memcpy (new_binding->domainname, domainname, len);
2293 #endif
2295 if (strcmp (dirname, _nl_default_dirname) == 0)
2296 new_binding->dirname = (char *) _nl_default_dirname;
2297 else
2299 #if defined _LIBC || defined HAVE_STRDUP
2300 new_binding->dirname = strdup (dirname);
2301 if (new_binding->dirname == NULL)
2302 return NULL;
2303 #else
2304 len = strlen (dirname) + 1;
2305 new_binding->dirname = (char *) malloc (len);
2306 if (new_binding->dirname == NULL)
2307 return NULL;
2308 memcpy (new_binding->dirname, dirname, len);
2309 #endif
2312 /* Now enqueue it. */
2313 if (_nl_domain_bindings == NULL
2314 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
2316 new_binding->next = _nl_domain_bindings;
2317 _nl_domain_bindings = new_binding;
2319 else
2321 binding = _nl_domain_bindings;
2322 while (binding->next != NULL
2323 && strcmp (domainname, binding->next->domainname) > 0)
2324 binding = binding->next;
2326 new_binding->next = binding->next;
2327 binding->next = new_binding;
2330 binding = new_binding;
2333 return binding->dirname;
2336 #ifdef _LIBC
2337 /* Alias for function name in GNU C Library. */
2338 #endif
2340 /* End of bindtextdom.c */
2342 /* Begin of dgettext.c */
2344 /* Implementation of the dgettext(3) function
2345 Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. */
2347 #if defined HAVE_LOCALE_H || defined _LIBC
2348 # include <locale.h>
2349 #endif
2351 #ifdef _LIBC
2352 #else
2353 #endif
2355 /* Names for the libintl functions are a problem. They must not clash
2356 with existing names and they should follow ANSI C. But this source
2357 code is also used in GNU C Library where the names have a __
2358 prefix. So we have to make a difference here. */
2359 #ifdef _LIBC
2360 # define DGETTEXT __dgettext
2361 # define DCGETTEXT __dcgettext
2362 #else
2363 # define DGETTEXT dgettext__
2364 # define DCGETTEXT dcgettext__
2365 #endif
2367 /* Look up MSGID in the DOMAINNAME message catalog of the current
2368 LC_MESSAGES locale. */
2369 static char *
2370 DGETTEXT (domainname, msgid)
2371 const char *domainname;
2372 const char *msgid;
2374 return DCGETTEXT (domainname, msgid, LC_MESSAGES);
2377 #ifdef _LIBC
2378 /* Alias for function name in GNU C Library. */
2379 #endif
2381 /* End of dgettext.c */
2383 /* Begin of gettext.c */
2385 /* Implementation of gettext(3) function.
2386 Copyright (C) 1995, 1997 Free Software Foundation, Inc. */
2388 #ifdef _LIBC
2389 # define __need_NULL
2390 # include <stddef.h>
2391 #else
2392 # ifdef STDC_HEADERS
2393 # include <stdlib.h> /* Just for NULL. */
2394 # else
2395 # ifdef HAVE_STRING_H
2396 # else
2397 # define NULL ((void *) 0)
2398 # endif
2399 # endif
2400 #endif
2402 #ifdef _LIBC
2403 #else
2404 #endif
2406 /* Names for the libintl functions are a problem. They must not clash
2407 with existing names and they should follow ANSI C. But this source
2408 code is also used in GNU C Library where the names have a __
2409 prefix. So we have to make a difference here. */
2410 #ifdef _LIBC
2411 # define GETTEXT __gettext
2412 # define DGETTEXT __dgettext
2413 #else
2414 # define GETTEXT gettext__
2415 # define DGETTEXT dgettext__
2416 #endif
2418 /* Look up MSGID in the current default message catalog for the current
2419 LC_MESSAGES locale. If not found, returns MSGID itself (the default
2420 text). */
2421 static char *
2422 GETTEXT (msgid)
2423 const char *msgid;
2425 return DGETTEXT (NULL, msgid);
2428 #ifdef _LIBC
2429 /* Alias for function name in GNU C Library. */
2430 #endif
2432 /* End of gettext.c */
2434 /* Begin of textdomain.c */
2436 /* Implementation of the textdomain(3) function.
2437 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
2438 Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
2440 #if defined STDC_HEADERS || defined _LIBC
2441 #endif
2443 #if defined STDC_HEADERS || defined HAVE_STRING_H || defined _LIBC
2444 #else
2445 # ifndef memcpy
2446 # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
2447 # endif
2448 #endif
2450 #ifdef _LIBC
2451 #else
2452 #endif
2454 /* Name of the default text domain. */
2455 /* static const char _nl_default_default_domain[]; */
2457 /* Default text domain in which entries for gettext(3) are to be found. */
2458 /* static const char *_nl_current_default_domain; */
2460 /* Names for the libintl functions are a problem. They must not clash
2461 with existing names and they should follow ANSI C. But this source
2462 code is also used in GNU C Library where the names have a __
2463 prefix. So we have to make a difference here. */
2464 #ifdef _LIBC
2465 # define TEXTDOMAIN __textdomain
2466 # ifndef strdup
2467 # define strdup(str) __strdup (str)
2468 # endif
2469 #else
2470 # define TEXTDOMAIN textdomain__
2471 #endif
2473 /* Set the current default message catalog to DOMAINNAME.
2474 If DOMAINNAME is null, return the current default.
2475 If DOMAINNAME is "", reset to the default of "messages". */
2476 static char *
2477 TEXTDOMAIN (domainname)
2478 const char *domainname;
2480 char *old;
2482 /* A NULL pointer requests the current setting. */
2483 if (domainname == NULL)
2484 return (char *) _nl_current_default_domain;
2486 old = (char *) _nl_current_default_domain;
2488 /* If domain name is the null string set to default domain "messages". */
2489 if (domainname[0] == '\0'
2490 || strcmp (domainname, _nl_default_default_domain) == 0)
2491 _nl_current_default_domain = _nl_default_default_domain;
2492 else
2494 /* If the following malloc fails `_nl_current_default_domain'
2495 will be NULL. This value will be returned and so signals we
2496 are out of core. */
2497 #if defined _LIBC || defined HAVE_STRDUP
2498 _nl_current_default_domain = strdup (domainname);
2499 #else
2500 size_t len = strlen (domainname) + 1;
2501 char *cp = (char *) malloc (len);
2502 if (cp != NULL)
2503 memcpy (cp, domainname, len);
2504 _nl_current_default_domain = cp;
2505 #endif
2508 if (old != _nl_default_default_domain)
2509 free (old);
2511 return (char *) _nl_current_default_domain;
2514 #ifdef _LIBC
2515 /* Alias for function name in GNU C Library. */
2516 #endif
2518 /* End of textdomain.c */
2520 /* Begin of intl-compat.c */
2522 /* intl-compat.c - Stub functions to call gettext functions from GNU gettext
2523 Library.
2524 Copyright (C) 1995 Software Foundation, Inc. */
2526 #undef gettext
2527 #undef dgettext
2528 #undef dcgettext
2529 #undef textdomain
2530 #undef bindtextdomain
2532 char *
2533 bindtextdomain (domainname, dirname)
2534 const char *domainname;
2535 const char *dirname;
2537 return bindtextdomain__ (domainname, dirname);
2540 char *
2541 dcgettext (domainname, msgid, category)
2542 const char *domainname;
2543 const char *msgid;
2544 int category;
2546 return dcgettext__ (domainname, msgid, category);
2549 char *
2550 dgettext (domainname, msgid)
2551 const char *domainname;
2552 const char *msgid;
2554 return dgettext__ (domainname, msgid);
2557 char *
2558 gettext (msgid)
2559 const char *msgid;
2561 return gettext__ (msgid);
2564 char *
2565 textdomain (domainname)
2566 const char *domainname;
2568 return textdomain__ (domainname);
2571 /* End of intl-compat.c */