Update.
[glibc.git] / intl / bindtextdom.c
blob3d49344aaf8410c40b21fdb61ac379d4fa32ed41
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 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
88 to be used for the DOMAINNAME message catalog.
89 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
90 modified, only the current value is returned.
91 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
92 modified nor returned. */
93 static void
94 set_binding_values (domainname, dirnamep, codesetp)
95 const char *domainname;
96 const char **dirnamep;
97 const char **codesetp;
99 struct binding *binding;
100 int modified;
102 /* Some sanity checks. */
103 if (domainname == NULL || domainname[0] == '\0')
105 if (dirnamep)
106 *dirnamep = NULL;
107 if (codesetp)
108 *codesetp = NULL;
109 return;
112 __libc_rwlock_wrlock (_nl_state_lock);
114 modified = 0;
116 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
118 int compare = strcmp (domainname, binding->domainname);
119 if (compare == 0)
120 /* We found it! */
121 break;
122 if (compare < 0)
124 /* It is not in the list. */
125 binding = NULL;
126 break;
130 if (binding != NULL)
132 if (dirnamep)
134 const char *dirname = *dirnamep;
136 if (dirname == NULL)
137 /* The current binding has be to returned. */
138 *dirnamep = binding->dirname;
139 else
141 /* The domain is already bound. If the new value and the old
142 one are equal we simply do nothing. Otherwise replace the
143 old binding. */
144 char *result = binding->dirname;
145 if (strcmp (dirname, result) != 0)
147 if (strcmp (dirname, _nl_default_dirname) == 0)
148 result = (char *) _nl_default_dirname;
149 else
151 #if defined _LIBC || defined HAVE_STRDUP
152 result = strdup (dirname);
153 #else
154 size_t len = strlen (dirname) + 1;
155 result = (char *) malloc (len);
156 if (__builtin_expect (result != NULL, 1))
157 memcpy (result, dirname, len);
158 #endif
161 if (__builtin_expect (result != NULL, 1))
163 if (binding->dirname != _nl_default_dirname)
164 free (binding->dirname);
166 binding->dirname = result;
167 modified = 1;
170 *dirnamep = result;
174 if (codesetp)
176 const char *codeset = *codesetp;
178 if (codeset == NULL)
179 /* The current binding has be to returned. */
180 *codesetp = binding->codeset;
181 else
183 /* The domain is already bound. If the new value and the old
184 one are equal we simply do nothing. Otherwise replace the
185 old binding. */
186 char *result = binding->codeset;
187 if (result == NULL || strcmp (codeset, result) != 0)
189 #if defined _LIBC || defined HAVE_STRDUP
190 result = strdup (codeset);
191 #else
192 size_t len = strlen (codeset) + 1;
193 result = (char *) malloc (len);
194 if (__builtin_expect (result != NULL, 1))
195 memcpy (result, codeset, len);
196 #endif
198 if (__builtin_expect (result != NULL, 1))
200 if (binding->codeset != NULL)
201 free (binding->codeset);
203 binding->codeset = result;
204 modified = 1;
207 *codesetp = result;
211 else if ((dirnamep == NULL || *dirnamep == NULL)
212 && (codesetp == NULL || *codesetp == NULL))
214 /* Simply return the default values. */
215 if (dirnamep)
216 *dirnamep = _nl_default_dirname;
217 if (codesetp)
218 *codesetp = NULL;
220 else
222 /* We have to create a new binding. */
223 size_t len = strlen (domainname) + 1;
224 struct binding *new_binding =
225 (struct binding *) malloc (sizeof (*new_binding) + len);
227 if (__builtin_expect (new_binding == NULL, 0))
228 goto failed;
230 memcpy (new_binding->domainname, domainname, len);
232 if (dirnamep)
234 const char *dirname = *dirnamep;
236 if (dirname == NULL)
237 /* The default value. */
238 dirname = _nl_default_dirname;
239 else
241 if (strcmp (dirname, _nl_default_dirname) == 0)
242 dirname = _nl_default_dirname;
243 else
245 char *result;
246 #if defined _LIBC || defined HAVE_STRDUP
247 result = strdup (dirname);
248 if (__builtin_expect (result == NULL, 0))
249 goto failed_dirname;
250 #else
251 size_t len = strlen (dirname) + 1;
252 result = (char *) malloc (len);
253 if (__builtin_expect (result == NULL, 0))
254 goto failed_dirname;
255 memcpy (result, dirname, len);
256 #endif
257 dirname = result;
260 *dirnamep = dirname;
261 new_binding->dirname = (char *) dirname;
263 else
264 /* The default value. */
265 new_binding->dirname = (char *) _nl_default_dirname;
267 if (codesetp)
269 const char *codeset = *codesetp;
271 if (codeset != NULL)
273 char *result;
275 #if defined _LIBC || defined HAVE_STRDUP
276 result = strdup (codeset);
277 if (__builtin_expect (result == NULL, 0))
278 goto failed_codeset;
279 #else
280 size_t len = strlen (codeset) + 1;
281 result = (char *) malloc (len);
282 if (__builtin_expect (result == NULL, 0))
283 goto failed_codeset;
284 memcpy (result, codeset, len);
285 #endif
286 codeset = result;
288 *codesetp = codeset;
289 new_binding->codeset = (char *) codeset;
291 else
292 new_binding->codeset = NULL;
294 /* Now enqueue it. */
295 if (_nl_domain_bindings == NULL
296 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
298 new_binding->next = _nl_domain_bindings;
299 _nl_domain_bindings = new_binding;
301 else
303 binding = _nl_domain_bindings;
304 while (binding->next != NULL
305 && strcmp (domainname, binding->next->domainname) > 0)
306 binding = binding->next;
308 new_binding->next = binding->next;
309 binding->next = new_binding;
312 modified = 1;
314 /* Here we deal with memory allocation failures. */
315 if (0)
317 failed_codeset:
318 if (new_binding->dirname != _nl_default_dirname)
319 free (new_binding->dirname);
320 failed_dirname:
321 free (new_binding);
322 failed:
323 if (dirnamep)
324 *dirnamep = NULL;
325 if (codesetp)
326 *codesetp = NULL;
330 /* If we modified any binding, we flush the caches. */
331 if (modified)
332 ++_nl_msg_cat_cntr;
334 __libc_rwlock_unlock (_nl_state_lock);
337 /* Specify that the DOMAINNAME message catalog will be found
338 in DIRNAME rather than in the system locale data base. */
339 char *
340 BINDTEXTDOMAIN (domainname, dirname)
341 const char *domainname;
342 const char *dirname;
344 set_binding_values (domainname, &dirname, NULL);
345 return (char *) dirname;
348 /* Specify the character encoding in which the messages from the
349 DOMAINNAME message catalog will be returned. */
350 char *
351 BIND_TEXTDOMAIN_CODESET (domainname, codeset)
352 const char *domainname;
353 const char *codeset;
355 set_binding_values (domainname, NULL, &codeset);
356 return (char *) codeset;
359 #ifdef _LIBC
360 /* Aliases for function names in GNU C Library. */
361 weak_alias (__bindtextdomain, bindtextdomain);
362 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
363 #endif