init version.
[bush.git] / lib / intl / bindtextdom.c
blobd534a7800e766029ca2546868b7b80b81d0c52e4
1 /* bindtextdom.c - Implementation of the bindtextdomain(3) function */
3 /* Copyright (C) 1995-1998, 2000, 2001, 2002, 2005-2009 Free Software Foundation, Inc.
5 This file is part of GNU Bush.
7 Bush is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bush is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bush. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
25 #include <stddef.h>
26 #include <stdlib.h>
27 #include <string.h>
29 #ifdef _LIBC
30 # include <libintl.h>
31 #else
32 # include "libgnuintl.h"
33 #endif
34 #include "gettextP.h"
36 #ifdef _LIBC
37 /* We have to handle multi-threaded applications. */
38 # include <bits/libc-lock.h>
39 #else
40 /* Provide dummy implementation if this is outside glibc. */
41 # define __libc_rwlock_define(CLASS, NAME)
42 # define __libc_rwlock_wrlock(NAME)
43 # define __libc_rwlock_unlock(NAME)
44 #endif
46 /* The internal variables in the standalone libintl.a must have different
47 names than the internal variables in GNU libc, otherwise programs
48 using libintl.a cannot be linked statically. */
49 #if !defined _LIBC
50 # define _nl_default_dirname libintl_nl_default_dirname
51 # define _nl_domain_bindings libintl_nl_domain_bindings
52 #endif
54 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
55 #ifndef offsetof
56 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
57 #endif
59 /* @@ end of prolog @@ */
61 /* Contains the default location of the message catalogs. */
62 extern const char _nl_default_dirname[];
63 #ifdef _LIBC
64 extern const char _nl_default_dirname_internal[] attribute_hidden;
65 #else
66 # define INTUSE(name) name
67 #endif
69 /* List with bindings of specific domains. */
70 extern struct binding *_nl_domain_bindings;
72 /* Lock variable to protect the global data in the gettext implementation. */
73 __libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
76 /* Names for the libintl functions are a problem. They must not clash
77 with existing names and they should follow ANSI C. But this source
78 code is also used in GNU C Library where the names have a __
79 prefix. So we have to make a difference here. */
80 #ifdef _LIBC
81 # define BINDTEXTDOMAIN __bindtextdomain
82 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
83 # ifndef strdup
84 # define strdup(str) __strdup (str)
85 # endif
86 #else
87 # define BINDTEXTDOMAIN libintl_bindtextdomain
88 # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
89 #endif
91 /* Prototypes for local functions. */
92 static void set_binding_values PARAMS ((const char *domainname,
93 const char **dirnamep,
94 const char **codesetp));
96 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
97 to be used for the DOMAINNAME message catalog.
98 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
99 modified, only the current value is returned.
100 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
101 modified nor returned. */
102 static void
103 set_binding_values (domainname, dirnamep, codesetp)
104 const char *domainname;
105 const char **dirnamep;
106 const char **codesetp;
108 struct binding *binding;
109 int modified;
111 /* Some sanity checks. */
112 if (domainname == NULL || domainname[0] == '\0')
114 if (dirnamep)
115 *dirnamep = NULL;
116 if (codesetp)
117 *codesetp = NULL;
118 return;
121 __libc_rwlock_wrlock (_nl_state_lock);
123 modified = 0;
125 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
127 int compare = strcmp (domainname, binding->domainname);
128 if (compare == 0)
129 /* We found it! */
130 break;
131 if (compare < 0)
133 /* It is not in the list. */
134 binding = NULL;
135 break;
139 if (binding != NULL)
141 if (dirnamep)
143 const char *dirname = *dirnamep;
145 if (dirname == NULL)
146 /* The current binding has be to returned. */
147 *dirnamep = binding->dirname;
148 else
150 /* The domain is already bound. If the new value and the old
151 one are equal we simply do nothing. Otherwise replace the
152 old binding. */
153 char *result = binding->dirname;
154 if (strcmp (dirname, result) != 0)
156 if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
157 result = (char *) INTUSE(_nl_default_dirname);
158 else
160 #if defined _LIBC || defined HAVE_STRDUP
161 result = strdup (dirname);
162 #else
163 size_t len = strlen (dirname) + 1;
164 result = (char *) malloc (len);
165 if (__builtin_expect (result != NULL, 1))
166 memcpy (result, dirname, len);
167 #endif
170 if (__builtin_expect (result != NULL, 1))
172 if (binding->dirname != INTUSE(_nl_default_dirname))
173 free (binding->dirname);
175 binding->dirname = result;
176 modified = 1;
179 *dirnamep = result;
183 if (codesetp)
185 const char *codeset = *codesetp;
187 if (codeset == NULL)
188 /* The current binding has be to returned. */
189 *codesetp = binding->codeset;
190 else
192 /* The domain is already bound. If the new value and the old
193 one are equal we simply do nothing. Otherwise replace the
194 old binding. */
195 char *result = binding->codeset;
196 if (result == NULL || strcmp (codeset, result) != 0)
198 #if defined _LIBC || defined HAVE_STRDUP
199 result = strdup (codeset);
200 #else
201 size_t len = strlen (codeset) + 1;
202 result = (char *) malloc (len);
203 if (__builtin_expect (result != NULL, 1))
204 memcpy (result, codeset, len);
205 #endif
207 if (__builtin_expect (result != NULL, 1))
209 if (binding->codeset != NULL)
210 free (binding->codeset);
212 binding->codeset = result;
213 binding->codeset_cntr++;
214 modified = 1;
217 *codesetp = result;
221 else if ((dirnamep == NULL || *dirnamep == NULL)
222 && (codesetp == NULL || *codesetp == NULL))
224 /* Simply return the default values. */
225 if (dirnamep)
226 *dirnamep = INTUSE(_nl_default_dirname);
227 if (codesetp)
228 *codesetp = NULL;
230 else
232 /* We have to create a new binding. */
233 size_t len = strlen (domainname) + 1;
234 struct binding *new_binding =
235 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
237 if (__builtin_expect (new_binding == NULL, 0))
238 goto failed;
240 memcpy (new_binding->domainname, domainname, len);
242 if (dirnamep)
244 const char *dirname = *dirnamep;
246 if (dirname == NULL)
247 /* The default value. */
248 dirname = INTUSE(_nl_default_dirname);
249 else
251 if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
252 dirname = INTUSE(_nl_default_dirname);
253 else
255 char *result;
256 #if defined _LIBC || defined HAVE_STRDUP
257 result = strdup (dirname);
258 if (__builtin_expect (result == NULL, 0))
259 goto failed_dirname;
260 #else
261 size_t len = strlen (dirname) + 1;
262 result = (char *) malloc (len);
263 if (__builtin_expect (result == NULL, 0))
264 goto failed_dirname;
265 memcpy (result, dirname, len);
266 #endif
267 dirname = result;
270 *dirnamep = dirname;
271 new_binding->dirname = (char *) dirname;
273 else
274 /* The default value. */
275 new_binding->dirname = (char *) INTUSE(_nl_default_dirname);
277 new_binding->codeset_cntr = 0;
279 if (codesetp)
281 const char *codeset = *codesetp;
283 if (codeset != NULL)
285 char *result;
287 #if defined _LIBC || defined HAVE_STRDUP
288 result = strdup (codeset);
289 if (__builtin_expect (result == NULL, 0))
290 goto failed_codeset;
291 #else
292 size_t len = strlen (codeset) + 1;
293 result = (char *) malloc (len);
294 if (__builtin_expect (result == NULL, 0))
295 goto failed_codeset;
296 memcpy (result, codeset, len);
297 #endif
298 codeset = result;
299 new_binding->codeset_cntr++;
301 *codesetp = codeset;
302 new_binding->codeset = (char *) codeset;
304 else
305 new_binding->codeset = NULL;
307 /* Now enqueue it. */
308 if (_nl_domain_bindings == NULL
309 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
311 new_binding->next = _nl_domain_bindings;
312 _nl_domain_bindings = new_binding;
314 else
316 binding = _nl_domain_bindings;
317 while (binding->next != NULL
318 && strcmp (domainname, binding->next->domainname) > 0)
319 binding = binding->next;
321 new_binding->next = binding->next;
322 binding->next = new_binding;
325 modified = 1;
327 /* Here we deal with memory allocation failures. */
328 if (0)
330 failed_codeset:
331 if (new_binding->dirname != INTUSE(_nl_default_dirname))
332 free (new_binding->dirname);
333 failed_dirname:
334 free (new_binding);
335 failed:
336 if (dirnamep)
337 *dirnamep = NULL;
338 if (codesetp)
339 *codesetp = NULL;
343 /* If we modified any binding, we flush the caches. */
344 if (modified)
345 ++_nl_msg_cat_cntr;
347 __libc_rwlock_unlock (_nl_state_lock);
350 /* Specify that the DOMAINNAME message catalog will be found
351 in DIRNAME rather than in the system locale data base. */
352 char *
353 BINDTEXTDOMAIN (domainname, dirname)
354 const char *domainname;
355 const char *dirname;
357 set_binding_values (domainname, &dirname, NULL);
358 return (char *) dirname;
361 /* Specify the character encoding in which the messages from the
362 DOMAINNAME message catalog will be returned. */
363 char *
364 BIND_TEXTDOMAIN_CODESET (domainname, codeset)
365 const char *domainname;
366 const char *codeset;
368 set_binding_values (domainname, NULL, &codeset);
369 return (char *) codeset;
372 #ifdef _LIBC
373 /* Aliases for function names in GNU C Library. */
374 weak_alias (__bindtextdomain, bindtextdomain);
375 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
376 #endif