Update.
[glibc.git] / intl / bindtextdom.c
blob56a42232708dc5f9a7cdfa80a50ae23d89c4fd3c
1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
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.
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
13 Lesser General Public License for more details.
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. */
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
24 #include <stddef.h>
25 #include <stdlib.h>
26 #include <string.h>
28 #ifdef _LIBC
29 # include <libintl.h>
30 #else
31 # include "libgnuintl.h"
32 #endif
33 #include "gettextP.h"
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. */
40 # define __libc_rwlock_define(CLASS, NAME)
41 # define __libc_rwlock_wrlock(NAME)
42 # define __libc_rwlock_unlock(NAME)
43 #endif
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
49 # define _nl_default_dirname _nl_default_dirname__
50 # define _nl_domain_bindings _nl_domain_bindings__
51 #endif
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
58 /* @@ end of prolog @@ */
60 /* Contains the default location of the message catalogs. */
61 extern const char _nl_default_dirname[];
62 #ifdef _LIBC
63 extern const char _nl_default_dirname_internal[] attribute_hidden;
64 #else
65 # define INTUSE(name) name
66 #endif
68 /* List with bindings of specific domains. */
69 extern struct binding *_nl_domain_bindings;
71 /* Lock variable to protect the global data in the gettext implementation. */
72 __libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
75 /* Names for the libintl functions are a problem. They must not clash
76 with existing names and they should follow ANSI C. But this source
77 code is also used in GNU C Library where the names have a __
78 prefix. So we have to make a difference here. */
79 #ifdef _LIBC
80 # define BINDTEXTDOMAIN __bindtextdomain
81 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
82 # ifndef strdup
83 # define strdup(str) __strdup (str)
84 # endif
85 #else
86 # define BINDTEXTDOMAIN bindtextdomain__
87 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
88 #endif
90 /* Prototypes for local functions. */
91 static void set_binding_values PARAMS ((const char *domainname,
92 const char **dirnamep,
93 const char **codesetp));
95 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
96 to be used for the DOMAINNAME message catalog.
97 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
98 modified, only the current value is returned.
99 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
100 modified nor returned. */
101 static void
102 set_binding_values (domainname, dirnamep, codesetp)
103 const char *domainname;
104 const char **dirnamep;
105 const char **codesetp;
107 struct binding *binding;
108 int modified;
110 /* Some sanity checks. */
111 if (domainname == NULL || domainname[0] == '\0')
113 if (dirnamep)
114 *dirnamep = NULL;
115 if (codesetp)
116 *codesetp = NULL;
117 return;
120 __libc_rwlock_wrlock (_nl_state_lock);
122 modified = 0;
124 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
126 int compare = strcmp (domainname, binding->domainname);
127 if (compare == 0)
128 /* We found it! */
129 break;
130 if (compare < 0)
132 /* It is not in the list. */
133 binding = NULL;
134 break;
138 if (binding != NULL)
140 if (dirnamep)
142 const char *dirname = *dirnamep;
144 if (dirname == NULL)
145 /* The current binding has be to returned. */
146 *dirnamep = binding->dirname;
147 else
149 /* The domain is already bound. If the new value and the old
150 one are equal we simply do nothing. Otherwise replace the
151 old binding. */
152 char *result = binding->dirname;
153 if (strcmp (dirname, result) != 0)
155 if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
156 result = (char *) INTUSE(_nl_default_dirname);
157 else
159 #if defined _LIBC || defined HAVE_STRDUP
160 result = strdup (dirname);
161 #else
162 size_t len = strlen (dirname) + 1;
163 result = (char *) malloc (len);
164 if (__builtin_expect (result != NULL, 1))
165 memcpy (result, dirname, len);
166 #endif
169 if (__builtin_expect (result != NULL, 1))
171 if (binding->dirname != INTUSE(_nl_default_dirname))
172 free (binding->dirname);
174 binding->dirname = result;
175 modified = 1;
178 *dirnamep = result;
182 if (codesetp)
184 const char *codeset = *codesetp;
186 if (codeset == NULL)
187 /* The current binding has be to returned. */
188 *codesetp = binding->codeset;
189 else
191 /* The domain is already bound. If the new value and the old
192 one are equal we simply do nothing. Otherwise replace the
193 old binding. */
194 char *result = binding->codeset;
195 if (result == NULL || strcmp (codeset, result) != 0)
197 #if defined _LIBC || defined HAVE_STRDUP
198 result = strdup (codeset);
199 #else
200 size_t len = strlen (codeset) + 1;
201 result = (char *) malloc (len);
202 if (__builtin_expect (result != NULL, 1))
203 memcpy (result, codeset, len);
204 #endif
206 if (__builtin_expect (result != NULL, 1))
208 if (binding->codeset != NULL)
209 free (binding->codeset);
211 binding->codeset = result;
212 ++binding->codeset_cntr;
213 modified = 1;
216 *codesetp = result;
220 else if ((dirnamep == NULL || *dirnamep == NULL)
221 && (codesetp == NULL || *codesetp == NULL))
223 /* Simply return the default values. */
224 if (dirnamep)
225 *dirnamep = INTUSE(_nl_default_dirname);
226 if (codesetp)
227 *codesetp = NULL;
229 else
231 /* We have to create a new binding. */
232 size_t len = strlen (domainname) + 1;
233 struct binding *new_binding =
234 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
236 if (__builtin_expect (new_binding == NULL, 0))
237 goto failed;
239 memcpy (new_binding->domainname, domainname, len);
241 if (dirnamep)
243 const char *dirname = *dirnamep;
245 if (dirname == NULL)
246 /* The default value. */
247 dirname = INTUSE(_nl_default_dirname);
248 else
250 if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
251 dirname = INTUSE(_nl_default_dirname);
252 else
254 char *result;
255 #if defined _LIBC || defined HAVE_STRDUP
256 result = strdup (dirname);
257 if (__builtin_expect (result == NULL, 0))
258 goto failed_dirname;
259 #else
260 size_t len = strlen (dirname) + 1;
261 result = (char *) malloc (len);
262 if (__builtin_expect (result == NULL, 0))
263 goto failed_dirname;
264 memcpy (result, dirname, len);
265 #endif
266 dirname = result;
269 *dirnamep = dirname;
270 new_binding->dirname = (char *) dirname;
272 else
273 /* The default value. */
274 new_binding->dirname = (char *) INTUSE(_nl_default_dirname);
276 new_binding->codeset_cntr = 0;
278 if (codesetp)
280 const char *codeset = *codesetp;
282 if (codeset != NULL)
284 char *result;
286 #if defined _LIBC || defined HAVE_STRDUP
287 result = strdup (codeset);
288 if (__builtin_expect (result == NULL, 0))
289 goto failed_codeset;
290 #else
291 size_t len = strlen (codeset) + 1;
292 result = (char *) malloc (len);
293 if (__builtin_expect (result == NULL, 0))
294 goto failed_codeset;
295 memcpy (result, codeset, len);
296 #endif
297 codeset = result;
298 ++new_binding->codeset_cntr;
300 *codesetp = codeset;
301 new_binding->codeset = (char *) codeset;
303 else
304 new_binding->codeset = NULL;
306 /* Now enqueue it. */
307 if (_nl_domain_bindings == NULL
308 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
310 new_binding->next = _nl_domain_bindings;
311 _nl_domain_bindings = new_binding;
313 else
315 binding = _nl_domain_bindings;
316 while (binding->next != NULL
317 && strcmp (domainname, binding->next->domainname) > 0)
318 binding = binding->next;
320 new_binding->next = binding->next;
321 binding->next = new_binding;
324 modified = 1;
326 /* Here we deal with memory allocation failures. */
327 if (0)
329 failed_codeset:
330 if (new_binding->dirname != INTUSE(_nl_default_dirname))
331 free (new_binding->dirname);
332 failed_dirname:
333 free (new_binding);
334 failed:
335 if (dirnamep)
336 *dirnamep = NULL;
337 if (codesetp)
338 *codesetp = NULL;
342 /* If we modified any binding, we flush the caches. */
343 if (modified)
344 ++_nl_msg_cat_cntr;
346 __libc_rwlock_unlock (_nl_state_lock);
349 /* Specify that the DOMAINNAME message catalog will be found
350 in DIRNAME rather than in the system locale data base. */
351 char *
352 BINDTEXTDOMAIN (domainname, dirname)
353 const char *domainname;
354 const char *dirname;
356 set_binding_values (domainname, &dirname, NULL);
357 return (char *) dirname;
360 /* Specify the character encoding in which the messages from the
361 DOMAINNAME message catalog will be returned. */
362 char *
363 BIND_TEXTDOMAIN_CODESET (domainname, codeset)
364 const char *domainname;
365 const char *codeset;
367 set_binding_values (domainname, NULL, &codeset);
368 return (char *) codeset;
371 #ifdef _LIBC
372 /* Aliases for function names in GNU C Library. */
373 weak_alias (__bindtextdomain, bindtextdomain);
374 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
375 #endif