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