]> git.saurik.com Git - bison.git/blame - intl/bindtextdom.c
Add.
[bison.git] / intl / bindtextdom.c
CommitLineData
705db0b5 1/* Implementation of the bindtextdomain(3) function
1e24cc5b 2 Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
705db0b5
AD
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program 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
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18#ifdef HAVE_CONFIG_H
19# include <config.h>
20#endif
21
1e24cc5b
AD
22#include <stddef.h>
23#include <stdlib.h>
24#include <string.h>
705db0b5 25
1e24cc5b
AD
26#ifdef _LIBC
27# include <libintl.h>
705db0b5 28#else
1e24cc5b 29# include "libgnuintl.h"
705db0b5 30#endif
1e24cc5b 31#include "gettextP.h"
705db0b5
AD
32
33#ifdef _LIBC
1e24cc5b
AD
34/* We have to handle multi-threaded applications. */
35# include <bits/libc-lock.h>
705db0b5 36#else
1e24cc5b
AD
37/* Provide dummy implementation if this is outside glibc. */
38# define __libc_rwlock_define(CLASS, NAME)
39# define __libc_rwlock_wrlock(NAME)
40# define __libc_rwlock_unlock(NAME)
41#endif
42
43/* The internal variables in the standalone libintl.a must have different
44 names than the internal variables in GNU libc, otherwise programs
45 using libintl.a cannot be linked statically. */
46#if !defined _LIBC
47# define _nl_default_dirname _nl_default_dirname__
48# define _nl_domain_bindings _nl_domain_bindings__
49#endif
50
51/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
52#ifndef offsetof
53# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
705db0b5 54#endif
705db0b5
AD
55
56/* @@ end of prolog @@ */
57
58/* Contains the default location of the message catalogs. */
59extern const char _nl_default_dirname[];
60
61/* List with bindings of specific domains. */
62extern struct binding *_nl_domain_bindings;
63
1e24cc5b
AD
64/* Lock variable to protect the global data in the gettext implementation. */
65__libc_rwlock_define (extern, _nl_state_lock)
66
705db0b5
AD
67
68/* Names for the libintl functions are a problem. They must not clash
69 with existing names and they should follow ANSI C. But this source
70 code is also used in GNU C Library where the names have a __
71 prefix. So we have to make a difference here. */
72#ifdef _LIBC
73# define BINDTEXTDOMAIN __bindtextdomain
1e24cc5b 74# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
705db0b5
AD
75# ifndef strdup
76# define strdup(str) __strdup (str)
77# endif
78#else
79# define BINDTEXTDOMAIN bindtextdomain__
1e24cc5b 80# define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
705db0b5
AD
81#endif
82
1e24cc5b
AD
83/* Prototypes for local functions. */
84static void set_binding_values PARAMS ((const char *domainname,
85 const char **dirnamep,
86 const char **codesetp));
87
88/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
89 to be used for the DOMAINNAME message catalog.
90 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
91 modified, only the current value is returned.
92 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
93 modified nor returned. */
94static void
95set_binding_values (domainname, dirnamep, codesetp)
705db0b5 96 const char *domainname;
1e24cc5b
AD
97 const char **dirnamep;
98 const char **codesetp;
705db0b5
AD
99{
100 struct binding *binding;
1e24cc5b 101 int modified;
705db0b5
AD
102
103 /* Some sanity checks. */
104 if (domainname == NULL || domainname[0] == '\0')
1e24cc5b
AD
105 {
106 if (dirnamep)
107 *dirnamep = NULL;
108 if (codesetp)
109 *codesetp = NULL;
110 return;
111 }
112
113 __libc_rwlock_wrlock (_nl_state_lock);
114
115 modified = 0;
705db0b5
AD
116
117 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
118 {
119 int compare = strcmp (domainname, binding->domainname);
120 if (compare == 0)
121 /* We found it! */
122 break;
123 if (compare < 0)
124 {
125 /* It is not in the list. */
126 binding = NULL;
127 break;
128 }
129 }
130
705db0b5
AD
131 if (binding != NULL)
132 {
1e24cc5b 133 if (dirnamep)
705db0b5 134 {
1e24cc5b 135 const char *dirname = *dirnamep;
705db0b5 136
1e24cc5b
AD
137 if (dirname == NULL)
138 /* The current binding has be to returned. */
139 *dirnamep = binding->dirname;
705db0b5
AD
140 else
141 {
1e24cc5b
AD
142 /* The domain is already bound. If the new value and the old
143 one are equal we simply do nothing. Otherwise replace the
144 old binding. */
145 char *result = binding->dirname;
146 if (strcmp (dirname, result) != 0)
147 {
148 if (strcmp (dirname, _nl_default_dirname) == 0)
149 result = (char *) _nl_default_dirname;
150 else
151 {
705db0b5 152#if defined _LIBC || defined HAVE_STRDUP
1e24cc5b 153 result = strdup (dirname);
705db0b5 154#else
1e24cc5b
AD
155 size_t len = strlen (dirname) + 1;
156 result = (char *) malloc (len);
157 if (__builtin_expect (result != NULL, 1))
158 memcpy (result, dirname, len);
705db0b5 159#endif
1e24cc5b
AD
160 }
161
162 if (__builtin_expect (result != NULL, 1))
163 {
164 if (binding->dirname != _nl_default_dirname)
165 free (binding->dirname);
166
167 binding->dirname = result;
168 modified = 1;
169 }
170 }
171 *dirnamep = result;
705db0b5 172 }
1e24cc5b 173 }
705db0b5 174
1e24cc5b
AD
175 if (codesetp)
176 {
177 const char *codeset = *codesetp;
705db0b5 178
1e24cc5b
AD
179 if (codeset == NULL)
180 /* The current binding has be to returned. */
181 *codesetp = binding->codeset;
182 else
183 {
184 /* The domain is already bound. If the new value and the old
185 one are equal we simply do nothing. Otherwise replace the
186 old binding. */
187 char *result = binding->codeset;
188 if (result == NULL || strcmp (codeset, result) != 0)
189 {
190#if defined _LIBC || defined HAVE_STRDUP
191 result = strdup (codeset);
192#else
193 size_t len = strlen (codeset) + 1;
194 result = (char *) malloc (len);
195 if (__builtin_expect (result != NULL, 1))
196 memcpy (result, codeset, len);
197#endif
198
199 if (__builtin_expect (result != NULL, 1))
200 {
201 if (binding->codeset != NULL)
202 free (binding->codeset);
203
204 binding->codeset = result;
205 binding->codeset_cntr++;
206 modified = 1;
207 }
208 }
209 *codesetp = result;
210 }
705db0b5
AD
211 }
212 }
1e24cc5b
AD
213 else if ((dirnamep == NULL || *dirnamep == NULL)
214 && (codesetp == NULL || *codesetp == NULL))
215 {
216 /* Simply return the default values. */
217 if (dirnamep)
218 *dirnamep = _nl_default_dirname;
219 if (codesetp)
220 *codesetp = NULL;
221 }
705db0b5
AD
222 else
223 {
224 /* We have to create a new binding. */
1e24cc5b 225 size_t len = strlen (domainname) + 1;
705db0b5 226 struct binding *new_binding =
1e24cc5b
AD
227 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
228
229 if (__builtin_expect (new_binding == NULL, 0))
230 goto failed;
705db0b5 231
1e24cc5b
AD
232 memcpy (new_binding->domainname, domainname, len);
233
234 if (dirnamep)
235 {
236 const char *dirname = *dirnamep;
705db0b5 237
1e24cc5b
AD
238 if (dirname == NULL)
239 /* The default value. */
240 dirname = _nl_default_dirname;
241 else
242 {
243 if (strcmp (dirname, _nl_default_dirname) == 0)
244 dirname = _nl_default_dirname;
245 else
246 {
247 char *result;
705db0b5 248#if defined _LIBC || defined HAVE_STRDUP
1e24cc5b
AD
249 result = strdup (dirname);
250 if (__builtin_expect (result == NULL, 0))
251 goto failed_dirname;
705db0b5 252#else
1e24cc5b
AD
253 size_t len = strlen (dirname) + 1;
254 result = (char *) malloc (len);
255 if (__builtin_expect (result == NULL, 0))
256 goto failed_dirname;
257 memcpy (result, dirname, len);
705db0b5 258#endif
1e24cc5b
AD
259 dirname = result;
260 }
261 }
262 *dirnamep = dirname;
263 new_binding->dirname = (char *) dirname;
264 }
705db0b5 265 else
1e24cc5b
AD
266 /* The default value. */
267 new_binding->dirname = (char *) _nl_default_dirname;
268
269 new_binding->codeset_cntr = 0;
270
271 if (codesetp)
705db0b5 272 {
1e24cc5b
AD
273 const char *codeset = *codesetp;
274
275 if (codeset != NULL)
276 {
277 char *result;
278
705db0b5 279#if defined _LIBC || defined HAVE_STRDUP
1e24cc5b
AD
280 result = strdup (codeset);
281 if (__builtin_expect (result == NULL, 0))
282 goto failed_codeset;
705db0b5 283#else
1e24cc5b
AD
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);
705db0b5 289#endif
1e24cc5b
AD
290 codeset = result;
291 new_binding->codeset_cntr++;
292 }
293 *codesetp = codeset;
294 new_binding->codeset = (char *) codeset;
705db0b5 295 }
1e24cc5b
AD
296 else
297 new_binding->codeset = NULL;
705db0b5
AD
298
299 /* Now enqueue it. */
300 if (_nl_domain_bindings == NULL
301 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
302 {
303 new_binding->next = _nl_domain_bindings;
304 _nl_domain_bindings = new_binding;
305 }
306 else
307 {
308 binding = _nl_domain_bindings;
309 while (binding->next != NULL
310 && strcmp (domainname, binding->next->domainname) > 0)
311 binding = binding->next;
312
313 new_binding->next = binding->next;
314 binding->next = new_binding;
315 }
316
1e24cc5b
AD
317 modified = 1;
318
319 /* Here we deal with memory allocation failures. */
320 if (0)
321 {
322 failed_codeset:
323 if (new_binding->dirname != _nl_default_dirname)
324 free (new_binding->dirname);
325 failed_dirname:
326 free (new_binding);
327 failed:
328 if (dirnamep)
329 *dirnamep = NULL;
330 if (codesetp)
331 *codesetp = NULL;
332 }
705db0b5
AD
333 }
334
1e24cc5b
AD
335 /* If we modified any binding, we flush the caches. */
336 if (modified)
337 ++_nl_msg_cat_cntr;
338
339 __libc_rwlock_unlock (_nl_state_lock);
340}
341
342/* Specify that the DOMAINNAME message catalog will be found
343 in DIRNAME rather than in the system locale data base. */
344char *
345BINDTEXTDOMAIN (domainname, dirname)
346 const char *domainname;
347 const char *dirname;
348{
349 set_binding_values (domainname, &dirname, NULL);
350 return (char *) dirname;
351}
352
353/* Specify the character encoding in which the messages from the
354 DOMAINNAME message catalog will be returned. */
355char *
356BIND_TEXTDOMAIN_CODESET (domainname, codeset)
357 const char *domainname;
358 const char *codeset;
359{
360 set_binding_values (domainname, NULL, &codeset);
361 return (char *) codeset;
705db0b5
AD
362}
363
364#ifdef _LIBC
1e24cc5b 365/* Aliases for function names in GNU C Library. */
705db0b5 366weak_alias (__bindtextdomain, bindtextdomain);
1e24cc5b 367weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
705db0b5 368#endif