~ubuntu-branches/ubuntu/vivid/ssed/vivid

« back to all changes in this revision

Viewing changes to intl/bindtextdom.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Metzler
  • Date: 2004-03-23 16:45:36 UTC
  • Revision ID: james.westby@ubuntu.com-20040323164536-r0jrs8udv1ftwoac
Tags: upstream-3.60
ImportĀ upstreamĀ versionĀ 3.60

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <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.  */
 
60
extern const char _nl_default_dirname[];
 
61
 
 
62
/* List with bindings of specific domains.  */
 
63
extern 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.  */
 
85
static 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.  */
 
95
static void
 
96
set_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.  */
 
345
char *
 
346
BINDTEXTDOMAIN (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.  */
 
356
char *
 
357
BIND_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.  */
 
367
weak_alias (__bindtextdomain, bindtextdomain);
 
368
weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
 
369
#endif