xref: /netbsd-src/external/gpl3/gcc/dist/intl/finddomain.c (revision 4fee23f98c45552038ad6b5bd05124a41302fb01)
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