xref: /netbsd-src/external/gpl2/texinfo/dist/intl/finddomain.c (revision 29619d2afe564e54d657b83e5a3ae89584f83720)
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