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