]> git.ipfire.org Git - thirdparty/glibc.git/blame - intl/bindtextdom.c
Fix rule dependency in last change.
[thirdparty/glibc.git] / intl / bindtextdom.c
CommitLineData
8f2ece69 1/* Implementation of the bindtextdomain(3) function
9cfe5381 2 Copyright (C) 1995-1998, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
41bdb6e2 3 This file is part of the GNU C Library.
24906b43 4
c84142e8 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
0393dfd6 9
c84142e8
UD
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
24906b43 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
24906b43
RM
18
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22
0555fcce
UD
23#include <stddef.h>
24#include <stdlib.h>
25#include <string.h>
24906b43
RM
26
27#ifdef _LIBC
28# include <libintl.h>
29#else
4a4d50f3 30# include "libgnuintl.h"
24906b43 31#endif
24906b43
RM
32#include "gettextP.h"
33
0ed99ce4
UD
34#ifdef _LIBC
35/* We have to handle multi-threaded applications. */
36# include <bits/libc-lock.h>
37#else
38/* Provide dummy implementation if this is outside glibc. */
0a55a284
UD
39# define __libc_rwlock_define(CLASS, NAME)
40# define __libc_rwlock_wrlock(NAME)
41# define __libc_rwlock_unlock(NAME)
0ed99ce4
UD
42#endif
43
52d895a4
UD
44/* The internal variables in the standalone libintl.a must have different
45 names than the internal variables in GNU libc, otherwise programs
46 using libintl.a cannot be linked statically. */
47#if !defined _LIBC
0f131646
RM
48# define _nl_default_dirname libintl_nl_default_dirname
49# define _nl_domain_bindings libintl_nl_domain_bindings
52d895a4
UD
50#endif
51
4a4d50f3
UD
52/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
53#ifndef offsetof
54# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
55#endif
56
24906b43
RM
57/* @@ end of prolog @@ */
58
59/* Contains the default location of the message catalogs. */
60extern const char _nl_default_dirname[];
230491f0 61#ifdef _LIBC
9cfe5381 62libc_hidden_proto (_nl_default_dirname)
230491f0 63#endif
24906b43
RM
64
65/* List with bindings of specific domains. */
66extern struct binding *_nl_domain_bindings;
67
0ed99ce4 68/* Lock variable to protect the global data in the gettext implementation. */
418f1701 69__libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
0ed99ce4 70
24906b43
RM
71
72/* Names for the libintl functions are a problem. They must not clash
73 with existing names and they should follow ANSI C. But this source
74 code is also used in GNU C Library where the names have a __
75 prefix. So we have to make a difference here. */
76#ifdef _LIBC
77# define BINDTEXTDOMAIN __bindtextdomain
17c389fc 78# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
cb343854
UD
79# ifndef strdup
80# define strdup(str) __strdup (str)
81# endif
24906b43 82#else
0f131646
RM
83# define BINDTEXTDOMAIN libintl_bindtextdomain
84# define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
24906b43
RM
85#endif
86
fbd61fc1 87/* Prototypes for local functions. */
4a4d50f3
UD
88static void set_binding_values PARAMS ((const char *domainname,
89 const char **dirnamep,
90 const char **codesetp));
c44a663d 91
17c389fc
UD
92/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
93 to be used for the DOMAINNAME message catalog.
94 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
95 modified, only the current value is returned.
96 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
97 modified nor returned. */
98static void
99set_binding_values (domainname, dirnamep, codesetp)
24906b43 100 const char *domainname;
17c389fc
UD
101 const char **dirnamep;
102 const char **codesetp;
24906b43
RM
103{
104 struct binding *binding;
17c389fc 105 int modified;
24906b43
RM
106
107 /* Some sanity checks. */
108 if (domainname == NULL || domainname[0] == '\0')
17c389fc
UD
109 {
110 if (dirnamep)
111 *dirnamep = NULL;
112 if (codesetp)
113 *codesetp = NULL;
114 return;
115 }
24906b43 116
0ed99ce4
UD
117 __libc_rwlock_wrlock (_nl_state_lock);
118
17c389fc
UD
119 modified = 0;
120
24906b43
RM
121 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
122 {
123 int compare = strcmp (domainname, binding->domainname);
124 if (compare == 0)
125 /* We found it! */
126 break;
127 if (compare < 0)
128 {
129 /* It is not in the list. */
130 binding = NULL;
131 break;
132 }
133 }
134
17c389fc 135 if (binding != NULL)
24906b43 136 {
17c389fc 137 if (dirnamep)
24906b43 138 {
17c389fc
UD
139 const char *dirname = *dirnamep;
140
141 if (dirname == NULL)
142 /* The current binding has be to returned. */
143 *dirnamep = binding->dirname;
40a55d20
UD
144 else
145 {
17c389fc
UD
146 /* The domain is already bound. If the new value and the old
147 one are equal we simply do nothing. Otherwise replace the
148 old binding. */
149 char *result = binding->dirname;
150 if (strcmp (dirname, result) != 0)
151 {
9cfe5381
RM
152 if (strcmp (dirname, _nl_default_dirname) == 0)
153 result = (char *) _nl_default_dirname;
17c389fc
UD
154 else
155 {
40a55d20 156#if defined _LIBC || defined HAVE_STRDUP
17c389fc 157 result = strdup (dirname);
40a55d20 158#else
17c389fc
UD
159 size_t len = strlen (dirname) + 1;
160 result = (char *) malloc (len);
161 if (__builtin_expect (result != NULL, 1))
162 memcpy (result, dirname, len);
40a55d20 163#endif
17c389fc
UD
164 }
165
166 if (__builtin_expect (result != NULL, 1))
167 {
9cfe5381 168 if (binding->dirname != _nl_default_dirname)
17c389fc
UD
169 free (binding->dirname);
170
171 binding->dirname = result;
172 modified = 1;
173 }
174 }
175 *dirnamep = result;
40a55d20 176 }
17c389fc
UD
177 }
178
179 if (codesetp)
180 {
181 const char *codeset = *codesetp;
24906b43 182
17c389fc
UD
183 if (codeset == NULL)
184 /* The current binding has be to returned. */
185 *codesetp = binding->codeset;
186 else
0ed99ce4 187 {
17c389fc
UD
188 /* The domain is already bound. If the new value and the old
189 one are equal we simply do nothing. Otherwise replace the
190 old binding. */
191 char *result = binding->codeset;
192 if (result == NULL || strcmp (codeset, result) != 0)
193 {
194#if defined _LIBC || defined HAVE_STRDUP
195 result = strdup (codeset);
196#else
197 size_t len = strlen (codeset) + 1;
198 result = (char *) malloc (len);
199 if (__builtin_expect (result != NULL, 1))
200 memcpy (result, codeset, len);
201#endif
24906b43 202
17c389fc
UD
203 if (__builtin_expect (result != NULL, 1))
204 {
72e6cdfa 205 free (binding->codeset);
17c389fc
UD
206
207 binding->codeset = result;
208 modified = 1;
209 }
210 }
211 *codesetp = result;
0ed99ce4 212 }
40a55d20 213 }
24906b43 214 }
17c389fc
UD
215 else if ((dirnamep == NULL || *dirnamep == NULL)
216 && (codesetp == NULL || *codesetp == NULL))
217 {
218 /* Simply return the default values. */
219 if (dirnamep)
9cfe5381 220 *dirnamep = _nl_default_dirname;
17c389fc
UD
221 if (codesetp)
222 *codesetp = NULL;
223 }
24906b43
RM
224 else
225 {
226 /* We have to create a new binding. */
0ed99ce4 227 size_t len = strlen (domainname) + 1;
24906b43 228 struct binding *new_binding =
4a4d50f3 229 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
24906b43 230
17c389fc
UD
231 if (__builtin_expect (new_binding == NULL, 0))
232 goto failed;
233
234 memcpy (new_binding->domainname, domainname, len);
235
236 if (dirnamep)
24906b43 237 {
17c389fc 238 const char *dirname = *dirnamep;
0ed99ce4 239
17c389fc
UD
240 if (dirname == NULL)
241 /* The default value. */
9cfe5381 242 dirname = _nl_default_dirname;
0ed99ce4
UD
243 else
244 {
9cfe5381
RM
245 if (strcmp (dirname, _nl_default_dirname) == 0)
246 dirname = _nl_default_dirname;
17c389fc
UD
247 else
248 {
249 char *result;
40a55d20 250#if defined _LIBC || defined HAVE_STRDUP
17c389fc
UD
251 result = strdup (dirname);
252 if (__builtin_expect (result == NULL, 0))
253 goto failed_dirname;
40a55d20 254#else
17c389fc
UD
255 size_t len = strlen (dirname) + 1;
256 result = (char *) malloc (len);
257 if (__builtin_expect (result == NULL, 0))
258 goto failed_dirname;
259 memcpy (result, dirname, len);
40a55d20 260#endif
17c389fc
UD
261 dirname = result;
262 }
0ed99ce4 263 }
17c389fc
UD
264 *dirnamep = dirname;
265 new_binding->dirname = (char *) dirname;
24906b43 266 }
17c389fc
UD
267 else
268 /* The default value. */
9cfe5381 269 new_binding->dirname = (char *) _nl_default_dirname;
a334319f 270
17c389fc 271 if (codesetp)
24906b43 272 {
17c389fc
UD
273 const char *codeset = *codesetp;
274
275 if (codeset != NULL)
0ed99ce4 276 {
17c389fc 277 char *result;
24906b43 278
17c389fc
UD
279#if defined _LIBC || defined HAVE_STRDUP
280 result = strdup (codeset);
281 if (__builtin_expect (result == NULL, 0))
282 goto failed_codeset;
283#else
284 size_t len = strlen (codeset) + 1;
285 result = (char *) malloc (len);
286 if (__builtin_expect (result == NULL, 0))
287 goto failed_codeset;
288 memcpy (result, codeset, len);
289#endif
290 codeset = result;
0ed99ce4 291 }
17c389fc
UD
292 *codesetp = codeset;
293 new_binding->codeset = (char *) codeset;
294 }
295 else
296 new_binding->codeset = NULL;
297
298 /* Now enqueue it. */
299 if (_nl_domain_bindings == NULL
300 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
301 {
302 new_binding->next = _nl_domain_bindings;
303 _nl_domain_bindings = new_binding;
304 }
305 else
306 {
307 binding = _nl_domain_bindings;
308 while (binding->next != NULL
309 && strcmp (domainname, binding->next->domainname) > 0)
310 binding = binding->next;
311
312 new_binding->next = binding->next;
313 binding->next = new_binding;
314 }
315
316 modified = 1;
317
318 /* Here we deal with memory allocation failures. */
319 if (0)
320 {
321 failed_codeset:
9cfe5381 322 if (new_binding->dirname != _nl_default_dirname)
17c389fc
UD
323 free (new_binding->dirname);
324 failed_dirname:
325 free (new_binding);
326 failed:
327 if (dirnamep)
328 *dirnamep = NULL;
329 if (codesetp)
330 *codesetp = NULL;
24906b43 331 }
24906b43
RM
332 }
333
17c389fc
UD
334 /* If we modified any binding, we flush the caches. */
335 if (modified)
0ed99ce4
UD
336 ++_nl_msg_cat_cntr;
337
338 __libc_rwlock_unlock (_nl_state_lock);
17c389fc
UD
339}
340
341/* Specify that the DOMAINNAME message catalog will be found
342 in DIRNAME rather than in the system locale data base. */
343char *
344BINDTEXTDOMAIN (domainname, dirname)
345 const char *domainname;
346 const char *dirname;
347{
348 set_binding_values (domainname, &dirname, NULL);
349 return (char *) dirname;
350}
0ed99ce4 351
17c389fc
UD
352/* Specify the character encoding in which the messages from the
353 DOMAINNAME message catalog will be returned. */
354char *
355BIND_TEXTDOMAIN_CODESET (domainname, codeset)
356 const char *domainname;
357 const char *codeset;
358{
359 set_binding_values (domainname, NULL, &codeset);
360 return (char *) codeset;
24906b43
RM
361}
362
363#ifdef _LIBC
17c389fc 364/* Aliases for function names in GNU C Library. */
24906b43 365weak_alias (__bindtextdomain, bindtextdomain);
17c389fc 366weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
24906b43 367#endif