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