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