xref: /openbsd-src/gnu/usr.bin/texinfo/intl/finddomain.c (revision a1acfa9b69ad64eb720639240c8438f11107dc85)
128ea187bSespie /* Handle list of needed message catalogs
2*a1acfa9bSespie    Copyright (C) 1995-1999, 2000-2001, 2003 Free Software Foundation, Inc.
33fb98d4aSespie    Written by Ulrich Drepper <drepper@gnu.org>, 1995.
4840175f0Skstailey 
53fb98d4aSespie    This program is free software; you can redistribute it and/or modify it
63fb98d4aSespie    under the terms of the GNU Library General Public License as published
73fb98d4aSespie    by the Free Software Foundation; either version 2, or (at your option)
8840175f0Skstailey    any later version.
9840175f0Skstailey 
10840175f0Skstailey    This program is distributed in the hope that it will be useful,
11840175f0Skstailey    but WITHOUT ANY WARRANTY; without even the implied warranty of
123fb98d4aSespie    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
133fb98d4aSespie    Library General Public License for more details.
14840175f0Skstailey 
153fb98d4aSespie    You should have received a copy of the GNU Library General Public
163fb98d4aSespie    License along with this program; if not, write to the Free Software
173fb98d4aSespie    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
183fb98d4aSespie    USA.  */
19840175f0Skstailey 
20840175f0Skstailey #ifdef HAVE_CONFIG_H
21840175f0Skstailey # include <config.h>
22840175f0Skstailey #endif
23840175f0Skstailey 
24840175f0Skstailey #include <stdio.h>
25840175f0Skstailey #include <sys/types.h>
26840175f0Skstailey #include <stdlib.h>
27840175f0Skstailey #include <string.h>
28840175f0Skstailey 
29840175f0Skstailey #if defined HAVE_UNISTD_H || defined _LIBC
30840175f0Skstailey # include <unistd.h>
31840175f0Skstailey #endif
32840175f0Skstailey 
33840175f0Skstailey #include "gettextP.h"
34840175f0Skstailey #ifdef _LIBC
35840175f0Skstailey # include <libintl.h>
36840175f0Skstailey #else
373fb98d4aSespie # include "libgnuintl.h"
38840175f0Skstailey #endif
39840175f0Skstailey 
40840175f0Skstailey /* @@ end of prolog @@ */
41840175f0Skstailey /* List of already loaded domains.  */
42840175f0Skstailey static struct loaded_l10nfile *_nl_loaded_domains;
43840175f0Skstailey 
44840175f0Skstailey 
45840175f0Skstailey /* Return a data structure describing the message catalog described by
46840175f0Skstailey    the DOMAINNAME and CATEGORY parameters with respect to the currently
47840175f0Skstailey    established bindings.  */
48840175f0Skstailey struct loaded_l10nfile *
491cc83814Sespie internal_function
_nl_find_domain(const char * dirname,char * locale,const char * domainname,struct binding * domainbinding)50*a1acfa9bSespie _nl_find_domain (const char *dirname, char *locale,
51*a1acfa9bSespie 		 const char *domainname, struct binding *domainbinding)
52840175f0Skstailey {
53840175f0Skstailey   struct loaded_l10nfile *retval;
54840175f0Skstailey   const char *language;
55840175f0Skstailey   const char *modifier;
56840175f0Skstailey   const char *territory;
57840175f0Skstailey   const char *codeset;
58840175f0Skstailey   const char *normalized_codeset;
59840175f0Skstailey   const char *special;
60840175f0Skstailey   const char *sponsor;
61840175f0Skstailey   const char *revision;
62840175f0Skstailey   const char *alias_value;
63840175f0Skstailey   int mask;
64840175f0Skstailey 
65840175f0Skstailey   /* LOCALE can consist of up to four recognized parts for the XPG syntax:
66840175f0Skstailey 
67840175f0Skstailey 		language[_territory[.codeset]][@modifier]
68840175f0Skstailey 
69840175f0Skstailey      and six parts for the CEN syntax:
70840175f0Skstailey 
7128ea187bSespie 	language[_territory][+audience][+special][,[sponsor][_revision]]
72840175f0Skstailey 
731cc83814Sespie      Beside the first part all of them are allowed to be missing.  If
741cc83814Sespie      the full specified locale is not found, the less specific one are
751cc83814Sespie      looked for.  The various parts will be stripped off according to
76840175f0Skstailey      the following order:
77840175f0Skstailey 		(1) revision
78840175f0Skstailey 		(2) sponsor
79840175f0Skstailey 		(3) special
80840175f0Skstailey 		(4) codeset
81840175f0Skstailey 		(5) normalized codeset
82840175f0Skstailey 		(6) territory
83840175f0Skstailey 		(7) audience/modifier
84840175f0Skstailey    */
85840175f0Skstailey 
86840175f0Skstailey   /* If we have already tested for this locale entry there has to
87840175f0Skstailey      be one data set in the list of loaded domains.  */
88840175f0Skstailey   retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
89840175f0Skstailey 			       strlen (dirname) + 1, 0, locale, NULL, NULL,
90840175f0Skstailey 			       NULL, NULL, NULL, NULL, NULL, domainname, 0);
91840175f0Skstailey   if (retval != NULL)
92840175f0Skstailey     {
93840175f0Skstailey       /* We know something about this locale.  */
94840175f0Skstailey       int cnt;
95840175f0Skstailey 
96840175f0Skstailey       if (retval->decided == 0)
973fb98d4aSespie 	_nl_load_domain (retval, domainbinding);
98840175f0Skstailey 
99840175f0Skstailey       if (retval->data != NULL)
100840175f0Skstailey 	return retval;
101840175f0Skstailey 
102840175f0Skstailey       for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
103840175f0Skstailey 	{
104840175f0Skstailey 	  if (retval->successor[cnt]->decided == 0)
1053fb98d4aSespie 	    _nl_load_domain (retval->successor[cnt], domainbinding);
106840175f0Skstailey 
107840175f0Skstailey 	  if (retval->successor[cnt]->data != NULL)
108840175f0Skstailey 	    break;
109840175f0Skstailey 	}
110840175f0Skstailey       return cnt >= 0 ? retval : NULL;
111840175f0Skstailey       /* NOTREACHED */
112840175f0Skstailey     }
113840175f0Skstailey 
114840175f0Skstailey   /* See whether the locale value is an alias.  If yes its value
115840175f0Skstailey      *overwrites* the alias name.  No test for the original value is
116840175f0Skstailey      done.  */
117840175f0Skstailey   alias_value = _nl_expand_alias (locale);
118840175f0Skstailey   if (alias_value != NULL)
119840175f0Skstailey     {
1201cc83814Sespie #if defined _LIBC || defined HAVE_STRDUP
1211cc83814Sespie       locale = strdup (alias_value);
1221cc83814Sespie       if (locale == NULL)
1231cc83814Sespie 	return NULL;
1241cc83814Sespie #else
125840175f0Skstailey       size_t len = strlen (alias_value) + 1;
126840175f0Skstailey       locale = (char *) malloc (len);
127840175f0Skstailey       if (locale == NULL)
128840175f0Skstailey 	return NULL;
129840175f0Skstailey 
130840175f0Skstailey       memcpy (locale, alias_value, len);
1311cc83814Sespie #endif
132840175f0Skstailey     }
133840175f0Skstailey 
134840175f0Skstailey   /* Now we determine the single parts of the locale name.  First
135840175f0Skstailey      look for the language.  Termination symbols are `_' and `@' if
136840175f0Skstailey      we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
137840175f0Skstailey   mask = _nl_explode_name (locale, &language, &modifier, &territory,
138840175f0Skstailey 			   &codeset, &normalized_codeset, &special,
139840175f0Skstailey 			   &sponsor, &revision);
140840175f0Skstailey 
141840175f0Skstailey   /* Create all possible locale entries which might be interested in
14228ea187bSespie      generalization.  */
143840175f0Skstailey   retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
144840175f0Skstailey 			       strlen (dirname) + 1, mask, language, territory,
145840175f0Skstailey 			       codeset, normalized_codeset, modifier, special,
146840175f0Skstailey 			       sponsor, revision, domainname, 1);
147840175f0Skstailey   if (retval == NULL)
148840175f0Skstailey     /* This means we are out of core.  */
149840175f0Skstailey     return NULL;
150840175f0Skstailey 
151840175f0Skstailey   if (retval->decided == 0)
1523fb98d4aSespie     _nl_load_domain (retval, domainbinding);
153840175f0Skstailey   if (retval->data == NULL)
154840175f0Skstailey     {
155840175f0Skstailey       int cnt;
156840175f0Skstailey       for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
157840175f0Skstailey 	{
158840175f0Skstailey 	  if (retval->successor[cnt]->decided == 0)
1593fb98d4aSespie 	    _nl_load_domain (retval->successor[cnt], domainbinding);
160840175f0Skstailey 	  if (retval->successor[cnt]->data != NULL)
161840175f0Skstailey 	    break;
162840175f0Skstailey 	}
163840175f0Skstailey     }
164840175f0Skstailey 
165840175f0Skstailey   /* The room for an alias was dynamically allocated.  Free it now.  */
166840175f0Skstailey   if (alias_value != NULL)
167840175f0Skstailey     free (locale);
168840175f0Skstailey 
1693fb98d4aSespie   /* The space for normalized_codeset is dynamically allocated.  Free it.  */
1703fb98d4aSespie   if (mask & XPG_NORM_CODESET)
1713fb98d4aSespie     free ((void *) normalized_codeset);
1723fb98d4aSespie 
173840175f0Skstailey   return retval;
174840175f0Skstailey }
1751cc83814Sespie 
1761cc83814Sespie 
1771cc83814Sespie #ifdef _LIBC
libc_freeres_fn(free_mem)178*a1acfa9bSespie libc_freeres_fn (free_mem)
1791cc83814Sespie {
1801cc83814Sespie   struct loaded_l10nfile *runp = _nl_loaded_domains;
1811cc83814Sespie 
1821cc83814Sespie   while (runp != NULL)
1831cc83814Sespie     {
1841cc83814Sespie       struct loaded_l10nfile *here = runp;
1851cc83814Sespie       if (runp->data != NULL)
1861cc83814Sespie 	_nl_unload_domain ((struct loaded_domain *) runp->data);
1871cc83814Sespie       runp = runp->next;
1883fb98d4aSespie       free ((char *) here->filename);
1891cc83814Sespie       free (here);
1901cc83814Sespie     }
1911cc83814Sespie }
1921cc83814Sespie #endif
193