Update.
[glibc.git] / intl / bindtextdom.c
blob4ea368da00acdaa4996d228a1816bdf80c410d99
1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
23 #if defined STDC_HEADERS || defined _LIBC
24 # include <stdlib.h>
25 #else
26 # ifdef HAVE_MALLOC_H
27 # include <malloc.h>
28 # else
29 void free ();
30 # endif
31 #endif
33 #if defined HAVE_STRING_H || defined _LIBC
34 # include <string.h>
35 #else
36 # include <strings.h>
37 # ifndef memcpy
38 # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
39 # endif
40 #endif
42 #ifdef _LIBC
43 # include <libintl.h>
44 #else
45 # include "libgettext.h"
46 #endif
47 #include "gettext.h"
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 /* @@ end of prolog @@ */
62 /* Contains the default location of the message catalogs. */
63 extern const char _nl_default_dirname[];
65 /* List with bindings of specific domains. */
66 extern struct binding *_nl_domain_bindings;
68 /* Lock variable to protect the global data in the gettext implementation. */
69 __libc_rwlock_define (extern, _nl_state_lock)
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
78 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
79 # ifndef strdup
80 # define strdup(str) __strdup (str)
81 # endif
82 #else
83 # define BINDTEXTDOMAIN bindtextdomain__
84 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
85 #endif
87 /* Prototypes for local functions. */
88 static void set_binding_values (const char *domainname, const char **dirnamep,
89 const char **codesetp);
91 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
92 to be used for the DOMAINNAME message catalog.
93 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
94 modified, only the current value is returned.
95 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
96 modified nor returned. */
97 static void
98 set_binding_values (domainname, dirnamep, codesetp)
99 const char *domainname;
100 const char **dirnamep;
101 const char **codesetp;
103 struct binding *binding;
104 int modified;
106 /* Some sanity checks. */
107 if (domainname == NULL || domainname[0] == '\0')
109 if (dirnamep)
110 *dirnamep = NULL;
111 if (codesetp)
112 *codesetp = NULL;
113 return;
116 __libc_rwlock_wrlock (_nl_state_lock);
118 modified = 0;
120 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
122 int compare = strcmp (domainname, binding->domainname);
123 if (compare == 0)
124 /* We found it! */
125 break;
126 if (compare < 0)
128 /* It is not in the list. */
129 binding = NULL;
130 break;
134 if (binding != NULL)
136 if (dirnamep)
138 const char *dirname = *dirnamep;
140 if (dirname == NULL)
141 /* The current binding has be to returned. */
142 *dirnamep = binding->dirname;
143 else
145 /* The domain is already bound. If the new value and the old
146 one are equal we simply do nothing. Otherwise replace the
147 old binding. */
148 char *result = binding->dirname;
149 if (strcmp (dirname, result) != 0)
151 if (strcmp (dirname, _nl_default_dirname) == 0)
152 result = (char *) _nl_default_dirname;
153 else
155 #if defined _LIBC || defined HAVE_STRDUP
156 result = strdup (dirname);
157 #else
158 size_t len = strlen (dirname) + 1;
159 result = (char *) malloc (len);
160 if (__builtin_expect (result != NULL, 1))
161 memcpy (result, dirname, len);
162 #endif
165 if (__builtin_expect (result != NULL, 1))
167 if (binding->dirname != _nl_default_dirname)
168 free (binding->dirname);
170 binding->dirname = result;
171 modified = 1;
174 *dirnamep = result;
178 if (codesetp)
180 const char *codeset = *codesetp;
182 if (codeset == NULL)
183 /* The current binding has be to returned. */
184 *codesetp = binding->codeset;
185 else
187 /* The domain is already bound. If the new value and the old
188 one are equal we simply do nothing. Otherwise replace the
189 old binding. */
190 char *result = binding->codeset;
191 if (result == NULL || strcmp (codeset, result) != 0)
193 #if defined _LIBC || defined HAVE_STRDUP
194 result = strdup (codeset);
195 #else
196 size_t len = strlen (codeset) + 1;
197 result = (char *) malloc (len);
198 if (__builtin_expect (result != NULL, 1))
199 memcpy (result, codeset, len);
200 #endif
202 if (__builtin_expect (result != NULL, 1))
204 if (binding->codeset != NULL)
205 free (binding->codeset);
207 binding->codeset = result;
208 modified = 1;
211 *codesetp = result;
215 else if ((dirnamep == NULL || *dirnamep == NULL)
216 && (codesetp == NULL || *codesetp == NULL))
218 /* Simply return the default values. */
219 if (dirnamep)
220 *dirnamep = _nl_default_dirname;
221 if (codesetp)
222 *codesetp = NULL;
224 else
226 /* We have to create a new binding. */
227 size_t len = strlen (domainname) + 1;
228 struct binding *new_binding =
229 (struct binding *) malloc (sizeof (*new_binding) + len);
231 if (__builtin_expect (new_binding == NULL, 0))
232 goto failed;
234 memcpy (new_binding->domainname, domainname, len);
236 if (dirnamep)
238 const char *dirname = *dirnamep;
240 if (dirname == NULL)
241 /* The default value. */
242 dirname = _nl_default_dirname;
243 else
245 if (strcmp (dirname, _nl_default_dirname) == 0)
246 dirname = _nl_default_dirname;
247 else
249 char *result;
250 #if defined _LIBC || defined HAVE_STRDUP
251 result = strdup (dirname);
252 if (__builtin_expect (result == NULL, 0))
253 goto failed_dirname;
254 #else
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);
260 #endif
261 dirname = result;
264 *dirnamep = dirname;
265 new_binding->dirname = (char *) dirname;
267 else
268 /* The default value. */
269 new_binding->dirname = (char *) _nl_default_dirname;
271 if (codesetp)
273 const char *codeset = *codesetp;
275 if (codeset != NULL)
277 char *result;
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;
292 *codesetp = codeset;
293 new_binding->codeset = (char *) codeset;
295 else
296 new_binding->codeset = NULL;
298 /* Now enqueue it. */
299 if (_nl_domain_bindings == NULL
300 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
302 new_binding->next = _nl_domain_bindings;
303 _nl_domain_bindings = new_binding;
305 else
307 binding = _nl_domain_bindings;
308 while (binding->next != NULL
309 && strcmp (domainname, binding->next->domainname) > 0)
310 binding = binding->next;
312 new_binding->next = binding->next;
313 binding->next = new_binding;
316 modified = 1;
318 /* Here we deal with memory allocation failures. */
319 if (0)
321 failed_codeset:
322 if (new_binding->dirname != _nl_default_dirname)
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;
334 /* If we modified any binding, we flush the caches. */
335 if (modified)
336 ++_nl_msg_cat_cntr;
338 __libc_rwlock_unlock (_nl_state_lock);
341 /* Specify that the DOMAINNAME message catalog will be found
342 in DIRNAME rather than in the system locale data base. */
343 char *
344 BINDTEXTDOMAIN (domainname, dirname)
345 const char *domainname;
346 const char *dirname;
348 set_binding_values (domainname, &dirname, NULL);
349 return (char *) dirname;
352 /* Specify the character encoding in which the messages from the
353 DOMAINNAME message catalog will be returned. */
354 char *
355 BIND_TEXTDOMAIN_CODESET (domainname, codeset)
356 const char *domainname;
357 const char *codeset;
359 set_binding_values (domainname, NULL, &codeset);
360 return (char *) codeset;
363 #ifdef _LIBC
364 /* Aliases for function names in GNU C Library. */
365 weak_alias (__bindtextdomain, bindtextdomain);
366 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
367 #endif