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)
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. */
26 # define alloca __builtin_alloca
27 # define HAVE_ALLOCA 1
29 # if defined HAVE_ALLOCA_H || defined _LIBC
42 #if defined HAVE_STRING_H || defined _LIBC
44 # define _GNU_SOURCE 1
50 # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
53 #if !HAVE_STRCHR && !defined _LIBC
59 #if defined STDC_HEADERS || defined _LIBC
68 #if defined _LIBC || defined HAVE_ARGZ_H
72 #include <sys/types.h>
74 #if defined STDC_HEADERS || defined _LIBC
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. */
92 # define PARAMS(args) args
94 # define PARAMS(args) ()
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
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
;
118 struct loaded_l10nfile
*next
;
119 struct loaded_l10nfile
*successor
[1];
122 static const char *_nl_normalize_codeset
PARAMS ((const unsigned char *codeset
,
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
,
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! */
152 # if defined __STDC__ && __STDC__
153 # define NULL ((void *) 0)
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. */
164 # define stpcpy(dest, src) __stpcpy(dest, src)
168 static char *stpcpy
PARAMS ((char *dest
, const char *src
));
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
));
179 argz_count__ (argz
, len
)
186 size_t part_len
= strlen (argz
);
187 argz
+= part_len
+ 1;
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
));
203 argz_stringify__ (argz
, len
, sep
)
210 size_t part_len
= strlen (argz
);
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
,
226 argz_next__ (argz
, argz_len
, entry
)
233 if (entry
< argz
+ argz_len
)
234 entry
= strchr (entry
, '\0') + 1;
236 return entry
>= argz
+ argz_len
? NULL
: (char *) entry
;
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
));
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;
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
;
272 const char *language
;
273 const char *territory
;
275 const char *normalized_codeset
;
276 const char *modifier
;
279 const char *revision
;
280 const char *filename
;
284 struct loaded_l10nfile
*last
= NULL
;
285 struct loaded_l10nfile
*retval
;
290 /* Allocate room for the full file name. */
291 abs_filename
= (char *) malloc (dirlist_len
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
)
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);
323 cp
= stpcpy (cp
, language
);
325 if ((mask
& TERRITORY
) != 0)
328 cp
= stpcpy (cp
, territory
);
330 if ((mask
& XPG_CODESET
) != 0)
333 cp
= stpcpy (cp
, codeset
);
335 if ((mask
& XPG_NORM_CODESET
) != 0)
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)
350 cp
= stpcpy (cp
, special
);
352 if ((mask
& (CEN_SPONSOR
| CEN_REVISION
)) != 0)
355 if ((mask
& CEN_SPONSOR
) != 0)
356 cp
= stpcpy (cp
, sponsor
);
357 if ((mask
& CEN_REVISION
) != 0)
360 cp
= stpcpy (cp
, revision
);
365 stpcpy (cp
, filename
);
367 /* Look in list of already loaded domains whether it is already
370 for (retval
= *l10nfile_list
; retval
!= NULL
; retval
= retval
->next
)
371 if (retval
->filename
!= NULL
)
373 int compare
= strcmp (retval
->filename
, abs_filename
);
379 /* It's not in the list. */
387 if (retval
!= NULL
|| do_allocate
== 0)
393 retval
= (struct loaded_l10nfile
*)
394 malloc (sizeof (*retval
) + (__argz_count (dirlist
, dirlist_len
)
396 * sizeof (struct loaded_l10nfile
*)));
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));
408 retval
->next
= *l10nfile_list
;
409 *l10nfile_list
= retval
;
413 retval
->next
= last
->next
;
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. */
430 while ((dir
= __argz_next ((char *) dirlist
, dirlist_len
, dir
))
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
;
443 /* Normalize codeset name. There is no standard for the codeset
444 names. Normalization allows the user to use any of the common
447 _nl_normalize_codeset (codeset
, name_len
)
448 const unsigned char *codeset
;
457 for (cnt
= 0; cnt
< name_len
; ++cnt
)
458 if (isalnum (codeset
[cnt
]))
462 if (isalpha (codeset
[cnt
]))
466 retval
= (char *) malloc ((only_digit
? 3 : 0) + len
+ 1);
471 wp
= stpcpy (retval
, "iso");
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
];
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
497 #if defined HAVE_STRING_H || defined _LIBC
502 _nl_explode_name (name
, language
, modifier
, territory
, codeset
,
503 normalized_codeset
, special
, sponsor
, revision
)
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
;
521 *normalized_codeset
= 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. */
531 *language
= cp
= name
;
532 while (cp
[0] != '\0' && cp
[0] != '_' && cp
[0] != '@'
533 && cp
[0] != '+' && cp
[0] != ',')
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. */
546 while (cp
[0] != '\0' && cp
[0] != '.' && cp
[0] != '@'
547 && cp
[0] != '+' && cp
[0] != ',' && cp
[0] != '_')
554 /* Next is the codeset. */
559 while (cp
[0] != '\0' && cp
[0] != '@')
564 if (*codeset
!= cp
&& (*codeset
)[0] != '\0')
566 *normalized_codeset
= _nl_normalize_codeset ((const unsigned
569 if (strcmp (*codeset
, *normalized_codeset
) == 0)
570 free ((char *) *normalized_codeset
);
572 mask
|= XPG_NORM_CODESET
;
577 if (cp
[0] == '@' || (syntax
!= xpg
&& cp
[0] == '+'))
579 /* Next is the modifier. */
580 syntax
= cp
[0] == '@' ? xpg
: cen
;
584 while (syntax
== cen
&& cp
[0] != '\0' && cp
[0] != '+'
585 && cp
[0] != ',' && cp
[0] != '_')
588 mask
|= XPG_MODIFIER
| CEN_AUDIENCE
;
591 if (syntax
!= xpg
&& (cp
[0] == '+' || cp
[0] == ',' || cp
[0] == '_'))
597 /* Next is special application (CEN syntax). */
601 while (cp
[0] != '\0' && cp
[0] != ',' && cp
[0] != '_')
609 /* Next is sponsor (CEN syntax). */
613 while (cp
[0] != '\0' && cp
[0] != '_')
621 /* Next is revision (CEN syntax). */
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. */
633 if (*territory
!= NULL
&& (*territory
)[0] == '\0')
636 if (*codeset
!= NULL
&& (*codeset
)[0] == '\0')
637 mask
&= ~XPG_CODESET
;
639 if (*modifier
!= NULL
&& (*modifier
)[0] == '\0')
640 mask
&= ~XPG_MODIFIER
;
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. */
654 #include <sys/stat.h>
656 #if defined STDC_HEADERS || defined _LIBC
659 #if defined HAVE_UNISTD_H || defined _LIBC
663 #if (defined HAVE_MMAP && defined HAVE_MUNMAP) || defined _LIBC
664 # include <sys/mman.h>
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. */
676 #if HAVE_LIMITS_H || _LIBC
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. */
695 # define UINT_MAX_32_BITS 4294967295U
697 # define UINT_MAX_32_BITS 0xFFFFFFFF
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. */
706 # define UINT_MAX UINT_MAX_32_BITS
709 #if UINT_MAX == UINT_MAX_32_BITS
710 typedef unsigned nls_uint32
;
712 # if USHRT_MAX == UINT_MAX_32_BITS
713 typedef unsigned short nls_uint32
;
715 # if ULONG_MAX == UINT_MAX_32_BITS
716 typedef unsigned long nls_uint32
;
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."
725 /* Header for binary .mo file format. */
726 struct mo_file_header
728 /* The magic number. */
730 /* The revision number of the file format. */
732 /* The number of strings pairs. */
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
;
746 /* Length of addressed string. */
748 /* Offset of string in file. */
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. */
769 # define PARAMS(args) args
771 # define PARAMS(args) ()
775 #ifndef internal_function
776 # define internal_function
780 # define W(flag, data) ((flag) ? SWAP (data) : (data))
784 # include <byteswap.h>
785 # define SWAP(i) bswap_32 (i)
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
795 SWAP (i
) nls_uint32 i
;
798 return (i
<< 24) | ((i
& 0xff00) << 8) | ((i
>> 8) & 0xff00) | (i
>> 24);
809 struct string_desc
*orig_tab
;
810 struct string_desc
*trans_tab
;
811 nls_uint32 hash_size
;
812 nls_uint32
*hash_tab
;
817 struct binding
*next
;
822 static struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
824 const char *__domainname))
826 static void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain))
828 static void _nl_unload_domain PARAMS ((struct loaded_domain *__domain))
831 #endif /* gettextP.h */
833 /* End of gettextP.h */
835 /* Resume of loadmsgcat.c */
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. */
842 # define close __close
845 # define munmap __munmap
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. */
857 _nl_load_domain (domain_file
)
858 struct loaded_l10nfile
*domain_file
;
863 struct mo_file_header
*data
= (struct mo_file_header
*) -1;
864 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
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
877 if (domain_file
->filename
== NULL
)
880 /* Try to open the addressed file. */
881 fd
= open (domain_file
->filename
, O_RDONLY
);
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. */
895 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
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
,
902 if (data
!= (struct mo_file_header
*) -1)
904 /* mmap() call was successful. */
910 /* If the data is not yet available (i.e. mmap'ed) we try to load
912 if (data
== (struct mo_file_header
*) -1)
917 data
= (struct mo_file_header
*) malloc (size
);
922 read_ptr
= (char *) data
;
925 long int nb
= (long int) read (fd
, read_ptr
, to_read
);
940 /* Using the magic number we can test whether it really is a message
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) \
948 munmap ((caddr_t
) data
, size
);
956 = (struct loaded_domain
*) malloc (sizeof (struct loaded_domain
));
957 if (domain_file
->data
== NULL
)
960 domain
= (struct loaded_domain
*) domain_file
->data
;
961 domain
->data
= (char *) data
;
962 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
964 domain
->use_mmap
= use_mmap
;
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
))
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
));
983 /* This is an illegal revision. */
984 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
987 munmap ((caddr_t
) data
, size
);
992 domain_file
->data
= NULL
;
996 /* Show that one domain is changed. This might make some cached
997 translations invalid. */
1004 _nl_unload_domain (domain
)
1005 struct loaded_domain
*domain
;
1007 if (domain
->use_mmap
)
1008 munmap ((caddr_t
) domain
->data
, domain
->mmap_size
);
1010 free ((void *) domain
->data
);
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
1027 # ifdef HAVE_MALLOC_H
1028 # include <malloc.h>
1034 #if defined HAVE_STRING_H || defined _LIBC
1035 # ifndef _GNU_SOURCE
1036 # define _GNU_SOURCE 1
1040 # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
1043 #if !HAVE_STRCHR && !defined _LIBC
1045 # define strchr index
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
);
1064 /* For those loosing systems which don't have `alloca' we have to add
1065 some additional code emulating it. */
1067 /* Nothing has to be done. */
1068 # define ADD_BLOCK(list, address) /* nothing */
1069 # define FREE_BLOCKS(list) /* nothing */
1074 struct block_list
*next
;
1076 # define ADD_BLOCK(list, addr) \
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 \
1081 if (newp != NULL) { \
1082 newp->address = (addr); \
1083 newp->next = (list); \
1087 # define FREE_BLOCKS(list) \
1089 while (list != NULL) { \
1090 struct block_list *old = list; \
1091 list = list->next; \
1096 # define alloca(size) (malloc (size))
1097 #endif /* have alloca */
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
))
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
));
1120 _nl_expand_alias (name
)
1123 static const char *locale_alias_path
= ALIASPATH
;
1124 struct alias_map
*retval
;
1125 const char *result
= NULL
;
1129 __libc_lock_lock (lock
);
1134 struct alias_map item
;
1139 retval
= (struct alias_map
*) bsearch (&item
, map
, nmap
,
1140 sizeof (struct alias_map
),
1141 (int (*) PARAMS ((const void *,
1147 /* We really found an alias. Return the value. */
1150 result
= retval
->value
;
1154 /* Perhaps we can find another alias file. */
1156 while (added
== 0 && locale_alias_path
[0] != '\0')
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
);
1174 __libc_lock_unlock (lock
);
1182 read_alias_file (fname
, fname_len
)
1187 struct block_list
*block_list
= NULL
;
1192 static const char aliasfile
[] = "/locale.alias";
1194 full_fname
= (char *) alloca (fname_len
+ sizeof aliasfile
);
1195 ADD_BLOCK (block_list
, full_fname
);
1197 mempcpy (mempcpy (full_fname
, fname
, fname_len
),
1198 aliasfile
, sizeof aliasfile
);
1200 memcpy (full_fname
, fname
, fname_len
);
1201 memcpy (&full_fname
[fname_len
], aliasfile
, sizeof aliasfile
);
1204 fp
= fopen (full_fname
, "r");
1207 FREE_BLOCKS (block_list
);
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
1219 unsigned char buf
[BUFSIZ
];
1220 unsigned char *alias
;
1221 unsigned char *value
;
1224 if (fgets ((char *)buf
, sizeof buf
, fp
) == NULL
)
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. */
1238 while (strchr (altbuf
, '\n') == NULL
);
1242 /* Ignore leading white space. */
1243 while (isspace (cp
[0]))
1246 /* A leading '#' signals a comment line. */
1247 if (cp
[0] != '\0' && cp
[0] != '#')
1250 while (cp
[0] != '\0' && !isspace (cp
[0]))
1252 /* Terminate alias name. */
1256 /* Now look for the beginning of the value. */
1257 while (isspace (cp
[0]))
1266 while (cp
[0] != '\0' && !isspace (cp
[0]))
1268 /* Terminate value. */
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. */
1277 else if (cp
[0] != '\0')
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
);
1298 string_space
= new_pool
;
1299 string_space_max
= new_size
;
1302 map
[nmap
].alias
= memcpy (&string_space
[string_space_act
],
1304 string_space_act
+= alias_len
;
1306 map
[nmap
].value
= memcpy (&string_space
[string_space_act
],
1308 string_space_act
+= value_len
;
1316 /* Should we test for ferror()? I think we have to silently ignore
1317 errors. --drepper */
1321 qsort (map
, nmap
, sizeof (struct alias_map
),
1322 (int (*) PARAMS ((const void *, const void *))) alias_compare
);
1324 FREE_BLOCKS (block_list
);
1329 extend_alias_table ()
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. */
1346 static void __attribute__ ((unused
))
1349 if (string_space
!= NULL
)
1350 free (string_space
);
1354 text_set_element (__libc_subfreeres
, free_mem
);
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
);
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
;
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
;
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. */
1399 #if defined STDC_HEADERS || defined _LIBC
1401 # ifdef HAVE_MALLOC_H
1407 #if defined HAVE_STRING_H || defined _LIBC
1410 # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
1413 #if !HAVE_STRCHR && !defined _LIBC
1415 # define strchr index
1419 #if defined HAVE_UNISTD_H || defined _LIBC
1423 # include <libintl.h>
1425 # include "gettext.h"
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
*
1436 _nl_find_domain (dirname
, locale
, domainname
)
1437 const char *dirname
;
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
;
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:
1469 (5) normalized codeset
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);
1481 /* We know something about this locale. */
1484 if (retval
->decided
== 0)
1485 _nl_load_domain (retval
);
1487 if (retval
->data
!= NULL
)
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
)
1498 return cnt
>= 0 ? retval
: NULL
;
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
1505 alias_value
= _nl_expand_alias (locale
);
1506 if (alias_value
!= NULL
)
1508 #if defined _LIBC || defined HAVE_STRDUP
1509 locale
= strdup (alias_value
);
1513 size_t len
= strlen (alias_value
) + 1;
1514 locale
= (char *) malloc (len
);
1518 memcpy (locale
, alias_value
, len
);
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
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);
1536 /* This means we are out of core. */
1539 if (retval
->decided
== 0)
1540 _nl_load_domain (retval
);
1541 if (retval
->data
== NULL
)
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
)
1553 /* The room for an alias was dynamically allocated. Free it now. */
1554 if (alias_value
!= NULL
)
1561 static void __attribute__ ((unused
))
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
);
1576 text_set_element (__libc_subfreeres
, free_mem
);
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. */
1590 # define __set_errno(val) errno = (val)
1593 #if defined STDC_HEADERS || defined _LIBC
1596 # ifdef HAVE_MALLOC_H
1602 #if defined HAVE_STRING_H || defined _LIBC
1603 # ifndef _GNU_SOURCE
1604 # define _GNU_SOURCE 1
1608 #if !HAVE_STRCHR && !defined _LIBC
1610 # define strchr index
1614 #if defined HAVE_UNISTD_H || defined _LIBC
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. */
1630 # define PARAMS(Args) Args
1632 # define PARAMS(Args) ()
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. */
1653 while (*str
!= '\0')
1656 hval
+= (unsigned long) *str
++;
1657 g
= hval
& ((unsigned long) 0xf << (HASHWORDBITS
- 4));
1660 hval
^= g
>> (HASHWORDBITS
- 8);
1667 /* End of hash-string.h */
1669 /* Resume of dcgettext.c */
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
1677 # define stpcpy __stpcpy
1680 # if !defined HAVE_GETCWD
1682 # define getcwd(buf, max) getwd (buf)
1686 # ifndef HAVE_STPCPY
1687 static char *stpcpy
PARAMS ((char *dest
, const char *src
));
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__))
1701 #ifndef _POSIX_PATH_MAX
1702 # define _POSIX_PATH_MAX 255
1705 #if !defined(PATH_MAX) && defined(_PC_PATH_MAX)
1706 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
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>
1714 #if !defined(PATH_MAX) && defined(MAXPATHLEN)
1715 # define PATH_MAX MAXPATHLEN
1719 # define PATH_MAX _POSIX_PATH_MAX
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). */
1729 # define HAVE_LOCALE_NULL
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()
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
))
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. */
1759 # define DCGETTEXT __dcgettext
1761 # define DCGETTEXT dcgettext__
1764 /* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
1767 DCGETTEXT (domainname
, msgid
, category
)
1768 const char *domainname
;
1773 struct block_list
*block_list
= NULL
;
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
;
1782 int saved_errno
= errno
;
1784 /* If no real MSGID is given 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
);
1803 /* It is not in the list. */
1809 if (binding
== NULL
)
1810 dirname
= (char *) _nl_default_dirname
;
1811 else if (binding
->dirname
[0] == '/')
1812 dirname
= binding
->dirname
;
1815 /* We have a relative path. Make it absolute now. */
1816 size_t dirname_len
= strlen (binding
->dirname
) + 1;
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
);
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
);
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
), "/"),
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. */
1867 /* Make CATEGORYVALUE point to the next element of the list. */
1868 while (categoryvalue
[0] != '\0' && categoryvalue
[0] == ':')
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
1876 single_locale
[0] = 'C';
1877 single_locale
[1] = '\0';
1881 char *cp
= single_locale
;
1882 while (categoryvalue
[0] != '\0' && categoryvalue
[0] != ':')
1883 *cp
++ = *categoryvalue
++;
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
);
1903 retval
= find_msg (domain
, msgid
);
1909 for (cnt
= 0; domain
->successor
[cnt
] != NULL
; ++cnt
)
1911 retval
= find_msg (domain
->successor
[cnt
], msgid
);
1920 FREE_BLOCKS (block_list
);
1921 __set_errno (saved_errno
);
1930 /* Alias for function name in GNU C Library. */
1935 find_msg (domain_file
, msgid
)
1936 struct loaded_l10nfile
*domain_file
;
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
)
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
]);
1961 /* Hash table entry is empty. */
1964 if (W (domain
->must_swap
, domain
->orig_tab
[nstr
- 1].length
) == len
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
);
1973 if (idx
>= domain
->hash_size
- incr
)
1974 idx
-= domain
->hash_size
- incr
;
1978 nstr
= W (domain
->must_swap
, domain
->hash_tab
[idx
]);
1980 /* Hash table entry is empty. */
1983 if (W (domain
->must_swap
, domain
->orig_tab
[nstr
- 1].length
) == len
1985 domain
->data
+ W (domain
->must_swap
,
1986 domain
->orig_tab
[nstr
- 1].offset
))
1988 return (char *) domain
->data
1989 + W (domain
->must_swap
, domain
->trans_tab
[nstr
- 1].offset
);
1994 /* Now we try the default method: binary search in the sorted
1995 array of messages. */
1997 top
= domain
->nstrings
;
1998 while (bottom
< top
)
2002 act
= (bottom
+ top
) / 2;
2003 cmp_val
= strcmp (msgid
, domain
->data
2004 + W (domain
->must_swap
,
2005 domain
->orig_tab
[act
].offset
));
2008 else if (cmp_val
> 0)
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. */
2023 category_to_name (category
)
2032 retval
= "LC_COLLATE";
2037 retval
= "LC_CTYPE";
2042 retval
= "LC_MONETARY";
2047 retval
= "LC_NUMERIC";
2057 retval
= "LC_MESSAGES";
2062 retval
= "LC_RESPONSE";
2067 /* This might not make sense but is perhaps better than any other
2073 /* If you have a better idea for a default value let me know. */
2080 /* Guess value of current locale from value of the environment variables. */
2083 guess_category_value (category
, categoryname
)
2085 const char *categoryname
;
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')
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
);
2101 /* Setting of LC_ALL overwrites all other. */
2102 retval
= getenv ("LC_ALL");
2103 if (retval
!= NULL
&& retval
[0] != '\0')
2106 /* Next comes the name of the desired category. */
2107 retval
= getenv (categoryname
);
2108 if (retval
!= NULL
&& retval
[0] != '\0')
2111 /* Last possibility is the LANG environment variable. */
2112 retval
= getenv ("LANG");
2113 if (retval
!= NULL
&& retval
[0] != '\0')
2116 /* We use C as the default domain. POSIX says this is implementation
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
2126 #if !_LIBC && !HAVE_STPCPY
2132 while ((*dest
++ = *src
++) != '\0')
2139 /* If we want to free all resources we have to do some work at
2141 static void __attribute__ ((unused
))
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
);
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
2171 # ifdef HAVE_MALLOC_H
2177 #if defined HAVE_STRING_H || defined _LIBC
2180 # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
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. */
2199 # define BINDTEXTDOMAIN __bindtextdomain
2201 # define strdup(str) __strdup (str)
2204 # define BINDTEXTDOMAIN bindtextdomain__
2207 /* Specify that the DOMAINNAME message catalog will be found
2208 in DIRNAME rather than in the system locale data base. */
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')
2220 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
2222 int compare
= strcmp (domainname
, binding
->domainname
);
2228 /* It is not in the list. */
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
2243 if (strcmp (dirname
, binding
->dirname
) != 0)
2247 if (strcmp (dirname
, _nl_default_dirname
) == 0)
2248 new_dirname
= (char *) _nl_default_dirname
;
2251 #if defined _LIBC || defined HAVE_STRDUP
2252 new_dirname
= strdup (dirname
);
2253 if (new_dirname
== NULL
)
2256 size_t len
= strlen (dirname
) + 1;
2257 new_dirname
= (char *) malloc (len
);
2258 if (new_dirname
== NULL
)
2261 memcpy (new_dirname
, dirname
, len
);
2265 if (binding
->dirname
!= _nl_default_dirname
)
2266 free (binding
->dirname
);
2268 binding
->dirname
= new_dirname
;
2273 /* We have to create a new binding. */
2274 #if !defined _LIBC && !defined HAVE_STRDUP
2277 struct binding
*new_binding
=
2278 (struct binding
*) malloc (sizeof (*new_binding
));
2280 if (new_binding
== NULL
)
2283 #if defined _LIBC || defined HAVE_STRDUP
2284 new_binding
->domainname
= strdup (domainname
);
2285 if (new_binding
->domainname
== NULL
)
2288 len
= strlen (domainname
) + 1;
2289 new_binding
->domainname
= (char *) malloc (len
);
2290 if (new_binding
->domainname
== NULL
)
2292 memcpy (new_binding
->domainname
, domainname
, len
);
2295 if (strcmp (dirname
, _nl_default_dirname
) == 0)
2296 new_binding
->dirname
= (char *) _nl_default_dirname
;
2299 #if defined _LIBC || defined HAVE_STRDUP
2300 new_binding
->dirname
= strdup (dirname
);
2301 if (new_binding
->dirname
== NULL
)
2304 len
= strlen (dirname
) + 1;
2305 new_binding
->dirname
= (char *) malloc (len
);
2306 if (new_binding
->dirname
== NULL
)
2308 memcpy (new_binding
->dirname
, dirname
, len
);
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
;
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
;
2337 /* Alias for function name in GNU C Library. */
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>
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. */
2360 # define DGETTEXT __dgettext
2361 # define DCGETTEXT __dcgettext
2363 # define DGETTEXT dgettext__
2364 # define DCGETTEXT dcgettext__
2367 /* Look up MSGID in the DOMAINNAME message catalog of the current
2368 LC_MESSAGES locale. */
2370 DGETTEXT (domainname
, msgid
)
2371 const char *domainname
;
2374 return DCGETTEXT (domainname
, msgid
, LC_MESSAGES
);
2378 /* Alias for function name in GNU C Library. */
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. */
2389 # define __need_NULL
2390 # include <stddef.h>
2392 # ifdef STDC_HEADERS
2393 # include <stdlib.h> /* Just for NULL. */
2395 # ifdef HAVE_STRING_H
2397 # define NULL ((void *) 0)
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. */
2411 # define GETTEXT __gettext
2412 # define DGETTEXT __dgettext
2414 # define GETTEXT gettext__
2415 # define DGETTEXT dgettext__
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
2425 return DGETTEXT (NULL
, msgid
);
2429 /* Alias for function name in GNU C Library. */
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
2443 #if defined STDC_HEADERS || defined HAVE_STRING_H || defined _LIBC
2446 # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
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. */
2465 # define TEXTDOMAIN __textdomain
2467 # define strdup(str) __strdup (str)
2470 # define TEXTDOMAIN textdomain__
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". */
2477 TEXTDOMAIN (domainname
)
2478 const char *domainname
;
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
;
2494 /* If the following malloc fails `_nl_current_default_domain'
2495 will be NULL. This value will be returned and so signals we
2497 #if defined _LIBC || defined HAVE_STRDUP
2498 _nl_current_default_domain
= strdup (domainname
);
2500 size_t len
= strlen (domainname
) + 1;
2501 char *cp
= (char *) malloc (len
);
2503 memcpy (cp
, domainname
, len
);
2504 _nl_current_default_domain
= cp
;
2508 if (old
!= _nl_default_default_domain
)
2511 return (char *) _nl_current_default_domain
;
2515 /* Alias for function name in GNU C Library. */
2518 /* End of textdomain.c */
2520 /* Begin of intl-compat.c */
2522 /* intl-compat.c - Stub functions to call gettext functions from GNU gettext
2524 Copyright (C) 1995 Software Foundation, Inc. */
2530 #undef bindtextdomain
2533 bindtextdomain (domainname
, dirname
)
2534 const char *domainname
;
2535 const char *dirname
;
2537 return bindtextdomain__ (domainname
, dirname
);
2541 dcgettext (domainname
, msgid
, category
)
2542 const char *domainname
;
2546 return dcgettext__ (domainname
, msgid
, category
);
2550 dgettext (domainname
, msgid
)
2551 const char *domainname
;
2554 return dgettext__ (domainname
, msgid
);
2561 return gettext__ (msgid
);
2565 textdomain (domainname
)
2566 const char *domainname
;
2568 return textdomain__ (domainname
);
2571 /* End of intl-compat.c */