~ubuntu-branches/ubuntu/lucid/groundhog/lucid

« back to all changes in this revision

Viewing changes to intl/bindtextdom.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2004-08-20 23:12:32 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20040820231232-18s0op2f9g21ag1z
Tags: 1.4-6
Update Policy Version

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Implementation of the bindtextdomain(3) function
2
 
   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
 
2
   Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc.
3
3
 
4
 
   This program is free software; you can redistribute it and/or modify
5
 
   it under the terms of the GNU General Public License as published by
6
 
   the Free Software Foundation; either version 2, or (at your option)
 
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
7
   any later version.
8
8
 
9
9
   This program is distributed in the hope that it will be useful,
10
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
   GNU General Public License for more details.
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
   Library General Public License for more details.
13
13
 
14
 
   You should have received a copy of the GNU General Public License
15
 
   along with this program; if not, write to the Free Software Foundation,
16
 
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
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.  */
17
18
 
18
19
#ifdef HAVE_CONFIG_H
19
20
# include <config.h>
20
21
#endif
21
22
 
22
 
#if defined STDC_HEADERS || defined _LIBC
23
 
# include <stdlib.h>
24
 
#else
25
 
# ifdef HAVE_MALLOC_H
26
 
#  include <malloc.h>
27
 
# else
28
 
void free ();
29
 
# endif
30
 
#endif
31
 
 
32
 
#if defined HAVE_STRING_H || defined _LIBC
33
 
# include <string.h>
34
 
#else
35
 
# include <strings.h>
36
 
# ifndef memcpy
37
 
#  define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
38
 
# endif
39
 
#endif
 
23
#include <stddef.h>
 
24
#include <stdlib.h>
 
25
#include <string.h>
40
26
 
41
27
#ifdef _LIBC
42
28
# include <libintl.h>
43
29
#else
44
 
# include "libgettext.h"
 
30
# include "libgnuintl.h"
45
31
#endif
46
 
#include "gettext.h"
47
32
#include "gettextP.h"
48
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
 
49
57
/* @@ end of prolog @@ */
50
58
 
51
59
/* Contains the default location of the message catalogs.  */
54
62
/* List with bindings of specific domains.  */
55
63
extern struct binding *_nl_domain_bindings;
56
64
 
 
65
/* Lock variable to protect the global data in the gettext implementation.  */
 
66
__libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
 
67
 
57
68
 
58
69
/* Names for the libintl functions are a problem.  They must not clash
59
70
   with existing names and they should follow ANSI C.  But this source
61
72
   prefix.  So we have to make a difference here.  */
62
73
#ifdef _LIBC
63
74
# define BINDTEXTDOMAIN __bindtextdomain
 
75
# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
64
76
# ifndef strdup
65
77
#  define strdup(str) __strdup (str)
66
78
# endif
67
79
#else
68
80
# define BINDTEXTDOMAIN bindtextdomain__
 
81
# define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
69
82
#endif
70
83
 
71
 
/* Specify that the DOMAINNAME message catalog will be found
72
 
   in DIRNAME rather than in the system locale data base.  */
73
 
char *
74
 
BINDTEXTDOMAIN (domainname, dirname)
 
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)
75
97
     const char *domainname;
76
 
     const char *dirname;
 
98
     const char **dirnamep;
 
99
     const char **codesetp;
77
100
{
78
101
  struct binding *binding;
 
102
  int modified;
79
103
 
80
104
  /* Some sanity checks.  */
81
105
  if (domainname == NULL || domainname[0] == '\0')
82
 
    return NULL;
 
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;
83
117
 
84
118
  for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
85
119
    {
95
129
        }
96
130
    }
97
131
 
98
 
  if (dirname == NULL)
99
 
    /* The current binding has be to returned.  */
100
 
    return binding == NULL ? (char *) _nl_default_dirname : binding->dirname;
101
 
 
102
132
  if (binding != NULL)
103
133
    {
104
 
      /* The domain is already bound.  If the new value and the old
105
 
         one are equal we simply do nothing.  Otherwise replace the
106
 
         old binding.  */
107
 
      if (strcmp (dirname, binding->dirname) != 0)
108
 
        {
109
 
          char *new_dirname;
110
 
 
111
 
          if (strcmp (dirname, _nl_default_dirname) == 0)
112
 
            new_dirname = (char *) _nl_default_dirname;
113
 
          else
114
 
            {
115
 
#if defined _LIBC || defined HAVE_STRDUP
116
 
              new_dirname = strdup (dirname);
117
 
              if (new_dirname == NULL)
118
 
                return NULL;
119
 
#else
120
 
              size_t len = strlen (dirname) + 1;
121
 
              new_dirname = (char *) malloc (len);
122
 
              if (new_dirname == NULL)
123
 
                return NULL;
124
 
 
125
 
              memcpy (new_dirname, dirname, len);
126
 
#endif
127
 
            }
128
 
 
129
 
          if (binding->dirname != _nl_default_dirname)
130
 
            free (binding->dirname);
131
 
 
132
 
          binding->dirname = new_dirname;
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;
134
222
    }
135
223
  else
136
224
    {
137
225
      /* We have to create a new binding.  */
138
 
#if !defined _LIBC && !defined HAVE_STRDUP
139
 
      size_t len;
140
 
#endif
 
226
      size_t len = strlen (domainname) + 1;
141
227
      struct binding *new_binding =
142
 
        (struct binding *) malloc (sizeof (*new_binding));
143
 
 
144
 
      if (new_binding == NULL)
145
 
        return NULL;
146
 
 
147
 
#if defined _LIBC || defined HAVE_STRDUP
148
 
      new_binding->domainname = strdup (domainname);
149
 
      if (new_binding->domainname == NULL)
150
 
        return NULL;
151
 
#else
152
 
      len = strlen (domainname) + 1;
153
 
      new_binding->domainname = (char *) malloc (len);
154
 
      if (new_binding->domainname == NULL)
155
 
        return NULL;
 
228
        (struct binding *) malloc (offsetof (struct binding, domainname) + len);
 
229
 
 
230
      if (__builtin_expect (new_binding == NULL, 0))
 
231
        goto failed;
 
232
 
156
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);
157
259
#endif
158
 
 
159
 
      if (strcmp (dirname, _nl_default_dirname) == 0)
 
260
                  dirname = result;
 
261
                }
 
262
            }
 
263
          *dirnamep = dirname;
 
264
          new_binding->dirname = (char *) dirname;
 
265
        }
 
266
      else
 
267
        /* The default value.  */
160
268
        new_binding->dirname = (char *) _nl_default_dirname;
161
 
      else
 
269
 
 
270
      new_binding->codeset_cntr = 0;
 
271
 
 
272
      if (codesetp)
162
273
        {
 
274
          const char *codeset = *codesetp;
 
275
 
 
276
          if (codeset != NULL)
 
277
            {
 
278
              char *result;
 
279
 
163
280
#if defined _LIBC || defined HAVE_STRDUP
164
 
          new_binding->dirname = strdup (dirname);
165
 
          if (new_binding->dirname == NULL)
166
 
            return NULL;
 
281
              result = strdup (codeset);
 
282
              if (__builtin_expect (result == NULL, 0))
 
283
                goto failed_codeset;
167
284
#else
168
 
          len = strlen (dirname) + 1;
169
 
          new_binding->dirname = (char *) malloc (len);
170
 
          if (new_binding->dirname == NULL)
171
 
            return NULL;
172
 
          memcpy (new_binding->dirname, dirname, len);
 
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);
173
290
#endif
 
291
              codeset = result;
 
292
              new_binding->codeset_cntr++;
 
293
            }
 
294
          *codesetp = codeset;
 
295
          new_binding->codeset = (char *) codeset;
174
296
        }
 
297
      else
 
298
        new_binding->codeset = NULL;
175
299
 
176
300
      /* Now enqueue it.  */
177
301
      if (_nl_domain_bindings == NULL
191
315
          binding->next = new_binding;
192
316
        }
193
317
 
194
 
      binding = new_binding;
 
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
        }
195
334
    }
196
335
 
197
 
  return binding->dirname;
 
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;
198
363
}
199
364
 
200
365
#ifdef _LIBC
201
 
/* Alias for function name in GNU C Library.  */
 
366
/* Aliases for function names in GNU C Library.  */
202
367
weak_alias (__bindtextdomain, bindtextdomain);
 
368
weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
203
369
#endif