source: trunk/third/gaim-encryption/intl/bindtextdom.c @ 22512

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