*** empty log message ***
[glibc.git] / intl / bindtextdom.c
blobe4830798bc4583ec7a0dd9c4dafb27d5438ee43f
1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000, 2001 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 #if defined STDC_HEADERS || defined _LIBC
25 # include <stdlib.h>
26 #else
27 # ifdef HAVE_MALLOC_H
28 # include <malloc.h>
29 # else
30 void free ();
31 # endif
32 #endif
34 #if defined HAVE_STRING_H || defined _LIBC
35 # include <string.h>
36 #else
37 # include <strings.h>
38 # ifndef memcpy
39 # define memcpy(Dst, Src, Num) (bcopy (Src, Dst, Num), (Dst))
40 # endif
41 #endif
43 #ifdef _LIBC
44 # include <libintl.h>
45 #else
46 # include "libgnuintl.h"
47 #endif
48 #include "gettextP.h"
50 #ifdef _LIBC
51 /* We have to handle multi-threaded applications. */
52 # include <bits/libc-lock.h>
53 #else
54 /* Provide dummy implementation if this is outside glibc. */
55 # define __libc_rwlock_define(CLASS, NAME)
56 # define __libc_rwlock_wrlock(NAME)
57 # define __libc_rwlock_unlock(NAME)
58 #endif
60 /* The internal variables in the standalone libintl.a must have different
61 names than the internal variables in GNU libc, otherwise programs
62 using libintl.a cannot be linked statically. */
63 #if !defined _LIBC
64 # define _nl_default_dirname _nl_default_dirname__
65 # define _nl_domain_bindings _nl_domain_bindings__
66 #endif
68 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
69 #ifndef offsetof
70 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
71 #endif
73 /* @@ end of prolog @@ */
75 /* Contains the default location of the message catalogs. */
76 extern const char _nl_default_dirname[];
78 /* List with bindings of specific domains. */
79 extern struct binding *_nl_domain_bindings;
81 /* Lock variable to protect the global data in the gettext implementation. */
82 __libc_rwlock_define (extern, _nl_state_lock)
85 /* Names for the libintl functions are a problem. They must not clash
86 with existing names and they should follow ANSI C. But this source
87 code is also used in GNU C Library where the names have a __
88 prefix. So we have to make a difference here. */
89 #ifdef _LIBC
90 # define BINDTEXTDOMAIN __bindtextdomain
91 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
92 # ifndef strdup
93 # define strdup(str) __strdup (str)
94 # endif
95 #else
96 # define BINDTEXTDOMAIN bindtextdomain__
97 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
98 #endif
100 /* Prototypes for local functions. */
101 static void set_binding_values PARAMS ((const char *domainname,
102 const char **dirnamep,
103 const char **codesetp));
105 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
106 to be used for the DOMAINNAME message catalog.
107 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
108 modified, only the current value is returned.
109 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
110 modified nor returned. */
111 static void
112 set_binding_values (domainname, dirnamep, codesetp)
113 const char *domainname;
114 const char **dirnamep;
115 const char **codesetp;
117 struct binding *binding;
118 int modified;
120 /* Some sanity checks. */
121 if (domainname == NULL || domainname[0] == '\0')
123 if (dirnamep)
124 *dirnamep = NULL;
125 if (codesetp)
126 *codesetp = NULL;
127 return;
130 __libc_rwlock_wrlock (_nl_state_lock);
132 modified = 0;
134 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
136 int compare = strcmp (domainname, binding->domainname);
137 if (compare == 0)
138 /* We found it! */
139 break;
140 if (compare < 0)
142 /* It is not in the list. */
143 binding = NULL;
144 break;
148 if (binding != NULL)
150 if (dirnamep)
152 const char *dirname = *dirnamep;
154 if (dirname == NULL)
155 /* The current binding has be to returned. */
156 *dirnamep = binding->dirname;
157 else
159 /* The domain is already bound. If the new value and the old
160 one are equal we simply do nothing. Otherwise replace the
161 old binding. */
162 char *result = binding->dirname;
163 if (strcmp (dirname, result) != 0)
165 if (strcmp (dirname, _nl_default_dirname) == 0)
166 result = (char *) _nl_default_dirname;
167 else
169 #if defined _LIBC || defined HAVE_STRDUP
170 result = strdup (dirname);
171 #else
172 size_t len = strlen (dirname) + 1;
173 result = (char *) malloc (len);
174 if (__builtin_expect (result != NULL, 1))
175 memcpy (result, dirname, len);
176 #endif
179 if (__builtin_expect (result != NULL, 1))
181 if (binding->dirname != _nl_default_dirname)
182 free (binding->dirname);
184 binding->dirname = result;
185 modified = 1;
188 *dirnamep = result;
192 if (codesetp)
194 const char *codeset = *codesetp;
196 if (codeset == NULL)
197 /* The current binding has be to returned. */
198 *codesetp = binding->codeset;
199 else
201 /* The domain is already bound. If the new value and the old
202 one are equal we simply do nothing. Otherwise replace the
203 old binding. */
204 char *result = binding->codeset;
205 if (result == NULL || strcmp (codeset, result) != 0)
207 #if defined _LIBC || defined HAVE_STRDUP
208 result = strdup (codeset);
209 #else
210 size_t len = strlen (codeset) + 1;
211 result = (char *) malloc (len);
212 if (__builtin_expect (result != NULL, 1))
213 memcpy (result, codeset, len);
214 #endif
216 if (__builtin_expect (result != NULL, 1))
218 if (binding->codeset != NULL)
219 free (binding->codeset);
221 binding->codeset = result;
222 ++binding->codeset_cntr;
223 modified = 1;
226 *codesetp = result;
230 else if ((dirnamep == NULL || *dirnamep == NULL)
231 && (codesetp == NULL || *codesetp == NULL))
233 /* Simply return the default values. */
234 if (dirnamep)
235 *dirnamep = _nl_default_dirname;
236 if (codesetp)
237 *codesetp = NULL;
239 else
241 /* We have to create a new binding. */
242 size_t len = strlen (domainname) + 1;
243 struct binding *new_binding =
244 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
246 if (__builtin_expect (new_binding == NULL, 0))
247 goto failed;
249 memcpy (new_binding->domainname, domainname, len);
251 if (dirnamep)
253 const char *dirname = *dirnamep;
255 if (dirname == NULL)
256 /* The default value. */
257 dirname = _nl_default_dirname;
258 else
260 if (strcmp (dirname, _nl_default_dirname) == 0)
261 dirname = _nl_default_dirname;
262 else
264 char *result;
265 #if defined _LIBC || defined HAVE_STRDUP
266 result = strdup (dirname);
267 if (__builtin_expect (result == NULL, 0))
268 goto failed_dirname;
269 #else
270 size_t len = strlen (dirname) + 1;
271 result = (char *) malloc (len);
272 if (__builtin_expect (result == NULL, 0))
273 goto failed_dirname;
274 memcpy (result, dirname, len);
275 #endif
276 dirname = result;
279 *dirnamep = dirname;
280 new_binding->dirname = (char *) dirname;
282 else
283 /* The default value. */
284 new_binding->dirname = (char *) _nl_default_dirname;
286 new_binding->codeset_cntr = 0;
288 if (codesetp)
290 const char *codeset = *codesetp;
292 if (codeset != NULL)
294 char *result;
296 #if defined _LIBC || defined HAVE_STRDUP
297 result = strdup (codeset);
298 if (__builtin_expect (result == NULL, 0))
299 goto failed_codeset;
300 #else
301 size_t len = strlen (codeset) + 1;
302 result = (char *) malloc (len);
303 if (__builtin_expect (result == NULL, 0))
304 goto failed_codeset;
305 memcpy (result, codeset, len);
306 #endif
307 codeset = result;
308 ++new_binding->codeset_cntr;
310 *codesetp = codeset;
311 new_binding->codeset = (char *) codeset;
313 else
314 new_binding->codeset = NULL;
316 /* Now enqueue it. */
317 if (_nl_domain_bindings == NULL
318 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
320 new_binding->next = _nl_domain_bindings;
321 _nl_domain_bindings = new_binding;
323 else
325 binding = _nl_domain_bindings;
326 while (binding->next != NULL
327 && strcmp (domainname, binding->next->domainname) > 0)
328 binding = binding->next;
330 new_binding->next = binding->next;
331 binding->next = new_binding;
334 modified = 1;
336 /* Here we deal with memory allocation failures. */
337 if (0)
339 failed_codeset:
340 if (new_binding->dirname != _nl_default_dirname)
341 free (new_binding->dirname);
342 failed_dirname:
343 free (new_binding);
344 failed:
345 if (dirnamep)
346 *dirnamep = NULL;
347 if (codesetp)
348 *codesetp = NULL;
352 /* If we modified any binding, we flush the caches. */
353 if (modified)
354 ++_nl_msg_cat_cntr;
356 __libc_rwlock_unlock (_nl_state_lock);
359 /* Specify that the DOMAINNAME message catalog will be found
360 in DIRNAME rather than in the system locale data base. */
361 char *
362 BINDTEXTDOMAIN (domainname, dirname)
363 const char *domainname;
364 const char *dirname;
366 set_binding_values (domainname, &dirname, NULL);
367 return (char *) dirname;
370 /* Specify the character encoding in which the messages from the
371 DOMAINNAME message catalog will be returned. */
372 char *
373 BIND_TEXTDOMAIN_CODESET (domainname, codeset)
374 const char *domainname;
375 const char *codeset;
377 set_binding_values (domainname, NULL, &codeset);
378 return (char *) codeset;
381 #ifdef _LIBC
382 /* Aliases for function names in GNU C Library. */
383 weak_alias (__bindtextdomain, bindtextdomain);
384 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
385 #endif