Add Russian translation provided by Валерий Крувялис <valkru@mail.ru>
[xiph-mirror.git] / vorbis-tools / intl / bindtextdom.c
blobdab5d4f3577752b34b7327b21657177f7bf7fb50
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 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
45 #ifndef offsetof
46 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
47 #endif
49 /* @@ end of prolog @@ */
51 /* Lock variable to protect the global data in the gettext implementation. */
52 gl_rwlock_define (extern, _nl_state_lock attribute_hidden)
55 /* Names for the libintl functions are a problem. They must not clash
56 with existing names and they should follow ANSI C. But this source
57 code is also used in GNU C Library where the names have a __
58 prefix. So we have to make a difference here. */
59 #ifdef _LIBC
60 # define BINDTEXTDOMAIN __bindtextdomain
61 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
62 # ifndef strdup
63 # define strdup(str) __strdup (str)
64 # endif
65 #else
66 # define BINDTEXTDOMAIN libintl_bindtextdomain
67 # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
68 #endif
70 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
71 to be used for the DOMAINNAME message catalog.
72 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
73 modified, only the current value is returned.
74 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
75 modified nor returned. */
76 static void
77 set_binding_values (const char *domainname,
78 const char **dirnamep, const char **codesetp)
80 struct binding *binding;
81 int modified;
83 /* Some sanity checks. */
84 if (domainname == NULL || domainname[0] == '\0')
86 if (dirnamep)
87 *dirnamep = NULL;
88 if (codesetp)
89 *codesetp = NULL;
90 return;
93 gl_rwlock_wrlock (_nl_state_lock);
95 modified = 0;
97 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
99 int compare = strcmp (domainname, binding->domainname);
100 if (compare == 0)
101 /* We found it! */
102 break;
103 if (compare < 0)
105 /* It is not in the list. */
106 binding = NULL;
107 break;
111 if (binding != NULL)
113 if (dirnamep)
115 const char *dirname = *dirnamep;
117 if (dirname == NULL)
118 /* The current binding has be to returned. */
119 *dirnamep = binding->dirname;
120 else
122 /* The domain is already bound. If the new value and the old
123 one are equal we simply do nothing. Otherwise replace the
124 old binding. */
125 char *result = binding->dirname;
126 if (strcmp (dirname, result) != 0)
128 if (strcmp (dirname, _nl_default_dirname) == 0)
129 result = (char *) _nl_default_dirname;
130 else
132 #if defined _LIBC || defined HAVE_STRDUP
133 result = strdup (dirname);
134 #else
135 size_t len = strlen (dirname) + 1;
136 result = (char *) malloc (len);
137 if (__builtin_expect (result != NULL, 1))
138 memcpy (result, dirname, len);
139 #endif
142 if (__builtin_expect (result != NULL, 1))
144 if (binding->dirname != _nl_default_dirname)
145 free (binding->dirname);
147 binding->dirname = result;
148 modified = 1;
151 *dirnamep = result;
155 if (codesetp)
157 const char *codeset = *codesetp;
159 if (codeset == NULL)
160 /* The current binding has be to returned. */
161 *codesetp = binding->codeset;
162 else
164 /* The domain is already bound. If the new value and the old
165 one are equal we simply do nothing. Otherwise replace the
166 old binding. */
167 char *result = binding->codeset;
168 if (result == NULL || strcmp (codeset, result) != 0)
170 #if defined _LIBC || defined HAVE_STRDUP
171 result = strdup (codeset);
172 #else
173 size_t len = strlen (codeset) + 1;
174 result = (char *) malloc (len);
175 if (__builtin_expect (result != NULL, 1))
176 memcpy (result, codeset, len);
177 #endif
179 if (__builtin_expect (result != NULL, 1))
181 if (binding->codeset != NULL)
182 free (binding->codeset);
184 binding->codeset = result;
185 modified = 1;
188 *codesetp = result;
192 else if ((dirnamep == NULL || *dirnamep == NULL)
193 && (codesetp == NULL || *codesetp == NULL))
195 /* Simply return the default values. */
196 if (dirnamep)
197 *dirnamep = _nl_default_dirname;
198 if (codesetp)
199 *codesetp = NULL;
201 else
203 /* We have to create a new binding. */
204 size_t len = strlen (domainname) + 1;
205 struct binding *new_binding =
206 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
208 if (__builtin_expect (new_binding == NULL, 0))
209 goto failed;
211 memcpy (new_binding->domainname, domainname, len);
213 if (dirnamep)
215 const char *dirname = *dirnamep;
217 if (dirname == NULL)
218 /* The default value. */
219 dirname = _nl_default_dirname;
220 else
222 if (strcmp (dirname, _nl_default_dirname) == 0)
223 dirname = _nl_default_dirname;
224 else
226 char *result;
227 #if defined _LIBC || defined HAVE_STRDUP
228 result = strdup (dirname);
229 if (__builtin_expect (result == NULL, 0))
230 goto failed_dirname;
231 #else
232 size_t len = strlen (dirname) + 1;
233 result = (char *) malloc (len);
234 if (__builtin_expect (result == NULL, 0))
235 goto failed_dirname;
236 memcpy (result, dirname, len);
237 #endif
238 dirname = result;
241 *dirnamep = dirname;
242 new_binding->dirname = (char *) dirname;
244 else
245 /* The default value. */
246 new_binding->dirname = (char *) _nl_default_dirname;
248 if (codesetp)
250 const char *codeset = *codesetp;
252 if (codeset != NULL)
254 char *result;
256 #if defined _LIBC || defined HAVE_STRDUP
257 result = strdup (codeset);
258 if (__builtin_expect (result == NULL, 0))
259 goto failed_codeset;
260 #else
261 size_t len = strlen (codeset) + 1;
262 result = (char *) malloc (len);
263 if (__builtin_expect (result == NULL, 0))
264 goto failed_codeset;
265 memcpy (result, codeset, len);
266 #endif
267 codeset = result;
269 *codesetp = codeset;
270 new_binding->codeset = (char *) codeset;
272 else
273 new_binding->codeset = NULL;
275 /* Now enqueue it. */
276 if (_nl_domain_bindings == NULL
277 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
279 new_binding->next = _nl_domain_bindings;
280 _nl_domain_bindings = new_binding;
282 else
284 binding = _nl_domain_bindings;
285 while (binding->next != NULL
286 && strcmp (domainname, binding->next->domainname) > 0)
287 binding = binding->next;
289 new_binding->next = binding->next;
290 binding->next = new_binding;
293 modified = 1;
295 /* Here we deal with memory allocation failures. */
296 if (0)
298 failed_codeset:
299 if (new_binding->dirname != _nl_default_dirname)
300 free (new_binding->dirname);
301 failed_dirname:
302 free (new_binding);
303 failed:
304 if (dirnamep)
305 *dirnamep = NULL;
306 if (codesetp)
307 *codesetp = NULL;
311 /* If we modified any binding, we flush the caches. */
312 if (modified)
313 ++_nl_msg_cat_cntr;
315 gl_rwlock_unlock (_nl_state_lock);
318 /* Specify that the DOMAINNAME message catalog will be found
319 in DIRNAME rather than in the system locale data base. */
320 char *
321 BINDTEXTDOMAIN (const char *domainname, const char *dirname)
323 set_binding_values (domainname, &dirname, NULL);
324 return (char *) dirname;
327 /* Specify the character encoding in which the messages from the
328 DOMAINNAME message catalog will be returned. */
329 char *
330 BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset)
332 set_binding_values (domainname, NULL, &codeset);
333 return (char *) codeset;
336 #ifdef _LIBC
337 /* Aliases for function names in GNU C Library. */
338 weak_alias (__bindtextdomain, bindtextdomain);
339 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
340 #endif