No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / grep / intl / bindtextdom.c
blob6dff80cc40d3efa2d06bee4c4f6b39b939f34265
1 /* $NetBSD$ */
3 /* Implementation of the bindtextdomain(3) function
4 Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Library General Public License as published
8 by the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 USA. */
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
25 #include <stddef.h>
26 #include <stdlib.h>
27 #include <string.h>
29 #ifdef _LIBC
30 # include <libintl.h>
31 #else
32 # include "libgnuintl.h"
33 #endif
34 #include "gettextP.h"
36 #ifdef _LIBC
37 /* We have to handle multi-threaded applications. */
38 # include <bits/libc-lock.h>
39 #else
40 /* Provide dummy implementation if this is outside glibc. */
41 # define __libc_rwlock_define(CLASS, NAME)
42 # define __libc_rwlock_wrlock(NAME)
43 # define __libc_rwlock_unlock(NAME)
44 #endif
46 /* The internal variables in the standalone libintl.a must have different
47 names than the internal variables in GNU libc, otherwise programs
48 using libintl.a cannot be linked statically. */
49 #if !defined _LIBC
50 # define _nl_default_dirname _nl_default_dirname__
51 # define _nl_domain_bindings _nl_domain_bindings__
52 #endif
54 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
55 #ifndef offsetof
56 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
57 #endif
59 /* @@ end of prolog @@ */
61 /* Contains the default location of the message catalogs. */
62 extern const char _nl_default_dirname[];
64 /* List with bindings of specific domains. */
65 extern struct binding *_nl_domain_bindings;
67 /* Lock variable to protect the global data in the gettext implementation. */
68 __libc_rwlock_define (extern, _nl_state_lock)
71 /* Names for the libintl functions are a problem. They must not clash
72 with existing names and they should follow ANSI C. But this source
73 code is also used in GNU C Library where the names have a __
74 prefix. So we have to make a difference here. */
75 #ifdef _LIBC
76 # define BINDTEXTDOMAIN __bindtextdomain
77 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
78 # ifndef strdup
79 # define strdup(str) __strdup (str)
80 # endif
81 #else
82 # define BINDTEXTDOMAIN bindtextdomain__
83 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
84 #endif
86 /* Prototypes for local functions. */
87 static void set_binding_values PARAMS ((const char *domainname,
88 const char **dirnamep,
89 const char **codesetp));
91 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
92 to be used for the DOMAINNAME message catalog.
93 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
94 modified, only the current value is returned.
95 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
96 modified nor returned. */
97 static void
98 set_binding_values (domainname, dirnamep, codesetp)
99 const char *domainname;
100 const char **dirnamep;
101 const char **codesetp;
103 struct binding *binding;
104 int modified;
106 /* Some sanity checks. */
107 if (domainname == NULL || domainname[0] == '\0')
109 if (dirnamep)
110 *dirnamep = NULL;
111 if (codesetp)
112 *codesetp = NULL;
113 return;
116 __libc_rwlock_wrlock (_nl_state_lock);
118 modified = 0;
120 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
122 int compare = strcmp (domainname, binding->domainname);
123 if (compare == 0)
124 /* We found it! */
125 break;
126 if (compare < 0)
128 /* It is not in the list. */
129 binding = NULL;
130 break;
134 if (binding != NULL)
136 if (dirnamep)
138 const char *dirname = *dirnamep;
140 if (dirname == NULL)
141 /* The current binding has be to returned. */
142 *dirnamep = binding->dirname;
143 else
145 /* The domain is already bound. If the new value and the old
146 one are equal we simply do nothing. Otherwise replace the
147 old binding. */
148 char *result = binding->dirname;
149 if (strcmp (dirname, result) != 0)
151 if (strcmp (dirname, _nl_default_dirname) == 0)
152 result = (char *) _nl_default_dirname;
153 else
155 #if defined _LIBC || defined HAVE_STRDUP
156 result = strdup (dirname);
157 #else
158 size_t len = strlen (dirname) + 1;
159 result = (char *) malloc (len);
160 if (__builtin_expect (result != NULL, 1))
161 memcpy (result, dirname, len);
162 #endif
165 if (__builtin_expect (result != NULL, 1))
167 if (binding->dirname != _nl_default_dirname)
168 free (binding->dirname);
170 binding->dirname = result;
171 modified = 1;
174 *dirnamep = result;
178 if (codesetp)
180 const char *codeset = *codesetp;
182 if (codeset == NULL)
183 /* The current binding has be to returned. */
184 *codesetp = binding->codeset;
185 else
187 /* The domain is already bound. If the new value and the old
188 one are equal we simply do nothing. Otherwise replace the
189 old binding. */
190 char *result = binding->codeset;
191 if (result == NULL || strcmp (codeset, result) != 0)
193 #if defined _LIBC || defined HAVE_STRDUP
194 result = strdup (codeset);
195 #else
196 size_t len = strlen (codeset) + 1;
197 result = (char *) malloc (len);
198 if (__builtin_expect (result != NULL, 1))
199 memcpy (result, codeset, len);
200 #endif
202 if (__builtin_expect (result != NULL, 1))
204 if (binding->codeset != NULL)
205 free (binding->codeset);
207 binding->codeset = result;
208 binding->codeset_cntr++;
209 modified = 1;
212 *codesetp = result;
216 else if ((dirnamep == NULL || *dirnamep == NULL)
217 && (codesetp == NULL || *codesetp == NULL))
219 /* Simply return the default values. */
220 if (dirnamep)
221 *dirnamep = _nl_default_dirname;
222 if (codesetp)
223 *codesetp = NULL;
225 else
227 /* We have to create a new binding. */
228 size_t len = strlen (domainname) + 1;
229 struct binding *new_binding =
230 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
232 if (__builtin_expect (new_binding == NULL, 0))
233 goto failed;
235 memcpy (new_binding->domainname, domainname, len);
237 if (dirnamep)
239 const char *dirname = *dirnamep;
241 if (dirname == NULL)
242 /* The default value. */
243 dirname = _nl_default_dirname;
244 else
246 if (strcmp (dirname, _nl_default_dirname) == 0)
247 dirname = _nl_default_dirname;
248 else
250 char *result;
251 #if defined _LIBC || defined HAVE_STRDUP
252 result = strdup (dirname);
253 if (__builtin_expect (result == NULL, 0))
254 goto failed_dirname;
255 #else
256 size_t len = strlen (dirname) + 1;
257 result = (char *) malloc (len);
258 if (__builtin_expect (result == NULL, 0))
259 goto failed_dirname;
260 memcpy (result, dirname, len);
261 #endif
262 dirname = result;
265 *dirnamep = dirname;
266 new_binding->dirname = (char *) dirname;
268 else
269 /* The default value. */
270 new_binding->dirname = (char *) _nl_default_dirname;
272 new_binding->codeset_cntr = 0;
274 if (codesetp)
276 const char *codeset = *codesetp;
278 if (codeset != NULL)
280 char *result;
282 #if defined _LIBC || defined HAVE_STRDUP
283 result = strdup (codeset);
284 if (__builtin_expect (result == NULL, 0))
285 goto failed_codeset;
286 #else
287 size_t len = strlen (codeset) + 1;
288 result = (char *) malloc (len);
289 if (__builtin_expect (result == NULL, 0))
290 goto failed_codeset;
291 memcpy (result, codeset, len);
292 #endif
293 codeset = result;
294 new_binding->codeset_cntr++;
296 *codesetp = codeset;
297 new_binding->codeset = (char *) codeset;
299 else
300 new_binding->codeset = NULL;
302 /* Now enqueue it. */
303 if (_nl_domain_bindings == NULL
304 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
306 new_binding->next = _nl_domain_bindings;
307 _nl_domain_bindings = new_binding;
309 else
311 binding = _nl_domain_bindings;
312 while (binding->next != NULL
313 && strcmp (domainname, binding->next->domainname) > 0)
314 binding = binding->next;
316 new_binding->next = binding->next;
317 binding->next = new_binding;
320 modified = 1;
322 /* Here we deal with memory allocation failures. */
323 if (0)
325 failed_codeset:
326 if (new_binding->dirname != _nl_default_dirname)
327 free (new_binding->dirname);
328 failed_dirname:
329 free (new_binding);
330 failed:
331 if (dirnamep)
332 *dirnamep = NULL;
333 if (codesetp)
334 *codesetp = NULL;
338 /* If we modified any binding, we flush the caches. */
339 if (modified)
340 ++_nl_msg_cat_cntr;
342 __libc_rwlock_unlock (_nl_state_lock);
345 /* Specify that the DOMAINNAME message catalog will be found
346 in DIRNAME rather than in the system locale data base. */
347 char *
348 BINDTEXTDOMAIN (domainname, dirname)
349 const char *domainname;
350 const char *dirname;
352 set_binding_values (domainname, &dirname, NULL);
353 return (char *) dirname;
356 /* Specify the character encoding in which the messages from the
357 DOMAINNAME message catalog will be returned. */
358 char *
359 BIND_TEXTDOMAIN_CODESET (domainname, codeset)
360 const char *domainname;
361 const char *codeset;
363 set_binding_values (domainname, NULL, &codeset);
364 return (char *) codeset;
367 #ifdef _LIBC
368 /* Aliases for function names in GNU C Library. */
369 weak_alias (__bindtextdomain, bindtextdomain);
370 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
371 #endif