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