]> git.ipfire.org Git - thirdparty/glibc.git/blame - intl/finddomain.c
intl: Merge with gettext version 0.19.3
[thirdparty/glibc.git] / intl / finddomain.c
CommitLineData
8f2ece69 1/* Handle list of needed message catalogs
d4697bc9 2 Copyright (C) 1995-2014 Free Software Foundation, Inc.
f84ad0b1 3 Written by Ulrich Drepper <drepper@gnu.org>, 1995.
92f3773b 4
6d248857
WN
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
0393dfd6 9
6d248857 10 This program is distributed in the hope that it will be useful,
e4cf5070 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
6d248857
WN
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
24906b43 14
6d248857
WN
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24906b43
RM
17
18#ifdef HAVE_CONFIG_H
19# include <config.h>
20#endif
21
24906b43
RM
22#include <stdio.h>
23#include <sys/types.h>
0555fcce
UD
24#include <stdlib.h>
25#include <string.h>
24906b43
RM
26
27#if defined HAVE_UNISTD_H || defined _LIBC
28# include <unistd.h>
29#endif
30
24906b43
RM
31#include "gettextP.h"
32#ifdef _LIBC
33# include <libintl.h>
34#else
4a4d50f3 35# include "libgnuintl.h"
24906b43
RM
36#endif
37
6d248857
WN
38/* Handle multi-threaded applications. */
39#ifdef _LIBC
40# include <bits/libc-lock.h>
41# define gl_rwlock_define_initialized __libc_rwlock_define_initialized
42# define gl_rwlock_rdlock __libc_rwlock_rdlock
43# define gl_rwlock_wrlock __libc_rwlock_wrlock
44# define gl_rwlock_unlock __libc_rwlock_unlock
45#else
46# include "lock.h"
47#endif
48
24906b43 49/* @@ end of prolog @@ */
24906b43 50/* List of already loaded domains. */
7a12c6bb 51static struct loaded_l10nfile *_nl_loaded_domains;
857fa1b8 52
24906b43
RM
53
54/* Return a data structure describing the message catalog described by
55 the DOMAINNAME and CATEGORY parameters with respect to the currently
56 established bindings. */
7a12c6bb 57struct loaded_l10nfile *
d0fc4041 58internal_function
6d248857
WN
59_nl_find_domain (const char *dirname, char *locale,
60 const char *domainname, struct binding *domainbinding)
24906b43 61{
7a12c6bb 62 struct loaded_l10nfile *retval;
24906b43 63 const char *language;
7a12c6bb
RM
64 const char *modifier;
65 const char *territory;
66 const char *codeset;
67 const char *normalized_codeset;
7a12c6bb 68 const char *alias_value;
24906b43
RM
69 int mask;
70
7a12c6bb 71 /* LOCALE can consist of up to four recognized parts for the XPG syntax:
24906b43 72
6d248857 73 language[_territory][.codeset][@modifier]
24906b43 74
f41c8091
UD
75 Beside the first part all of them are allowed to be missing. If
76 the full specified locale is not found, the less specific one are
77 looked for. The various parts will be stripped off according to
24906b43 78 the following order:
e155c801
UD
79 (1) codeset
80 (2) normalized codeset
81 (3) territory
82 (4) modifier
24906b43
RM
83 */
84
f6b90f42 85 /* We need to protect modifying the _NL_LOADED_DOMAINS data. */
6d248857
WN
86 gl_rwlock_define_initialized (static, lock);
87 gl_rwlock_rdlock (lock);
f6b90f42 88
24906b43
RM
89 /* If we have already tested for this locale entry there has to
90 be one data set in the list of loaded domains. */
7a12c6bb
RM
91 retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
92 strlen (dirname) + 1, 0, locale, NULL, NULL,
e155c801 93 NULL, NULL, domainname, 0);
6d248857
WN
94
95 gl_rwlock_unlock (lock);
f6b90f42 96
24906b43
RM
97 if (retval != NULL)
98 {
99 /* We know something about this locale. */
100 int cnt;
101
ce7265c7 102 if (retval->decided <= 0)
c44a663d 103 _nl_load_domain (retval, domainbinding);
24906b43
RM
104
105 if (retval->data != NULL)
106 return retval;
107
75914335 108 for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
24906b43 109 {
ce7265c7 110 if (retval->successor[cnt]->decided <= 0)
c44a663d 111 _nl_load_domain (retval->successor[cnt], domainbinding);
24906b43
RM
112
113 if (retval->successor[cnt]->data != NULL)
114 break;
115 }
f6b90f42 116
0292b0dd 117 return retval;
24906b43
RM
118 /* NOTREACHED */
119 }
120
121 /* See whether the locale value is an alias. If yes its value
122 *overwrites* the alias name. No test for the original value is
123 done. */
124 alias_value = _nl_expand_alias (locale);
125 if (alias_value != NULL)
6d248857
WN
126 {
127#if defined _LIBC || defined HAVE_STRDUP
128 locale = strdup (alias_value);
129 if (locale == NULL)
130 return NULL;
131#else
132 size_t len = strlen (alias_value) + 1;
133 locale = (char *) malloc (len);
134 if (locale == NULL)
135 return NULL;
136
137 memcpy (locale, alias_value, len);
138#endif
139 }
24906b43
RM
140
141 /* Now we determine the single parts of the locale name. First
6d248857 142 look for the language. Termination symbols are `_', '.', and `@'. */
7a12c6bb 143 mask = _nl_explode_name (locale, &language, &modifier, &territory,
e155c801 144 &codeset, &normalized_codeset);
1c298d08
UD
145 if (mask == -1)
146 /* This means we are out of core. */
147 return NULL;
24906b43 148
f6b90f42 149 /* We need to protect modifying the _NL_LOADED_DOMAINS data. */
6d248857 150 gl_rwlock_wrlock (lock);
f6b90f42 151
24906b43 152 /* Create all possible locale entries which might be interested in
6d52618b 153 generalization. */
7a12c6bb
RM
154 retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
155 strlen (dirname) + 1, mask, language, territory,
e155c801
UD
156 codeset, normalized_codeset, modifier,
157 domainname, 1);
6d248857
WN
158
159 gl_rwlock_unlock (lock);
f6b90f42 160
24906b43
RM
161 if (retval == NULL)
162 /* This means we are out of core. */
ce31a3b1 163 goto out;
24906b43 164
ce7265c7 165 if (retval->decided <= 0)
c44a663d 166 _nl_load_domain (retval, domainbinding);
24906b43
RM
167 if (retval->data == NULL)
168 {
169 int cnt;
170 for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
171 {
ce7265c7 172 if (retval->successor[cnt]->decided <= 0)
c44a663d 173 _nl_load_domain (retval->successor[cnt], domainbinding);
24906b43
RM
174 if (retval->successor[cnt]->data != NULL)
175 break;
24906b43 176 }
24906b43
RM
177 }
178
6d248857
WN
179 /* The room for an alias was dynamically allocated. Free it now. */
180 if (alias_value != NULL)
181 free (locale);
182
ce31a3b1 183out:
a1648746
UD
184 /* The space for normalized_codeset is dynamically allocated. Free it. */
185 if (mask & XPG_NORM_CODESET)
a7123f0e 186 free ((void *) normalized_codeset);
a1648746 187
24906b43
RM
188 return retval;
189}
a5a0310d
UD
190
191
192#ifdef _LIBC
9e365fe7
UD
193/* This is called from iconv/gconv_db.c's free_mem, as locales must
194 be freed before freeing gconv steps arrays. */
195void __libc_freeres_fn_section
60d2f8f3 196_nl_finddomain_subfreeres (void)
a5a0310d
UD
197{
198 struct loaded_l10nfile *runp = _nl_loaded_domains;
199
200 while (runp != NULL)
201 {
202 struct loaded_l10nfile *here = runp;
203 if (runp->data != NULL)
204 _nl_unload_domain ((struct loaded_domain *) runp->data);
205 runp = runp->next;
f84ad0b1 206 free ((char *) here->filename);
a5a0310d
UD
207 free (here);
208 }
209}
a5a0310d 210#endif