Update.
[glibc.git] / intl / bindtextdom.c
blob45000a6b58ac2d82747e0b7f300272e5fa999ac0
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), (Dst))
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 /* 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 /* @@ end of prolog @@ */
70 /* Contains the default location of the message catalogs. */
71 extern const char _nl_default_dirname[];
73 /* List with bindings of specific domains. */
74 extern struct binding *_nl_domain_bindings;
76 /* Lock variable to protect the global data in the gettext implementation. */
77 __libc_rwlock_define (extern, _nl_state_lock)
80 /* Names for the libintl functions are a problem. They must not clash
81 with existing names and they should follow ANSI C. But this source
82 code is also used in GNU C Library where the names have a __
83 prefix. So we have to make a difference here. */
84 #ifdef _LIBC
85 # define BINDTEXTDOMAIN __bindtextdomain
86 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
87 # ifndef strdup
88 # define strdup(str) __strdup (str)
89 # endif
90 #else
91 # define BINDTEXTDOMAIN bindtextdomain__
92 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
93 #endif
95 /* Prototypes for local functions. */
96 static void set_binding_values (const char *domainname, const char **dirnamep,
97 const char **codesetp);
99 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
100 to be used for the DOMAINNAME message catalog.
101 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
102 modified, only the current value is returned.
103 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
104 modified nor returned. */
105 static void
106 set_binding_values (domainname, dirnamep, codesetp)
107 const char *domainname;
108 const char **dirnamep;
109 const char **codesetp;
111 struct binding *binding;
112 int modified;
114 /* Some sanity checks. */
115 if (domainname == NULL || domainname[0] == '\0')
117 if (dirnamep)
118 *dirnamep = NULL;
119 if (codesetp)
120 *codesetp = NULL;
121 return;
124 __libc_rwlock_wrlock (_nl_state_lock);
126 modified = 0;
128 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
130 int compare = strcmp (domainname, binding->domainname);
131 if (compare == 0)
132 /* We found it! */
133 break;
134 if (compare < 0)
136 /* It is not in the list. */
137 binding = NULL;
138 break;
142 if (binding != NULL)
144 if (dirnamep)
146 const char *dirname = *dirnamep;
148 if (dirname == NULL)
149 /* The current binding has be to returned. */
150 *dirnamep = binding->dirname;
151 else
153 /* The domain is already bound. If the new value and the old
154 one are equal we simply do nothing. Otherwise replace the
155 old binding. */
156 char *result = binding->dirname;
157 if (strcmp (dirname, result) != 0)
159 if (strcmp (dirname, _nl_default_dirname) == 0)
160 result = (char *) _nl_default_dirname;
161 else
163 #if defined _LIBC || defined HAVE_STRDUP
164 result = strdup (dirname);
165 #else
166 size_t len = strlen (dirname) + 1;
167 result = (char *) malloc (len);
168 if (__builtin_expect (result != NULL, 1))
169 memcpy (result, dirname, len);
170 #endif
173 if (__builtin_expect (result != NULL, 1))
175 if (binding->dirname != _nl_default_dirname)
176 free (binding->dirname);
178 binding->dirname = result;
179 modified = 1;
182 *dirnamep = result;
186 if (codesetp)
188 const char *codeset = *codesetp;
190 if (codeset == NULL)
191 /* The current binding has be to returned. */
192 *codesetp = binding->codeset;
193 else
195 /* The domain is already bound. If the new value and the old
196 one are equal we simply do nothing. Otherwise replace the
197 old binding. */
198 char *result = binding->codeset;
199 if (result == NULL || strcmp (codeset, result) != 0)
201 #if defined _LIBC || defined HAVE_STRDUP
202 result = strdup (codeset);
203 #else
204 size_t len = strlen (codeset) + 1;
205 result = (char *) malloc (len);
206 if (__builtin_expect (result != NULL, 1))
207 memcpy (result, codeset, len);
208 #endif
210 if (__builtin_expect (result != NULL, 1))
212 if (binding->codeset != NULL)
213 free (binding->codeset);
215 binding->codeset = result;
216 modified = 1;
219 *codesetp = result;
223 else if ((dirnamep == NULL || *dirnamep == NULL)
224 && (codesetp == NULL || *codesetp == NULL))
226 /* Simply return the default values. */
227 if (dirnamep)
228 *dirnamep = _nl_default_dirname;
229 if (codesetp)
230 *codesetp = NULL;
232 else
234 /* We have to create a new binding. */
235 size_t len = strlen (domainname) + 1;
236 struct binding *new_binding =
237 (struct binding *) malloc (sizeof (*new_binding) + len);
239 if (__builtin_expect (new_binding == NULL, 0))
240 goto failed;
242 memcpy (new_binding->domainname, domainname, len);
244 if (dirnamep)
246 const char *dirname = *dirnamep;
248 if (dirname == NULL)
249 /* The default value. */
250 dirname = _nl_default_dirname;
251 else
253 if (strcmp (dirname, _nl_default_dirname) == 0)
254 dirname = _nl_default_dirname;
255 else
257 char *result;
258 #if defined _LIBC || defined HAVE_STRDUP
259 result = strdup (dirname);
260 if (__builtin_expect (result == NULL, 0))
261 goto failed_dirname;
262 #else
263 size_t len = strlen (dirname) + 1;
264 result = (char *) malloc (len);
265 if (__builtin_expect (result == NULL, 0))
266 goto failed_dirname;
267 memcpy (result, dirname, len);
268 #endif
269 dirname = result;
272 *dirnamep = dirname;
273 new_binding->dirname = (char *) dirname;
275 else
276 /* The default value. */
277 new_binding->dirname = (char *) _nl_default_dirname;
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;
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 != _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