* Text.cpp (dissolveInset):
[lyx.git] / intl / bindtextdom.c
blobd1b1f9028f3c3fdda1fcab92230eea629267b27d
1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000-2003, 2005-2006 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published
6 by the Free Software Foundation; either version 2, or (at your option)
7 any later version.
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 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 this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 USA. */
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
23 #include <stddef.h>
24 #include <stdlib.h>
25 #include <string.h>
27 #include "gettextP.h"
28 #ifdef _LIBC
29 # include <libintl.h>
30 #else
31 # include "libgnuintl.h"
32 #endif
34 /* Handle multi-threaded applications. */
35 #ifdef _LIBC
36 # include <bits/libc-lock.h>
37 # define gl_rwlock_define __libc_rwlock_define
38 # define gl_rwlock_wrlock __libc_rwlock_wrlock
39 # define gl_rwlock_unlock __libc_rwlock_unlock
40 #else
41 # include "lock.h"
42 #endif
44 /* The internal variables in the standalone libintl.a must have different
45 names than the internal variables in GNU libc, otherwise programs
46 using libintl.a cannot be linked statically. */
47 #if !defined _LIBC
48 # define _nl_default_dirname libintl_nl_default_dirname
49 # define _nl_domain_bindings libintl_nl_domain_bindings
50 #endif
52 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
53 #ifndef offsetof
54 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
55 #endif
57 /* @@ end of prolog @@ */
59 /* Contains the default location of the message catalogs. */
60 extern const char _nl_default_dirname[];
61 #ifdef _LIBC
62 libc_hidden_proto (_nl_default_dirname)
63 #endif
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 gl_rwlock_define (extern, _nl_state_lock attribute_hidden)
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 libintl_bindtextdomain
84 # define BIND_TEXTDOMAIN_CODESET libintl_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 (const char *domainname,
95 const char **dirnamep, const char **codesetp)
97 struct binding *binding;
98 int modified;
100 /* Some sanity checks. */
101 if (domainname == NULL || domainname[0] == '\0')
103 if (dirnamep)
104 *dirnamep = NULL;
105 if (codesetp)
106 *codesetp = NULL;
107 return;
110 gl_rwlock_wrlock (_nl_state_lock);
112 modified = 0;
114 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
116 int compare = strcmp (domainname, binding->domainname);
117 if (compare == 0)
118 /* We found it! */
119 break;
120 if (compare < 0)
122 /* It is not in the list. */
123 binding = NULL;
124 break;
128 if (binding != NULL)
130 if (dirnamep)
132 const char *dirname = *dirnamep;
134 if (dirname == NULL)
135 /* The current binding has be to returned. */
136 *dirnamep = binding->dirname;
137 else
139 /* The domain is already bound. If the new value and the old
140 one are equal we simply do nothing. Otherwise replace the
141 old binding. */
142 char *result = binding->dirname;
143 if (strcmp (dirname, result) != 0)
145 if (strcmp (dirname, _nl_default_dirname) == 0)
146 result = (char *) _nl_default_dirname;
147 else
149 #if defined _LIBC || defined HAVE_STRDUP
150 result = strdup (dirname);
151 #else
152 size_t len = strlen (dirname) + 1;
153 result = (char *) malloc (len);
154 if (__builtin_expect (result != NULL, 1))
155 memcpy (result, dirname, len);
156 #endif
159 if (__builtin_expect (result != NULL, 1))
161 if (binding->dirname != _nl_default_dirname)
162 free (binding->dirname);
164 binding->dirname = result;
165 modified = 1;
168 *dirnamep = result;
172 if (codesetp)
174 const char *codeset = *codesetp;
176 if (codeset == NULL)
177 /* The current binding has be to returned. */
178 *codesetp = binding->codeset;
179 else
181 /* The domain is already bound. If the new value and the old
182 one are equal we simply do nothing. Otherwise replace the
183 old binding. */
184 char *result = binding->codeset;
185 if (result == NULL || strcmp (codeset, result) != 0)
187 #if defined _LIBC || defined HAVE_STRDUP
188 result = strdup (codeset);
189 #else
190 size_t len = strlen (codeset) + 1;
191 result = (char *) malloc (len);
192 if (__builtin_expect (result != NULL, 1))
193 memcpy (result, codeset, len);
194 #endif
196 if (__builtin_expect (result != NULL, 1))
198 if (binding->codeset != NULL)
199 free (binding->codeset);
201 binding->codeset = result;
202 modified = 1;
205 *codesetp = result;
209 else if ((dirnamep == NULL || *dirnamep == NULL)
210 && (codesetp == NULL || *codesetp == NULL))
212 /* Simply return the default values. */
213 if (dirnamep)
214 *dirnamep = _nl_default_dirname;
215 if (codesetp)
216 *codesetp = NULL;
218 else
220 /* We have to create a new binding. */
221 size_t len = strlen (domainname) + 1;
222 struct binding *new_binding =
223 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
225 if (__builtin_expect (new_binding == NULL, 0))
226 goto failed;
228 memcpy (new_binding->domainname, domainname, len);
230 if (dirnamep)
232 const char *dirname = *dirnamep;
234 if (dirname == NULL)
235 /* The default value. */
236 dirname = _nl_default_dirname;
237 else
239 if (strcmp (dirname, _nl_default_dirname) == 0)
240 dirname = _nl_default_dirname;
241 else
243 char *result;
244 #if defined _LIBC || defined HAVE_STRDUP
245 result = strdup (dirname);
246 if (__builtin_expect (result == NULL, 0))
247 goto failed_dirname;
248 #else
249 size_t len = strlen (dirname) + 1;
250 result = (char *) malloc (len);
251 if (__builtin_expect (result == NULL, 0))
252 goto failed_dirname;
253 memcpy (result, dirname, len);
254 #endif
255 dirname = result;
258 *dirnamep = dirname;
259 new_binding->dirname = (char *) dirname;
261 else
262 /* The default value. */
263 new_binding->dirname = (char *) _nl_default_dirname;
265 if (codesetp)
267 const char *codeset = *codesetp;
269 if (codeset != NULL)
271 char *result;
273 #if defined _LIBC || defined HAVE_STRDUP
274 result = strdup (codeset);
275 if (__builtin_expect (result == NULL, 0))
276 goto failed_codeset;
277 #else
278 size_t len = strlen (codeset) + 1;
279 result = (char *) malloc (len);
280 if (__builtin_expect (result == NULL, 0))
281 goto failed_codeset;
282 memcpy (result, codeset, len);
283 #endif
284 codeset = result;
286 *codesetp = codeset;
287 new_binding->codeset = (char *) codeset;
289 else
290 new_binding->codeset = NULL;
292 /* Now enqueue it. */
293 if (_nl_domain_bindings == NULL
294 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
296 new_binding->next = _nl_domain_bindings;
297 _nl_domain_bindings = new_binding;
299 else
301 binding = _nl_domain_bindings;
302 while (binding->next != NULL
303 && strcmp (domainname, binding->next->domainname) > 0)
304 binding = binding->next;
306 new_binding->next = binding->next;
307 binding->next = new_binding;
310 modified = 1;
312 /* Here we deal with memory allocation failures. */
313 if (0)
315 failed_codeset:
316 if (new_binding->dirname != _nl_default_dirname)
317 free (new_binding->dirname);
318 failed_dirname:
319 free (new_binding);
320 failed:
321 if (dirnamep)
322 *dirnamep = NULL;
323 if (codesetp)
324 *codesetp = NULL;
328 /* If we modified any binding, we flush the caches. */
329 if (modified)
330 ++_nl_msg_cat_cntr;
332 gl_rwlock_unlock (_nl_state_lock);
335 /* Specify that the DOMAINNAME message catalog will be found
336 in DIRNAME rather than in the system locale data base. */
337 char *
338 BINDTEXTDOMAIN (const char *domainname, const char *dirname)
340 set_binding_values (domainname, &dirname, NULL);
341 return (char *) dirname;
344 /* Specify the character encoding in which the messages from the
345 DOMAINNAME message catalog will be returned. */
346 char *
347 BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset)
349 set_binding_values (domainname, NULL, &codeset);
350 return (char *) codeset;
353 #ifdef _LIBC
354 /* Aliases for function names in GNU C Library. */
355 weak_alias (__bindtextdomain, bindtextdomain);
356 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
357 #endif