1f7cc78ecSespie /* Handle list of needed message catalogs
2*d2201f2fSdrahn Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
3f7cc78ecSespie Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
4f7cc78ecSespie
5f7cc78ecSespie This program is free software; you can redistribute it and/or modify
6f7cc78ecSespie it under the terms of the GNU General Public License as published by
7f7cc78ecSespie the Free Software Foundation; either version 2, or (at your option)
8f7cc78ecSespie any later version.
9f7cc78ecSespie
10f7cc78ecSespie This program is distributed in the hope that it will be useful,
11f7cc78ecSespie but WITHOUT ANY WARRANTY; without even the implied warranty of
12f7cc78ecSespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13f7cc78ecSespie GNU General Public License for more details.
14f7cc78ecSespie
15f7cc78ecSespie You should have received a copy of the GNU General Public License
16f7cc78ecSespie along with this program; if not, write to the Free Software Foundation,
17f7cc78ecSespie Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18f7cc78ecSespie
19f7cc78ecSespie #ifdef HAVE_CONFIG_H
20f7cc78ecSespie # include <config.h>
21f7cc78ecSespie #endif
22f7cc78ecSespie
23f7cc78ecSespie #include <ctype.h>
24f7cc78ecSespie #include <errno.h>
25f7cc78ecSespie #include <stdio.h>
26f7cc78ecSespie #include <sys/types.h>
27f7cc78ecSespie
28f7cc78ecSespie #if defined STDC_HEADERS || defined _LIBC
29f7cc78ecSespie # include <stdlib.h>
30f7cc78ecSespie #else
31f7cc78ecSespie # ifdef HAVE_MALLOC_H
32f7cc78ecSespie # include <malloc.h>
33f7cc78ecSespie # else
34f7cc78ecSespie void free ();
35f7cc78ecSespie # endif
36f7cc78ecSespie #endif
37f7cc78ecSespie
38f7cc78ecSespie #if defined HAVE_STRING_H || defined _LIBC
39f7cc78ecSespie # include <string.h>
40f7cc78ecSespie #else
41f7cc78ecSespie # include <strings.h>
42f7cc78ecSespie # ifndef memcpy
43f7cc78ecSespie # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
44f7cc78ecSespie # endif
45f7cc78ecSespie #endif
46f7cc78ecSespie #if !HAVE_STRCHR && !defined _LIBC
47f7cc78ecSespie # ifndef strchr
48f7cc78ecSespie # define strchr index
49f7cc78ecSespie # endif
50f7cc78ecSespie #endif
51f7cc78ecSespie
52f7cc78ecSespie #if defined HAVE_UNISTD_H || defined _LIBC
53f7cc78ecSespie # include <unistd.h>
54f7cc78ecSespie #endif
55f7cc78ecSespie
56f7cc78ecSespie #include "gettext.h"
57f7cc78ecSespie #include "gettextP.h"
58f7cc78ecSespie #ifdef _LIBC
59f7cc78ecSespie # include <libintl.h>
60f7cc78ecSespie #else
61f7cc78ecSespie # include "libgettext.h"
62f7cc78ecSespie #endif
63f7cc78ecSespie
64f7cc78ecSespie /* @@ end of prolog @@ */
65f7cc78ecSespie /* List of already loaded domains. */
66f7cc78ecSespie static struct loaded_l10nfile *_nl_loaded_domains;
67f7cc78ecSespie
68f7cc78ecSespie
69f7cc78ecSespie /* Return a data structure describing the message catalog described by
70f7cc78ecSespie the DOMAINNAME and CATEGORY parameters with respect to the currently
71f7cc78ecSespie established bindings. */
72f7cc78ecSespie struct loaded_l10nfile *
73*d2201f2fSdrahn internal_function
_nl_find_domain(dirname,locale,domainname)74f7cc78ecSespie _nl_find_domain (dirname, locale, domainname)
75f7cc78ecSespie const char *dirname;
76f7cc78ecSespie char *locale;
77f7cc78ecSespie const char *domainname;
78f7cc78ecSespie {
79f7cc78ecSespie struct loaded_l10nfile *retval;
80f7cc78ecSespie const char *language;
81f7cc78ecSespie const char *modifier;
82f7cc78ecSespie const char *territory;
83f7cc78ecSespie const char *codeset;
84f7cc78ecSespie const char *normalized_codeset;
85f7cc78ecSespie const char *special;
86f7cc78ecSespie const char *sponsor;
87f7cc78ecSespie const char *revision;
88f7cc78ecSespie const char *alias_value;
89f7cc78ecSespie int mask;
90f7cc78ecSespie
91f7cc78ecSespie /* LOCALE can consist of up to four recognized parts for the XPG syntax:
92f7cc78ecSespie
93f7cc78ecSespie language[_territory[.codeset]][@modifier]
94f7cc78ecSespie
95f7cc78ecSespie and six parts for the CEN syntax:
96f7cc78ecSespie
97f7cc78ecSespie language[_territory][+audience][+special][,[sponsor][_revision]]
98f7cc78ecSespie
99*d2201f2fSdrahn Beside the first part all of them are allowed to be missing. If
100*d2201f2fSdrahn the full specified locale is not found, the less specific one are
101*d2201f2fSdrahn looked for. The various parts will be stripped off according to
102f7cc78ecSespie the following order:
103f7cc78ecSespie (1) revision
104f7cc78ecSespie (2) sponsor
105f7cc78ecSespie (3) special
106f7cc78ecSespie (4) codeset
107f7cc78ecSespie (5) normalized codeset
108f7cc78ecSespie (6) territory
109f7cc78ecSespie (7) audience/modifier
110f7cc78ecSespie */
111f7cc78ecSespie
112f7cc78ecSespie /* If we have already tested for this locale entry there has to
113f7cc78ecSespie be one data set in the list of loaded domains. */
114f7cc78ecSespie retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
115f7cc78ecSespie strlen (dirname) + 1, 0, locale, NULL, NULL,
116f7cc78ecSespie NULL, NULL, NULL, NULL, NULL, domainname, 0);
117f7cc78ecSespie if (retval != NULL)
118f7cc78ecSespie {
119f7cc78ecSespie /* We know something about this locale. */
120f7cc78ecSespie int cnt;
121f7cc78ecSespie
122f7cc78ecSespie if (retval->decided == 0)
123f7cc78ecSespie _nl_load_domain (retval);
124f7cc78ecSespie
125f7cc78ecSespie if (retval->data != NULL)
126f7cc78ecSespie return retval;
127f7cc78ecSespie
128f7cc78ecSespie for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
129f7cc78ecSespie {
130f7cc78ecSespie if (retval->successor[cnt]->decided == 0)
131f7cc78ecSespie _nl_load_domain (retval->successor[cnt]);
132f7cc78ecSespie
133f7cc78ecSespie if (retval->successor[cnt]->data != NULL)
134f7cc78ecSespie break;
135f7cc78ecSespie }
136f7cc78ecSespie return cnt >= 0 ? retval : NULL;
137f7cc78ecSespie /* NOTREACHED */
138f7cc78ecSespie }
139f7cc78ecSespie
140f7cc78ecSespie /* See whether the locale value is an alias. If yes its value
141f7cc78ecSespie *overwrites* the alias name. No test for the original value is
142f7cc78ecSespie done. */
143f7cc78ecSespie alias_value = _nl_expand_alias (locale);
144f7cc78ecSespie if (alias_value != NULL)
145f7cc78ecSespie {
146*d2201f2fSdrahn #if defined _LIBC || defined HAVE_STRDUP
147*d2201f2fSdrahn locale = strdup (alias_value);
148*d2201f2fSdrahn if (locale == NULL)
149*d2201f2fSdrahn return NULL;
150*d2201f2fSdrahn #else
151f7cc78ecSespie size_t len = strlen (alias_value) + 1;
152f7cc78ecSespie locale = (char *) malloc (len);
153f7cc78ecSespie if (locale == NULL)
154f7cc78ecSespie return NULL;
155f7cc78ecSespie
156f7cc78ecSespie memcpy (locale, alias_value, len);
157*d2201f2fSdrahn #endif
158f7cc78ecSespie }
159f7cc78ecSespie
160f7cc78ecSespie /* Now we determine the single parts of the locale name. First
161f7cc78ecSespie look for the language. Termination symbols are `_' and `@' if
162f7cc78ecSespie we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */
163f7cc78ecSespie mask = _nl_explode_name (locale, &language, &modifier, &territory,
164f7cc78ecSespie &codeset, &normalized_codeset, &special,
165f7cc78ecSespie &sponsor, &revision);
166f7cc78ecSespie
167f7cc78ecSespie /* Create all possible locale entries which might be interested in
168f7cc78ecSespie generalization. */
169f7cc78ecSespie retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
170f7cc78ecSespie strlen (dirname) + 1, mask, language, territory,
171f7cc78ecSespie codeset, normalized_codeset, modifier, special,
172f7cc78ecSespie sponsor, revision, domainname, 1);
173f7cc78ecSespie if (retval == NULL)
174f7cc78ecSespie /* This means we are out of core. */
175f7cc78ecSespie return NULL;
176f7cc78ecSespie
177f7cc78ecSespie if (retval->decided == 0)
178f7cc78ecSespie _nl_load_domain (retval);
179f7cc78ecSespie if (retval->data == NULL)
180f7cc78ecSespie {
181f7cc78ecSespie int cnt;
182f7cc78ecSespie for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
183f7cc78ecSespie {
184f7cc78ecSespie if (retval->successor[cnt]->decided == 0)
185f7cc78ecSespie _nl_load_domain (retval->successor[cnt]);
186f7cc78ecSespie if (retval->successor[cnt]->data != NULL)
187f7cc78ecSespie break;
188f7cc78ecSespie }
189f7cc78ecSespie }
190f7cc78ecSespie
191f7cc78ecSespie /* The room for an alias was dynamically allocated. Free it now. */
192f7cc78ecSespie if (alias_value != NULL)
193f7cc78ecSespie free (locale);
194f7cc78ecSespie
195f7cc78ecSespie return retval;
196f7cc78ecSespie }
197*d2201f2fSdrahn
198*d2201f2fSdrahn
199*d2201f2fSdrahn #ifdef _LIBC
200*d2201f2fSdrahn static void __attribute__ ((unused))
free_mem(void)201*d2201f2fSdrahn free_mem (void)
202*d2201f2fSdrahn {
203*d2201f2fSdrahn struct loaded_l10nfile *runp = _nl_loaded_domains;
204*d2201f2fSdrahn
205*d2201f2fSdrahn while (runp != NULL)
206*d2201f2fSdrahn {
207*d2201f2fSdrahn struct loaded_l10nfile *here = runp;
208*d2201f2fSdrahn if (runp->data != NULL)
209*d2201f2fSdrahn _nl_unload_domain ((struct loaded_domain *) runp->data);
210*d2201f2fSdrahn runp = runp->next;
211*d2201f2fSdrahn free (here);
212*d2201f2fSdrahn }
213*d2201f2fSdrahn }
214*d2201f2fSdrahn
215*d2201f2fSdrahn text_set_element (__libc_subfreeres, free_mem);
216*d2201f2fSdrahn #endif
217