~vcs-imports/tuxtype/trunk

« back to all changes in this revision

Viewing changes to intl/dcigettext.c

  • Committer: dbruce-guest
  • Date: 2008-11-24 13:42:10 UTC
  • Revision ID: vcs-imports@canonical.com-20081124134210-owbqr2ral094y8to
Re-ran gettextize to add in-tree libintl (needed for Windows cross-build).
Got crossbuild working again, cleaned up configure.ac and Makefile.am's.
Fixed crashing bug in new word list editing feature that segfaulted if word list not user-writable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Implementation of the internal dcigettext function.
 
2
   Copyright (C) 1995-1999, 2000-2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 
17
   USA.  */
 
18
 
 
19
/* Tell glibc's <string.h> to provide a prototype for mempcpy().
 
20
   This must come before <config.h> because <config.h> may include
 
21
   <features.h>, and once <features.h> has been included, it's too late.  */
 
22
#ifndef _GNU_SOURCE
 
23
# define _GNU_SOURCE    1
 
24
#endif
 
25
 
 
26
#ifdef HAVE_CONFIG_H
 
27
# include <config.h>
 
28
#endif
 
29
 
 
30
/* NL_LOCALE_NAME does not work in glibc-2.4.  Ignore it.  */
 
31
#undef HAVE_NL_LOCALE_NAME
 
32
 
 
33
#include <sys/types.h>
 
34
 
 
35
#ifdef __GNUC__
 
36
# define alloca __builtin_alloca
 
37
# define HAVE_ALLOCA 1
 
38
#else
 
39
# ifdef _MSC_VER
 
40
#  include <malloc.h>
 
41
#  define alloca _alloca
 
42
# else
 
43
#  if defined HAVE_ALLOCA_H || defined _LIBC
 
44
#   include <alloca.h>
 
45
#  else
 
46
#   ifdef _AIX
 
47
 #pragma alloca
 
48
#   else
 
49
#    ifndef alloca
 
50
char *alloca ();
 
51
#    endif
 
52
#   endif
 
53
#  endif
 
54
# endif
 
55
#endif
 
56
 
 
57
#include <errno.h>
 
58
#ifndef errno
 
59
extern int errno;
 
60
#endif
 
61
#ifndef __set_errno
 
62
# define __set_errno(val) errno = (val)
 
63
#endif
 
64
 
 
65
#include <stddef.h>
 
66
#include <stdlib.h>
 
67
#include <string.h>
 
68
 
 
69
#if defined HAVE_UNISTD_H || defined _LIBC
 
70
# include <unistd.h>
 
71
#endif
 
72
 
 
73
#include <locale.h>
 
74
 
 
75
#ifdef _LIBC
 
76
  /* Guess whether integer division by zero raises signal SIGFPE.
 
77
     Set to 1 only if you know for sure.  In case of doubt, set to 0.  */
 
78
# if defined __alpha__ || defined __arm__ || defined __i386__ \
 
79
     || defined __m68k__ || defined __s390__
 
80
#  define INTDIV0_RAISES_SIGFPE 1
 
81
# else
 
82
#  define INTDIV0_RAISES_SIGFPE 0
 
83
# endif
 
84
#endif
 
85
#if !INTDIV0_RAISES_SIGFPE
 
86
# include <signal.h>
 
87
#endif
 
88
 
 
89
#if defined HAVE_SYS_PARAM_H || defined _LIBC
 
90
# include <sys/param.h>
 
91
#endif
 
92
 
 
93
#if !defined _LIBC
 
94
# if HAVE_NL_LOCALE_NAME
 
95
#  include <langinfo.h>
 
96
# endif
 
97
# include "localcharset.h"
 
98
#endif
 
99
 
 
100
#include "gettextP.h"
 
101
#include "plural-exp.h"
 
102
#ifdef _LIBC
 
103
# include <libintl.h>
 
104
#else
 
105
# ifdef IN_LIBGLOCALE
 
106
#  include <libintl.h>
 
107
# endif
 
108
# include "libgnuintl.h"
 
109
#endif
 
110
#include "hash-string.h"
 
111
 
 
112
/* Handle multi-threaded applications.  */
 
113
#ifdef _LIBC
 
114
# include <bits/libc-lock.h>
 
115
# define gl_rwlock_define_initialized __libc_rwlock_define_initialized
 
116
# define gl_rwlock_rdlock __libc_rwlock_rdlock
 
117
# define gl_rwlock_wrlock __libc_rwlock_wrlock
 
118
# define gl_rwlock_unlock __libc_rwlock_unlock
 
119
#else
 
120
# include "lock.h"
 
121
#endif
 
122
 
 
123
/* Alignment of types.  */
 
124
#if defined __GNUC__ && __GNUC__ >= 2
 
125
# define alignof(TYPE) __alignof__ (TYPE)
 
126
#else
 
127
# define alignof(TYPE) \
 
128
    ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
 
129
#endif
 
130
 
 
131
/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
 
132
#ifndef offsetof
 
133
# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
 
134
#endif
 
135
 
 
136
/* @@ end of prolog @@ */
 
137
 
 
138
#ifdef _LIBC
 
139
/* Rename the non ANSI C functions.  This is required by the standard
 
140
   because some ANSI C functions will require linking with this object
 
141
   file and the name space must not be polluted.  */
 
142
# define getcwd __getcwd
 
143
# ifndef stpcpy
 
144
#  define stpcpy __stpcpy
 
145
# endif
 
146
# define tfind __tfind
 
147
#else
 
148
# if !defined HAVE_GETCWD
 
149
char *getwd ();
 
150
#  define getcwd(buf, max) getwd (buf)
 
151
# else
 
152
#  if VMS
 
153
#   define getcwd(buf, max) (getcwd) (buf, max, 0)
 
154
#  else
 
155
char *getcwd ();
 
156
#  endif
 
157
# endif
 
158
# ifndef HAVE_STPCPY
 
159
static char *stpcpy (char *dest, const char *src);
 
160
# endif
 
161
# ifndef HAVE_MEMPCPY
 
162
static void *mempcpy (void *dest, const void *src, size_t n);
 
163
# endif
 
164
#endif
 
165
 
 
166
/* Use a replacement if the system does not provide the `tsearch' function
 
167
   family.  */
 
168
#if HAVE_TSEARCH || defined _LIBC
 
169
# include <search.h>
 
170
#else
 
171
# define tsearch libintl_tsearch
 
172
# define tfind libintl_tfind
 
173
# define tdelete libintl_tdelete
 
174
# define twalk libintl_twalk
 
175
# include "tsearch.h"
 
176
#endif
 
177
 
 
178
#ifdef _LIBC
 
179
# define tsearch __tsearch
 
180
#endif
 
181
 
 
182
/* Amount to increase buffer size by in each try.  */
 
183
#define PATH_INCR 32
 
184
 
 
185
/* The following is from pathmax.h.  */
 
186
/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
 
187
   PATH_MAX but might cause redefinition warnings when sys/param.h is
 
188
   later included (as on MORE/BSD 4.3).  */
 
189
#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
 
190
# include <limits.h>
 
191
#endif
 
192
 
 
193
#ifndef _POSIX_PATH_MAX
 
194
# define _POSIX_PATH_MAX 255
 
195
#endif
 
196
 
 
197
#if !defined PATH_MAX && defined _PC_PATH_MAX
 
198
# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
 
199
#endif
 
200
 
 
201
/* Don't include sys/param.h if it already has been.  */
 
202
#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
 
203
# include <sys/param.h>
 
204
#endif
 
205
 
 
206
#if !defined PATH_MAX && defined MAXPATHLEN
 
207
# define PATH_MAX MAXPATHLEN
 
208
#endif
 
209
 
 
210
#ifndef PATH_MAX
 
211
# define PATH_MAX _POSIX_PATH_MAX
 
212
#endif
 
213
 
 
214
/* Pathname support.
 
215
   ISSLASH(C)           tests whether C is a directory separator character.
 
216
   IS_ABSOLUTE_PATH(P)  tests whether P is an absolute path.  If it is not,
 
217
                        it may be concatenated to a directory pathname.
 
218
   IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
 
219
 */
 
220
#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
 
221
  /* Win32, Cygwin, OS/2, DOS */
 
222
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
 
223
# define HAS_DEVICE(P) \
 
224
    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
 
225
     && (P)[1] == ':')
 
226
# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
 
227
# define IS_PATH_WITH_DIR(P) \
 
228
    (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
 
229
#else
 
230
  /* Unix */
 
231
# define ISSLASH(C) ((C) == '/')
 
232
# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
 
233
# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
 
234
#endif
 
235
 
 
236
/* Whether to support different locales in different threads.  */
 
237
#if defined _LIBC || HAVE_NL_LOCALE_NAME || (HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS) || defined IN_LIBGLOCALE
 
238
# define HAVE_PER_THREAD_LOCALE
 
239
#endif
 
240
 
 
241
/* This is the type used for the search tree where known translations
 
242
   are stored.  */
 
243
struct known_translation_t
 
244
{
 
245
  /* Domain in which to search.  */
 
246
  const char *domainname;
 
247
 
 
248
  /* The category.  */
 
249
  int category;
 
250
 
 
251
#ifdef HAVE_PER_THREAD_LOCALE
 
252
  /* Name of the relevant locale category, or "" for the global locale.  */
 
253
  const char *localename;
 
254
#endif
 
255
 
 
256
#ifdef IN_LIBGLOCALE
 
257
  /* The character encoding.  */
 
258
  const char *encoding;
 
259
#endif
 
260
 
 
261
  /* State of the catalog counter at the point the string was found.  */
 
262
  int counter;
 
263
 
 
264
  /* Catalog where the string was found.  */
 
265
  struct loaded_l10nfile *domain;
 
266
 
 
267
  /* And finally the translation.  */
 
268
  const char *translation;
 
269
  size_t translation_length;
 
270
 
 
271
  /* Pointer to the string in question.  */
 
272
  char msgid[ZERO];
 
273
};
 
274
 
 
275
gl_rwlock_define_initialized (static, tree_lock)
 
276
 
 
277
/* Root of the search tree with known translations.  */
 
278
static void *root;
 
279
 
 
280
/* Function to compare two entries in the table of known translations.  */
 
281
static int
 
282
transcmp (const void *p1, const void *p2)
 
283
{
 
284
  const struct known_translation_t *s1;
 
285
  const struct known_translation_t *s2;
 
286
  int result;
 
287
 
 
288
  s1 = (const struct known_translation_t *) p1;
 
289
  s2 = (const struct known_translation_t *) p2;
 
290
 
 
291
  result = strcmp (s1->msgid, s2->msgid);
 
292
  if (result == 0)
 
293
    {
 
294
      result = strcmp (s1->domainname, s2->domainname);
 
295
      if (result == 0)
 
296
        {
 
297
#ifdef HAVE_PER_THREAD_LOCALE
 
298
          result = strcmp (s1->localename, s2->localename);
 
299
          if (result == 0)
 
300
#endif
 
301
            {
 
302
#ifdef IN_LIBGLOCALE
 
303
              result = strcmp (s1->encoding, s2->encoding);
 
304
              if (result == 0)
 
305
#endif
 
306
                /* We compare the category last (though this is the cheapest
 
307
                   operation) since it is hopefully always the same (namely
 
308
                   LC_MESSAGES).  */
 
309
                result = s1->category - s2->category;
 
310
            }
 
311
        }
 
312
    }
 
313
 
 
314
  return result;
 
315
}
 
316
 
 
317
/* Name of the default domain used for gettext(3) prior any call to
 
318
   textdomain(3).  The default value for this is "messages".  */
 
319
const char _nl_default_default_domain[] attribute_hidden = "messages";
 
320
 
 
321
#ifndef IN_LIBGLOCALE
 
322
/* Value used as the default domain for gettext(3).  */
 
323
const char *_nl_current_default_domain attribute_hidden
 
324
     = _nl_default_default_domain;
 
325
#endif
 
326
 
 
327
/* Contains the default location of the message catalogs.  */
 
328
#if defined __EMX__
 
329
extern const char _nl_default_dirname[];
 
330
#else
 
331
# ifdef _LIBC
 
332
extern const char _nl_default_dirname[];
 
333
libc_hidden_proto (_nl_default_dirname)
 
334
# endif
 
335
const char _nl_default_dirname[] = LOCALEDIR;
 
336
# ifdef _LIBC
 
337
libc_hidden_data_def (_nl_default_dirname)
 
338
# endif
 
339
#endif
 
340
 
 
341
#ifndef IN_LIBGLOCALE
 
342
/* List with bindings of specific domains created by bindtextdomain()
 
343
   calls.  */
 
344
struct binding *_nl_domain_bindings;
 
345
#endif
 
346
 
 
347
/* Prototypes for local functions.  */
 
348
static char *plural_lookup (struct loaded_l10nfile *domain,
 
349
                            unsigned long int n,
 
350
                            const char *translation, size_t translation_len)
 
351
     internal_function;
 
352
 
 
353
#ifdef IN_LIBGLOCALE
 
354
static const char *guess_category_value (int category,
 
355
                                         const char *categoryname,
 
356
                                         const char *localename)
 
357
     internal_function;
 
358
#else
 
359
static const char *guess_category_value (int category,
 
360
                                         const char *categoryname)
 
361
     internal_function;
 
362
#endif
 
363
 
 
364
#ifdef _LIBC
 
365
# include "../locale/localeinfo.h"
 
366
# define category_to_name(category) \
 
367
  _nl_category_names.str + _nl_category_name_idxs[category]
 
368
#else
 
369
static const char *category_to_name (int category) internal_function;
 
370
#endif
 
371
#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
 
372
static const char *get_output_charset (struct binding *domainbinding)
 
373
     internal_function;
 
374
#endif
 
375
 
 
376
 
 
377
/* For those loosing systems which don't have `alloca' we have to add
 
378
   some additional code emulating it.  */
 
379
#ifdef HAVE_ALLOCA
 
380
/* Nothing has to be done.  */
 
381
# define freea(p) /* nothing */
 
382
# define ADD_BLOCK(list, address) /* nothing */
 
383
# define FREE_BLOCKS(list) /* nothing */
 
384
#else
 
385
struct block_list
 
386
{
 
387
  void *address;
 
388
  struct block_list *next;
 
389
};
 
390
# define ADD_BLOCK(list, addr)                                                \
 
391
  do {                                                                        \
 
392
    struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
 
393
    /* If we cannot get a free block we cannot add the new element to         \
 
394
       the list.  */                                                          \
 
395
    if (newp != NULL) {                                                       \
 
396
      newp->address = (addr);                                                 \
 
397
      newp->next = (list);                                                    \
 
398
      (list) = newp;                                                          \
 
399
    }                                                                         \
 
400
  } while (0)
 
401
# define FREE_BLOCKS(list)                                                    \
 
402
  do {                                                                        \
 
403
    while (list != NULL) {                                                    \
 
404
      struct block_list *old = list;                                          \
 
405
      list = list->next;                                                      \
 
406
      free (old->address);                                                    \
 
407
      free (old);                                                             \
 
408
    }                                                                         \
 
409
  } while (0)
 
410
# undef alloca
 
411
# define alloca(size) (malloc (size))
 
412
# define freea(p) free (p)
 
413
#endif  /* have alloca */
 
414
 
 
415
 
 
416
#ifdef _LIBC
 
417
/* List of blocks allocated for translations.  */
 
418
typedef struct transmem_list
 
419
{
 
420
  struct transmem_list *next;
 
421
  char data[ZERO];
 
422
} transmem_block_t;
 
423
static struct transmem_list *transmem_list;
 
424
#else
 
425
typedef unsigned char transmem_block_t;
 
426
#endif
 
427
 
 
428
 
 
429
/* Names for the libintl functions are a problem.  They must not clash
 
430
   with existing names and they should follow ANSI C.  But this source
 
431
   code is also used in GNU C Library where the names have a __
 
432
   prefix.  So we have to make a difference here.  */
 
433
#ifdef _LIBC
 
434
# define DCIGETTEXT __dcigettext
 
435
#else
 
436
# define DCIGETTEXT libintl_dcigettext
 
437
#endif
 
438
 
 
439
/* Lock variable to protect the global data in the gettext implementation.  */
 
440
gl_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
 
441
 
 
442
/* Checking whether the binaries runs SUID must be done and glibc provides
 
443
   easier methods therefore we make a difference here.  */
 
444
#ifdef _LIBC
 
445
# define ENABLE_SECURE __libc_enable_secure
 
446
# define DETERMINE_SECURE
 
447
#else
 
448
# ifndef HAVE_GETUID
 
449
#  define getuid() 0
 
450
# endif
 
451
# ifndef HAVE_GETGID
 
452
#  define getgid() 0
 
453
# endif
 
454
# ifndef HAVE_GETEUID
 
455
#  define geteuid() getuid()
 
456
# endif
 
457
# ifndef HAVE_GETEGID
 
458
#  define getegid() getgid()
 
459
# endif
 
460
static int enable_secure;
 
461
# define ENABLE_SECURE (enable_secure == 1)
 
462
# define DETERMINE_SECURE \
 
463
  if (enable_secure == 0)                                                     \
 
464
    {                                                                         \
 
465
      if (getuid () != geteuid () || getgid () != getegid ())                 \
 
466
        enable_secure = 1;                                                    \
 
467
      else                                                                    \
 
468
        enable_secure = -1;                                                   \
 
469
    }
 
470
#endif
 
471
 
 
472
/* Get the function to evaluate the plural expression.  */
 
473
#include "eval-plural.h"
 
474
 
 
475
/* Look up MSGID in the DOMAINNAME message catalog for the current
 
476
   CATEGORY locale and, if PLURAL is nonzero, search over string
 
477
   depending on the plural form determined by N.  */
 
478
#ifdef IN_LIBGLOCALE
 
479
char *
 
480
gl_dcigettext (const char *domainname,
 
481
               const char *msgid1, const char *msgid2,
 
482
               int plural, unsigned long int n,
 
483
               int category,
 
484
               const char *localename, const char *encoding)
 
485
#else
 
486
char *
 
487
DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
 
488
            int plural, unsigned long int n, int category)
 
489
#endif
 
490
{
 
491
#ifndef HAVE_ALLOCA
 
492
  struct block_list *block_list = NULL;
 
493
#endif
 
494
  struct loaded_l10nfile *domain;
 
495
  struct binding *binding;
 
496
  const char *categoryname;
 
497
  const char *categoryvalue;
 
498
  const char *dirname;
 
499
  char *xdomainname;
 
500
  char *single_locale;
 
501
  char *retval;
 
502
  size_t retlen;
 
503
  int saved_errno;
 
504
  struct known_translation_t *search;
 
505
  struct known_translation_t **foundp = NULL;
 
506
  size_t msgid_len;
 
507
#if defined HAVE_PER_THREAD_LOCALE && !defined IN_LIBGLOCALE
 
508
  const char *localename;
 
509
#endif
 
510
  size_t domainname_len;
 
511
 
 
512
  /* If no real MSGID is given return NULL.  */
 
513
  if (msgid1 == NULL)
 
514
    return NULL;
 
515
 
 
516
#ifdef _LIBC
 
517
  if (category < 0 || category >= __LC_LAST || category == LC_ALL)
 
518
    /* Bogus.  */
 
519
    return (plural == 0
 
520
            ? (char *) msgid1
 
521
            /* Use the Germanic plural rule.  */
 
522
            : n == 1 ? (char *) msgid1 : (char *) msgid2);
 
523
#endif
 
524
 
 
525
  /* Preserve the `errno' value.  */
 
526
  saved_errno = errno;
 
527
 
 
528
  gl_rwlock_rdlock (_nl_state_lock);
 
529
 
 
530
  /* If DOMAINNAME is NULL, we are interested in the default domain.  If
 
531
     CATEGORY is not LC_MESSAGES this might not make much sense but the
 
532
     definition left this undefined.  */
 
533
  if (domainname == NULL)
 
534
    domainname = _nl_current_default_domain;
 
535
 
 
536
  /* OS/2 specific: backward compatibility with older libintl versions  */
 
537
#ifdef LC_MESSAGES_COMPAT
 
538
  if (category == LC_MESSAGES_COMPAT)
 
539
    category = LC_MESSAGES;
 
540
#endif
 
541
 
 
542
  msgid_len = strlen (msgid1) + 1;
 
543
 
 
544
  /* Try to find the translation among those which we found at
 
545
     some time.  */
 
546
  search = (struct known_translation_t *)
 
547
           alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
 
548
  memcpy (search->msgid, msgid1, msgid_len);
 
549
  search->domainname = domainname;
 
550
  search->category = category;
 
551
#ifdef HAVE_PER_THREAD_LOCALE
 
552
# ifndef IN_LIBGLOCALE
 
553
#  ifdef _LIBC
 
554
  localename = __current_locale_name (category);
 
555
#  else
 
556
#   if HAVE_NL_LOCALE_NAME
 
557
  /* NL_LOCALE_NAME is public glibc API introduced in glibc-2.4.  */
 
558
  localename = nl_langinfo (NL_LOCALE_NAME (category));
 
559
#   else
 
560
#    if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS
 
561
  /* The __names field is not public glibc API and must therefore not be used
 
562
     in code that is installed in public locations.  */
 
563
  {
 
564
    locale_t thread_locale = uselocale (NULL);
 
565
    if (thread_locale != LC_GLOBAL_LOCALE)
 
566
      localename = thread_locale->__names[category];
 
567
    else
 
568
      localename = "";
 
569
  }
 
570
#    endif
 
571
#   endif
 
572
#  endif
 
573
# endif
 
574
  search->localename = localename;
 
575
# ifdef IN_LIBGLOCALE
 
576
  search->encoding = encoding;
 
577
# endif
 
578
 
 
579
  /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
 
580
     tsearch calls can be fatal.  */
 
581
  gl_rwlock_rdlock (tree_lock);
 
582
 
 
583
  foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
 
584
 
 
585
  gl_rwlock_unlock (tree_lock);
 
586
 
 
587
  freea (search);
 
588
  if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
 
589
    {
 
590
      /* Now deal with plural.  */
 
591
      if (plural)
 
592
        retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
 
593
                                (*foundp)->translation_length);
 
594
      else
 
595
        retval = (char *) (*foundp)->translation;
 
596
 
 
597
      gl_rwlock_unlock (_nl_state_lock);
 
598
      __set_errno (saved_errno);
 
599
      return retval;
 
600
    }
 
601
#endif
 
602
 
 
603
  /* See whether this is a SUID binary or not.  */
 
604
  DETERMINE_SECURE;
 
605
 
 
606
  /* First find matching binding.  */
 
607
#ifdef IN_LIBGLOCALE
 
608
  /* We can use a trivial binding, since _nl_find_msg will ignore it anyway,
 
609
     and _nl_load_domain and _nl_find_domain just pass it through.  */
 
610
  binding = NULL;
 
611
  dirname = bindtextdomain (domainname, NULL);
 
612
#else
 
613
  for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
 
614
    {
 
615
      int compare = strcmp (domainname, binding->domainname);
 
616
      if (compare == 0)
 
617
        /* We found it!  */
 
618
        break;
 
619
      if (compare < 0)
 
620
        {
 
621
          /* It is not in the list.  */
 
622
          binding = NULL;
 
623
          break;
 
624
        }
 
625
    }
 
626
 
 
627
  if (binding == NULL)
 
628
    dirname = _nl_default_dirname;
 
629
  else
 
630
    {
 
631
      dirname = binding->dirname;
 
632
#endif
 
633
      if (!IS_ABSOLUTE_PATH (dirname))
 
634
        {
 
635
          /* We have a relative path.  Make it absolute now.  */
 
636
          size_t dirname_len = strlen (dirname) + 1;
 
637
          size_t path_max;
 
638
          char *resolved_dirname;
 
639
          char *ret;
 
640
 
 
641
          path_max = (unsigned int) PATH_MAX;
 
642
          path_max += 2;                /* The getcwd docs say to do this.  */
 
643
 
 
644
          for (;;)
 
645
            {
 
646
              resolved_dirname = (char *) alloca (path_max + dirname_len);
 
647
              ADD_BLOCK (block_list, tmp_dirname);
 
648
 
 
649
              __set_errno (0);
 
650
              ret = getcwd (resolved_dirname, path_max);
 
651
              if (ret != NULL || errno != ERANGE)
 
652
                break;
 
653
 
 
654
              path_max += path_max / 2;
 
655
              path_max += PATH_INCR;
 
656
            }
 
657
 
 
658
          if (ret == NULL)
 
659
            /* We cannot get the current working directory.  Don't signal an
 
660
               error but simply return the default string.  */
 
661
            goto return_untranslated;
 
662
 
 
663
          stpcpy (stpcpy (strchr (resolved_dirname, '\0'), "/"), dirname);
 
664
          dirname = resolved_dirname;
 
665
        }
 
666
#ifndef IN_LIBGLOCALE
 
667
    }
 
668
#endif
 
669
 
 
670
  /* Now determine the symbolic name of CATEGORY and its value.  */
 
671
  categoryname = category_to_name (category);
 
672
#ifdef IN_LIBGLOCALE
 
673
  categoryvalue = guess_category_value (category, categoryname, localename);
 
674
#else
 
675
  categoryvalue = guess_category_value (category, categoryname);
 
676
#endif
 
677
 
 
678
  domainname_len = strlen (domainname);
 
679
  xdomainname = (char *) alloca (strlen (categoryname)
 
680
                                 + domainname_len + 5);
 
681
  ADD_BLOCK (block_list, xdomainname);
 
682
 
 
683
  stpcpy ((char *) mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
 
684
                            domainname, domainname_len),
 
685
          ".mo");
 
686
 
 
687
  /* Creating working area.  */
 
688
  single_locale = (char *) alloca (strlen (categoryvalue) + 1);
 
689
  ADD_BLOCK (block_list, single_locale);
 
690
 
 
691
 
 
692
  /* Search for the given string.  This is a loop because we perhaps
 
693
     got an ordered list of languages to consider for the translation.  */
 
694
  while (1)
 
695
    {
 
696
      /* Make CATEGORYVALUE point to the next element of the list.  */
 
697
      while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
 
698
        ++categoryvalue;
 
699
      if (categoryvalue[0] == '\0')
 
700
        {
 
701
          /* The whole contents of CATEGORYVALUE has been searched but
 
702
             no valid entry has been found.  We solve this situation
 
703
             by implicitly appending a "C" entry, i.e. no translation
 
704
             will take place.  */
 
705
          single_locale[0] = 'C';
 
706
          single_locale[1] = '\0';
 
707
        }
 
708
      else
 
709
        {
 
710
          char *cp = single_locale;
 
711
          while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
 
712
            *cp++ = *categoryvalue++;
 
713
          *cp = '\0';
 
714
 
 
715
          /* When this is a SUID binary we must not allow accessing files
 
716
             outside the dedicated directories.  */
 
717
          if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale))
 
718
            /* Ingore this entry.  */
 
719
            continue;
 
720
        }
 
721
 
 
722
      /* If the current locale value is C (or POSIX) we don't load a
 
723
         domain.  Return the MSGID.  */
 
724
      if (strcmp (single_locale, "C") == 0
 
725
          || strcmp (single_locale, "POSIX") == 0)
 
726
        break;
 
727
 
 
728
      /* Find structure describing the message catalog matching the
 
729
         DOMAINNAME and CATEGORY.  */
 
730
      domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
 
731
 
 
732
      if (domain != NULL)
 
733
        {
 
734
#if defined IN_LIBGLOCALE
 
735
          retval = _nl_find_msg (domain, binding, encoding, msgid1, &retlen);
 
736
#else
 
737
          retval = _nl_find_msg (domain, binding, msgid1, 1, &retlen);
 
738
#endif
 
739
 
 
740
          if (retval == NULL)
 
741
            {
 
742
              int cnt;
 
743
 
 
744
              for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
 
745
                {
 
746
#if defined IN_LIBGLOCALE
 
747
                  retval = _nl_find_msg (domain->successor[cnt], binding,
 
748
                                         encoding, msgid1, &retlen);
 
749
#else
 
750
                  retval = _nl_find_msg (domain->successor[cnt], binding,
 
751
                                         msgid1, 1, &retlen);
 
752
#endif
 
753
 
 
754
                  if (retval != NULL)
 
755
                    {
 
756
                      domain = domain->successor[cnt];
 
757
                      break;
 
758
                    }
 
759
                }
 
760
            }
 
761
 
 
762
          /* Returning -1 means that some resource problem exists
 
763
             (likely memory) and that the strings could not be
 
764
             converted.  Return the original strings.  */
 
765
          if (__builtin_expect (retval == (char *) -1, 0))
 
766
            break;
 
767
 
 
768
          if (retval != NULL)
 
769
            {
 
770
              /* Found the translation of MSGID1 in domain DOMAIN:
 
771
                 starting at RETVAL, RETLEN bytes.  */
 
772
              FREE_BLOCKS (block_list);
 
773
              if (foundp == NULL)
 
774
                {
 
775
                  /* Create a new entry and add it to the search tree.  */
 
776
                  size_t size;
 
777
                  struct known_translation_t *newp;
 
778
 
 
779
                  size = offsetof (struct known_translation_t, msgid)
 
780
                         + msgid_len + domainname_len + 1;
 
781
#ifdef HAVE_PER_THREAD_LOCALE
 
782
                  size += strlen (localename) + 1;
 
783
#endif
 
784
                  newp = (struct known_translation_t *) malloc (size);
 
785
                  if (newp != NULL)
 
786
                    {
 
787
                      char *new_domainname;
 
788
#ifdef HAVE_PER_THREAD_LOCALE
 
789
                      char *new_localename;
 
790
#endif
 
791
 
 
792
                      new_domainname =
 
793
                        (char *) mempcpy (newp->msgid, msgid1, msgid_len);
 
794
                      memcpy (new_domainname, domainname, domainname_len + 1);
 
795
#ifdef HAVE_PER_THREAD_LOCALE
 
796
                      new_localename = new_domainname + domainname_len + 1;
 
797
                      strcpy (new_localename, localename);
 
798
#endif
 
799
                      newp->domainname = new_domainname;
 
800
                      newp->category = category;
 
801
#ifdef HAVE_PER_THREAD_LOCALE
 
802
                      newp->localename = new_localename;
 
803
#endif
 
804
#ifdef IN_LIBGLOCALE
 
805
                      newp->encoding = encoding;
 
806
#endif
 
807
                      newp->counter = _nl_msg_cat_cntr;
 
808
                      newp->domain = domain;
 
809
                      newp->translation = retval;
 
810
                      newp->translation_length = retlen;
 
811
 
 
812
                      gl_rwlock_wrlock (tree_lock);
 
813
 
 
814
                      /* Insert the entry in the search tree.  */
 
815
                      foundp = (struct known_translation_t **)
 
816
                        tsearch (newp, &root, transcmp);
 
817
 
 
818
                      gl_rwlock_unlock (tree_lock);
 
819
 
 
820
                      if (foundp == NULL
 
821
                          || __builtin_expect (*foundp != newp, 0))
 
822
                        /* The insert failed.  */
 
823
                        free (newp);
 
824
                    }
 
825
                }
 
826
              else
 
827
                {
 
828
                  /* We can update the existing entry.  */
 
829
                  (*foundp)->counter = _nl_msg_cat_cntr;
 
830
                  (*foundp)->domain = domain;
 
831
                  (*foundp)->translation = retval;
 
832
                  (*foundp)->translation_length = retlen;
 
833
                }
 
834
 
 
835
              __set_errno (saved_errno);
 
836
 
 
837
              /* Now deal with plural.  */
 
838
              if (plural)
 
839
                retval = plural_lookup (domain, n, retval, retlen);
 
840
 
 
841
              gl_rwlock_unlock (_nl_state_lock);
 
842
              return retval;
 
843
            }
 
844
        }
 
845
    }
 
846
 
 
847
 return_untranslated:
 
848
  /* Return the untranslated MSGID.  */
 
849
  FREE_BLOCKS (block_list);
 
850
  gl_rwlock_unlock (_nl_state_lock);
 
851
#ifndef _LIBC
 
852
  if (!ENABLE_SECURE)
 
853
    {
 
854
      extern void _nl_log_untranslated (const char *logfilename,
 
855
                                        const char *domainname,
 
856
                                        const char *msgid1, const char *msgid2,
 
857
                                        int plural);
 
858
      const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED");
 
859
 
 
860
      if (logfilename != NULL && logfilename[0] != '\0')
 
861
        _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
 
862
    }
 
863
#endif
 
864
  __set_errno (saved_errno);
 
865
  return (plural == 0
 
866
          ? (char *) msgid1
 
867
          /* Use the Germanic plural rule.  */
 
868
          : n == 1 ? (char *) msgid1 : (char *) msgid2);
 
869
}
 
870
 
 
871
 
 
872
/* Look up the translation of msgid within DOMAIN_FILE and DOMAINBINDING.
 
873
   Return it if found.  Return NULL if not found or in case of a conversion
 
874
   failure (problem in the particular message catalog).  Return (char *) -1
 
875
   in case of a memory allocation failure during conversion (only if
 
876
   ENCODING != NULL resp. CONVERT == true).  */
 
877
char *
 
878
internal_function
 
879
#ifdef IN_LIBGLOCALE
 
880
_nl_find_msg (struct loaded_l10nfile *domain_file,
 
881
              struct binding *domainbinding, const char *encoding,
 
882
              const char *msgid,
 
883
              size_t *lengthp)
 
884
#else
 
885
_nl_find_msg (struct loaded_l10nfile *domain_file,
 
886
              struct binding *domainbinding,
 
887
              const char *msgid, int convert,
 
888
              size_t *lengthp)
 
889
#endif
 
890
{
 
891
  struct loaded_domain *domain;
 
892
  nls_uint32 nstrings;
 
893
  size_t act;
 
894
  char *result;
 
895
  size_t resultlen;
 
896
 
 
897
  if (domain_file->decided <= 0)
 
898
    _nl_load_domain (domain_file, domainbinding);
 
899
 
 
900
  if (domain_file->data == NULL)
 
901
    return NULL;
 
902
 
 
903
  domain = (struct loaded_domain *) domain_file->data;
 
904
 
 
905
  nstrings = domain->nstrings;
 
906
 
 
907
  /* Locate the MSGID and its translation.  */
 
908
  if (domain->hash_tab != NULL)
 
909
    {
 
910
      /* Use the hashing table.  */
 
911
      nls_uint32 len = strlen (msgid);
 
912
      nls_uint32 hash_val = __hash_string (msgid);
 
913
      nls_uint32 idx = hash_val % domain->hash_size;
 
914
      nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
 
915
 
 
916
      while (1)
 
917
        {
 
918
          nls_uint32 nstr =
 
919
            W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
 
920
 
 
921
          if (nstr == 0)
 
922
            /* Hash table entry is empty.  */
 
923
            return NULL;
 
924
 
 
925
          nstr--;
 
926
 
 
927
          /* Compare msgid with the original string at index nstr.
 
928
             We compare the lengths with >=, not ==, because plural entries
 
929
             are represented by strings with an embedded NUL.  */
 
930
          if (nstr < nstrings
 
931
              ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
 
932
                && (strcmp (msgid,
 
933
                            domain->data + W (domain->must_swap,
 
934
                                              domain->orig_tab[nstr].offset))
 
935
                    == 0)
 
936
              : domain->orig_sysdep_tab[nstr - nstrings].length > len
 
937
                && (strcmp (msgid,
 
938
                            domain->orig_sysdep_tab[nstr - nstrings].pointer)
 
939
                    == 0))
 
940
            {
 
941
              act = nstr;
 
942
              goto found;
 
943
            }
 
944
 
 
945
          if (idx >= domain->hash_size - incr)
 
946
            idx -= domain->hash_size - incr;
 
947
          else
 
948
            idx += incr;
 
949
        }
 
950
      /* NOTREACHED */
 
951
    }
 
952
  else
 
953
    {
 
954
      /* Try the default method:  binary search in the sorted array of
 
955
         messages.  */
 
956
      size_t top, bottom;
 
957
 
 
958
      bottom = 0;
 
959
      top = nstrings;
 
960
      while (bottom < top)
 
961
        {
 
962
          int cmp_val;
 
963
 
 
964
          act = (bottom + top) / 2;
 
965
          cmp_val = strcmp (msgid, (domain->data
 
966
                                    + W (domain->must_swap,
 
967
                                         domain->orig_tab[act].offset)));
 
968
          if (cmp_val < 0)
 
969
            top = act;
 
970
          else if (cmp_val > 0)
 
971
            bottom = act + 1;
 
972
          else
 
973
            goto found;
 
974
        }
 
975
      /* No translation was found.  */
 
976
      return NULL;
 
977
    }
 
978
 
 
979
 found:
 
980
  /* The translation was found at index ACT.  If we have to convert the
 
981
     string to use a different character set, this is the time.  */
 
982
  if (act < nstrings)
 
983
    {
 
984
      result = (char *)
 
985
        (domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
 
986
      resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
 
987
    }
 
988
  else
 
989
    {
 
990
      result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
 
991
      resultlen = domain->trans_sysdep_tab[act - nstrings].length;
 
992
    }
 
993
 
 
994
#if defined _LIBC || HAVE_ICONV
 
995
# ifdef IN_LIBGLOCALE
 
996
  if (encoding != NULL)
 
997
# else
 
998
  if (convert)
 
999
# endif
 
1000
    {
 
1001
      /* We are supposed to do a conversion.  */
 
1002
# ifndef IN_LIBGLOCALE
 
1003
      const char *encoding = get_output_charset (domainbinding);
 
1004
# endif
 
1005
      size_t nconversions;
 
1006
      struct converted_domain *convd;
 
1007
      size_t i;
 
1008
 
 
1009
      /* Protect against reallocation of the table.  */
 
1010
      gl_rwlock_rdlock (domain->conversions_lock);
 
1011
 
 
1012
      /* Search whether a table with converted translations for this
 
1013
         encoding has already been allocated.  */
 
1014
      nconversions = domain->nconversions;
 
1015
      convd = NULL;
 
1016
 
 
1017
      for (i = nconversions; i > 0; )
 
1018
        {
 
1019
          i--;
 
1020
          if (strcmp (domain->conversions[i].encoding, encoding) == 0)
 
1021
            {
 
1022
              convd = &domain->conversions[i];
 
1023
              break;
 
1024
            }
 
1025
        }
 
1026
 
 
1027
      gl_rwlock_unlock (domain->conversions_lock);
 
1028
 
 
1029
      if (convd == NULL)
 
1030
        {
 
1031
          /* We have to allocate a new conversions table.  */
 
1032
          gl_rwlock_wrlock (domain->conversions_lock);
 
1033
 
 
1034
          /* Maybe in the meantime somebody added the translation.
 
1035
             Recheck.  */
 
1036
          for (i = nconversions; i > 0; )
 
1037
            {
 
1038
              i--;
 
1039
              if (strcmp (domain->conversions[i].encoding, encoding) == 0)
 
1040
                {
 
1041
                  convd = &domain->conversions[i];
 
1042
                  goto found_convd;
 
1043
                }
 
1044
            }
 
1045
 
 
1046
          {
 
1047
            /* Allocate a table for the converted translations for this
 
1048
               encoding.  */
 
1049
            struct converted_domain *new_conversions =
 
1050
              (struct converted_domain *)
 
1051
              (domain->conversions != NULL
 
1052
               ? realloc (domain->conversions,
 
1053
                          (nconversions + 1) * sizeof (struct converted_domain))
 
1054
               : malloc ((nconversions + 1) * sizeof (struct converted_domain)));
 
1055
 
 
1056
            if (__builtin_expect (new_conversions == NULL, 0))
 
1057
              {
 
1058
                /* Nothing we can do, no more memory.  We cannot use the
 
1059
                   translation because it might be encoded incorrectly.  */
 
1060
              unlock_fail:
 
1061
                gl_rwlock_unlock (domain->conversions_lock);
 
1062
                return (char *) -1;
 
1063
              }
 
1064
 
 
1065
            domain->conversions = new_conversions;
 
1066
 
 
1067
            /* Copy the 'encoding' string to permanent storage.  */
 
1068
            encoding = strdup (encoding);
 
1069
            if (__builtin_expect (encoding == NULL, 0))
 
1070
              /* Nothing we can do, no more memory.  We cannot use the
 
1071
                 translation because it might be encoded incorrectly.  */
 
1072
              goto unlock_fail;
 
1073
 
 
1074
            convd = &new_conversions[nconversions];
 
1075
            convd->encoding = encoding;
 
1076
 
 
1077
            /* Find out about the character set the file is encoded with.
 
1078
               This can be found (in textual form) in the entry "".  If this
 
1079
               entry does not exist or if this does not contain the 'charset='
 
1080
               information, we will assume the charset matches the one the
 
1081
               current locale and we don't have to perform any conversion.  */
 
1082
# ifdef _LIBC
 
1083
            convd->conv = (__gconv_t) -1;
 
1084
# else
 
1085
#  if HAVE_ICONV
 
1086
            convd->conv = (iconv_t) -1;
 
1087
#  endif
 
1088
# endif
 
1089
            {
 
1090
              char *nullentry;
 
1091
              size_t nullentrylen;
 
1092
 
 
1093
              /* Get the header entry.  This is a recursion, but it doesn't
 
1094
                 reallocate domain->conversions because we pass
 
1095
                 encoding = NULL or convert = 0, respectively.  */
 
1096
              nullentry =
 
1097
# ifdef IN_LIBGLOCALE
 
1098
                _nl_find_msg (domain_file, domainbinding, NULL, "",
 
1099
                              &nullentrylen);
 
1100
# else
 
1101
                _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
 
1102
# endif
 
1103
 
 
1104
              if (nullentry != NULL)
 
1105
                {
 
1106
                  const char *charsetstr;
 
1107
 
 
1108
                  charsetstr = strstr (nullentry, "charset=");
 
1109
                  if (charsetstr != NULL)
 
1110
                    {
 
1111
                      size_t len;
 
1112
                      char *charset;
 
1113
                      const char *outcharset;
 
1114
 
 
1115
                      charsetstr += strlen ("charset=");
 
1116
                      len = strcspn (charsetstr, " \t\n");
 
1117
 
 
1118
                      charset = (char *) alloca (len + 1);
 
1119
# if defined _LIBC || HAVE_MEMPCPY
 
1120
                      *((char *) mempcpy (charset, charsetstr, len)) = '\0';
 
1121
# else
 
1122
                      memcpy (charset, charsetstr, len);
 
1123
                      charset[len] = '\0';
 
1124
# endif
 
1125
 
 
1126
                      outcharset = encoding;
 
1127
 
 
1128
# ifdef _LIBC
 
1129
                      /* We always want to use transliteration.  */
 
1130
                      outcharset = norm_add_slashes (outcharset, "TRANSLIT");
 
1131
                      charset = norm_add_slashes (charset, "");
 
1132
                      int r = __gconv_open (outcharset, charset, &convd->conv,
 
1133
                                            GCONV_AVOID_NOCONV);
 
1134
                      if (__builtin_expect (r != __GCONV_OK, 0))
 
1135
                        {
 
1136
                          /* If the output encoding is the same there is
 
1137
                             nothing to do.  Otherwise do not use the
 
1138
                             translation at all.  */
 
1139
                          if (__builtin_expect (r != __GCONV_NULCONV, 1))
 
1140
                            {
 
1141
                              gl_rwlock_unlock (domain->conversions_lock);
 
1142
                              free ((char *) encoding);
 
1143
                              return NULL;
 
1144
                            }
 
1145
 
 
1146
                          convd->conv = (__gconv_t) -1;
 
1147
                        }
 
1148
# else
 
1149
#  if HAVE_ICONV
 
1150
                      /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
 
1151
                         we want to use transliteration.  */
 
1152
#   if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
 
1153
       || _LIBICONV_VERSION >= 0x0105
 
1154
                      if (strchr (outcharset, '/') == NULL)
 
1155
                        {
 
1156
                          char *tmp;
 
1157
 
 
1158
                          len = strlen (outcharset);
 
1159
                          tmp = (char *) alloca (len + 10 + 1);
 
1160
                          memcpy (tmp, outcharset, len);
 
1161
                          memcpy (tmp + len, "//TRANSLIT", 10 + 1);
 
1162
                          outcharset = tmp;
 
1163
 
 
1164
                          convd->conv = iconv_open (outcharset, charset);
 
1165
 
 
1166
                          freea (outcharset);
 
1167
                        }
 
1168
                      else
 
1169
#   endif
 
1170
                        convd->conv = iconv_open (outcharset, charset);
 
1171
#  endif
 
1172
# endif
 
1173
 
 
1174
                      freea (charset);
 
1175
                    }
 
1176
                }
 
1177
            }
 
1178
            convd->conv_tab = NULL;
 
1179
            /* Here domain->conversions is still == new_conversions.  */
 
1180
            domain->nconversions++;
 
1181
          }
 
1182
 
 
1183
        found_convd:
 
1184
          gl_rwlock_unlock (domain->conversions_lock);
 
1185
        }
 
1186
 
 
1187
      if (
 
1188
# ifdef _LIBC
 
1189
          convd->conv != (__gconv_t) -1
 
1190
# else
 
1191
#  if HAVE_ICONV
 
1192
          convd->conv != (iconv_t) -1
 
1193
#  endif
 
1194
# endif
 
1195
          )
 
1196
        {
 
1197
          /* We are supposed to do a conversion.  First allocate an
 
1198
             appropriate table with the same structure as the table
 
1199
             of translations in the file, where we can put the pointers
 
1200
             to the converted strings in.
 
1201
             There is a slight complication with plural entries.  They
 
1202
             are represented by consecutive NUL terminated strings.  We
 
1203
             handle this case by converting RESULTLEN bytes, including
 
1204
             NULs.  */
 
1205
 
 
1206
          if (convd->conv_tab == NULL
 
1207
              && ((convd->conv_tab =
 
1208
                    (char **) calloc (nstrings + domain->n_sysdep_strings,
 
1209
                                      sizeof (char *)))
 
1210
                  == NULL))
 
1211
            /* Mark that we didn't succeed allocating a table.  */
 
1212
            convd->conv_tab = (char **) -1;
 
1213
 
 
1214
          if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
 
1215
            /* Nothing we can do, no more memory.  We cannot use the
 
1216
               translation because it might be encoded incorrectly.  */
 
1217
            return (char *) -1;
 
1218
 
 
1219
          if (convd->conv_tab[act] == NULL)
 
1220
            {
 
1221
              /* We haven't used this string so far, so it is not
 
1222
                 translated yet.  Do this now.  */
 
1223
              /* We use a bit more efficient memory handling.
 
1224
                 We allocate always larger blocks which get used over
 
1225
                 time.  This is faster than many small allocations.   */
 
1226
              __libc_lock_define_initialized (static, lock)
 
1227
# define INITIAL_BLOCK_SIZE     4080
 
1228
              static unsigned char *freemem;
 
1229
              static size_t freemem_size;
 
1230
 
 
1231
              const unsigned char *inbuf;
 
1232
              unsigned char *outbuf;
 
1233
              int malloc_count;
 
1234
# ifndef _LIBC
 
1235
              transmem_block_t *transmem_list = NULL;
 
1236
# endif
 
1237
 
 
1238
              __libc_lock_lock (lock);
 
1239
 
 
1240
              inbuf = (const unsigned char *) result;
 
1241
              outbuf = freemem + sizeof (size_t);
 
1242
 
 
1243
              malloc_count = 0;
 
1244
              while (1)
 
1245
                {
 
1246
                  transmem_block_t *newmem;
 
1247
# ifdef _LIBC
 
1248
                  size_t non_reversible;
 
1249
                  int res;
 
1250
 
 
1251
                  if (freemem_size < sizeof (size_t))
 
1252
                    goto resize_freemem;
 
1253
 
 
1254
                  res = __gconv (convd->conv,
 
1255
                                 &inbuf, inbuf + resultlen,
 
1256
                                 &outbuf,
 
1257
                                 outbuf + freemem_size - sizeof (size_t),
 
1258
                                 &non_reversible);
 
1259
 
 
1260
                  if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
 
1261
                    break;
 
1262
 
 
1263
                  if (res != __GCONV_FULL_OUTPUT)
 
1264
                    {
 
1265
                      /* We should not use the translation at all, it
 
1266
                         is incorrectly encoded.  */
 
1267
                      __libc_lock_unlock (lock);
 
1268
                      return NULL;
 
1269
                    }
 
1270
 
 
1271
                  inbuf = (const unsigned char *) result;
 
1272
# else
 
1273
#  if HAVE_ICONV
 
1274
                  const char *inptr = (const char *) inbuf;
 
1275
                  size_t inleft = resultlen;
 
1276
                  char *outptr = (char *) outbuf;
 
1277
                  size_t outleft;
 
1278
 
 
1279
                  if (freemem_size < sizeof (size_t))
 
1280
                    goto resize_freemem;
 
1281
 
 
1282
                  outleft = freemem_size - sizeof (size_t);
 
1283
                  if (iconv (convd->conv,
 
1284
                             (ICONV_CONST char **) &inptr, &inleft,
 
1285
                             &outptr, &outleft)
 
1286
                      != (size_t) (-1))
 
1287
                    {
 
1288
                      outbuf = (unsigned char *) outptr;
 
1289
                      break;
 
1290
                    }
 
1291
                  if (errno != E2BIG)
 
1292
                    {
 
1293
                      __libc_lock_unlock (lock);
 
1294
                      return NULL;
 
1295
                    }
 
1296
#  endif
 
1297
# endif
 
1298
 
 
1299
                resize_freemem:
 
1300
                  /* We must allocate a new buffer or resize the old one.  */
 
1301
                  if (malloc_count > 0)
 
1302
                    {
 
1303
                      ++malloc_count;
 
1304
                      freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
 
1305
                      newmem = (transmem_block_t *) realloc (transmem_list,
 
1306
                                                             freemem_size);
 
1307
# ifdef _LIBC
 
1308
                      if (newmem != NULL)
 
1309
                        transmem_list = transmem_list->next;
 
1310
                      else
 
1311
                        {
 
1312
                          struct transmem_list *old = transmem_list;
 
1313
 
 
1314
                          transmem_list = transmem_list->next;
 
1315
                          free (old);
 
1316
                        }
 
1317
# endif
 
1318
                    }
 
1319
                  else
 
1320
                    {
 
1321
                      malloc_count = 1;
 
1322
                      freemem_size = INITIAL_BLOCK_SIZE;
 
1323
                      newmem = (transmem_block_t *) malloc (freemem_size);
 
1324
                    }
 
1325
                  if (__builtin_expect (newmem == NULL, 0))
 
1326
                    {
 
1327
                      freemem = NULL;
 
1328
                      freemem_size = 0;
 
1329
                      __libc_lock_unlock (lock);
 
1330
                      return (char *) -1;
 
1331
                    }
 
1332
 
 
1333
# ifdef _LIBC
 
1334
                  /* Add the block to the list of blocks we have to free
 
1335
                     at some point.  */
 
1336
                  newmem->next = transmem_list;
 
1337
                  transmem_list = newmem;
 
1338
 
 
1339
                  freemem = (unsigned char *) newmem->data;
 
1340
                  freemem_size -= offsetof (struct transmem_list, data);
 
1341
# else
 
1342
                  transmem_list = newmem;
 
1343
                  freemem = newmem;
 
1344
# endif
 
1345
 
 
1346
                  outbuf = freemem + sizeof (size_t);
 
1347
                }
 
1348
 
 
1349
              /* We have now in our buffer a converted string.  Put this
 
1350
                 into the table of conversions.  */
 
1351
              *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
 
1352
              convd->conv_tab[act] = (char *) freemem;
 
1353
              /* Shrink freemem, but keep it aligned.  */
 
1354
              freemem_size -= outbuf - freemem;
 
1355
              freemem = outbuf;
 
1356
              freemem += freemem_size & (alignof (size_t) - 1);
 
1357
              freemem_size = freemem_size & ~ (alignof (size_t) - 1);
 
1358
 
 
1359
              __libc_lock_unlock (lock);
 
1360
            }
 
1361
 
 
1362
          /* Now convd->conv_tab[act] contains the translation of all
 
1363
             the plural variants.  */
 
1364
          result = convd->conv_tab[act] + sizeof (size_t);
 
1365
          resultlen = *(size_t *) convd->conv_tab[act];
 
1366
        }
 
1367
    }
 
1368
 
 
1369
  /* The result string is converted.  */
 
1370
 
 
1371
#endif /* _LIBC || HAVE_ICONV */
 
1372
 
 
1373
  *lengthp = resultlen;
 
1374
  return result;
 
1375
}
 
1376
 
 
1377
 
 
1378
/* Look up a plural variant.  */
 
1379
static char *
 
1380
internal_function
 
1381
plural_lookup (struct loaded_l10nfile *domain, unsigned long int n,
 
1382
               const char *translation, size_t translation_len)
 
1383
{
 
1384
  struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
 
1385
  unsigned long int index;
 
1386
  const char *p;
 
1387
 
 
1388
  index = plural_eval (domaindata->plural, n);
 
1389
  if (index >= domaindata->nplurals)
 
1390
    /* This should never happen.  It means the plural expression and the
 
1391
       given maximum value do not match.  */
 
1392
    index = 0;
 
1393
 
 
1394
  /* Skip INDEX strings at TRANSLATION.  */
 
1395
  p = translation;
 
1396
  while (index-- > 0)
 
1397
    {
 
1398
#ifdef _LIBC
 
1399
      p = __rawmemchr (p, '\0');
 
1400
#else
 
1401
      p = strchr (p, '\0');
 
1402
#endif
 
1403
      /* And skip over the NUL byte.  */
 
1404
      p++;
 
1405
 
 
1406
      if (p >= translation + translation_len)
 
1407
        /* This should never happen.  It means the plural expression
 
1408
           evaluated to a value larger than the number of variants
 
1409
           available for MSGID1.  */
 
1410
        return (char *) translation;
 
1411
    }
 
1412
  return (char *) p;
 
1413
}
 
1414
 
 
1415
#ifndef _LIBC
 
1416
/* Return string representation of locale CATEGORY.  */
 
1417
static const char *
 
1418
internal_function
 
1419
category_to_name (int category)
 
1420
{
 
1421
  const char *retval;
 
1422
 
 
1423
  switch (category)
 
1424
  {
 
1425
#ifdef LC_COLLATE
 
1426
  case LC_COLLATE:
 
1427
    retval = "LC_COLLATE";
 
1428
    break;
 
1429
#endif
 
1430
#ifdef LC_CTYPE
 
1431
  case LC_CTYPE:
 
1432
    retval = "LC_CTYPE";
 
1433
    break;
 
1434
#endif
 
1435
#ifdef LC_MONETARY
 
1436
  case LC_MONETARY:
 
1437
    retval = "LC_MONETARY";
 
1438
    break;
 
1439
#endif
 
1440
#ifdef LC_NUMERIC
 
1441
  case LC_NUMERIC:
 
1442
    retval = "LC_NUMERIC";
 
1443
    break;
 
1444
#endif
 
1445
#ifdef LC_TIME
 
1446
  case LC_TIME:
 
1447
    retval = "LC_TIME";
 
1448
    break;
 
1449
#endif
 
1450
#ifdef LC_MESSAGES
 
1451
  case LC_MESSAGES:
 
1452
    retval = "LC_MESSAGES";
 
1453
    break;
 
1454
#endif
 
1455
#ifdef LC_RESPONSE
 
1456
  case LC_RESPONSE:
 
1457
    retval = "LC_RESPONSE";
 
1458
    break;
 
1459
#endif
 
1460
#ifdef LC_ALL
 
1461
  case LC_ALL:
 
1462
    /* This might not make sense but is perhaps better than any other
 
1463
       value.  */
 
1464
    retval = "LC_ALL";
 
1465
    break;
 
1466
#endif
 
1467
  default:
 
1468
    /* If you have a better idea for a default value let me know.  */
 
1469
    retval = "LC_XXX";
 
1470
  }
 
1471
 
 
1472
  return retval;
 
1473
}
 
1474
#endif
 
1475
 
 
1476
/* Guess value of current locale from value of the environment variables
 
1477
   or system-dependent defaults.  */
 
1478
static const char *
 
1479
internal_function
 
1480
#ifdef IN_LIBGLOCALE
 
1481
guess_category_value (int category, const char *categoryname,
 
1482
                      const char *locale)
 
1483
 
 
1484
#else
 
1485
guess_category_value (int category, const char *categoryname)
 
1486
#endif
 
1487
{
 
1488
  const char *language;
 
1489
#ifndef IN_LIBGLOCALE
 
1490
  const char *locale;
 
1491
# ifndef _LIBC
 
1492
  const char *language_default;
 
1493
  int locale_defaulted;
 
1494
# endif
 
1495
#endif
 
1496
 
 
1497
  /* We use the settings in the following order:
 
1498
     1. The value of the environment variable 'LANGUAGE'.  This is a GNU
 
1499
        extension.  Its value can be a colon-separated list of locale names.
 
1500
     2. The value of the environment variable 'LC_ALL', 'LC_xxx', or 'LANG'.
 
1501
        More precisely, the first among these that is set to a non-empty value.
 
1502
        This is how POSIX specifies it.  The value is a single locale name.
 
1503
     3. A system-dependent preference list of languages.  Its value can be a
 
1504
        colon-separated list of locale names.
 
1505
     4. A system-dependent default locale name.
 
1506
     This way:
 
1507
       - System-dependent settings can be overridden by environment variables.
 
1508
       - If the system provides both a list of languages and a default locale,
 
1509
         the former is used.  */
 
1510
 
 
1511
#ifndef IN_LIBGLOCALE
 
1512
  /* Fetch the locale name, through the POSIX method of looking to `LC_ALL',
 
1513
     `LC_xxx', and `LANG'.  On some systems this can be done by the
 
1514
     `setlocale' function itself.  */
 
1515
# ifdef _LIBC
 
1516
  locale = __current_locale_name (category);
 
1517
# else
 
1518
#  if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS
 
1519
  /* The __names field is not public glibc API and must therefore not be used
 
1520
     in code that is installed in public locations.  */
 
1521
  locale_t thread_locale = uselocale (NULL);
 
1522
  if (thread_locale != LC_GLOBAL_LOCALE)
 
1523
    {
 
1524
      locale = thread_locale->__names[category];
 
1525
      locale_defaulted = 0;
 
1526
    }
 
1527
  else
 
1528
#  endif
 
1529
    {
 
1530
      locale = _nl_locale_name_posix (category, categoryname);
 
1531
      locale_defaulted = 0;
 
1532
      if (locale == NULL)
 
1533
        {
 
1534
          locale = _nl_locale_name_default ();
 
1535
          locale_defaulted = 1;
 
1536
        }
 
1537
    }
 
1538
# endif
 
1539
#endif
 
1540
 
 
1541
  /* Ignore LANGUAGE and its system-dependent analogon if the locale is set
 
1542
     to "C" because
 
1543
     1. "C" locale usually uses the ASCII encoding, and most international
 
1544
        messages use non-ASCII characters. These characters get displayed
 
1545
        as question marks (if using glibc's iconv()) or as invalid 8-bit
 
1546
        characters (because other iconv()s refuse to convert most non-ASCII
 
1547
        characters to ASCII). In any case, the output is ugly.
 
1548
     2. The precise output of some programs in the "C" locale is specified
 
1549
        by POSIX and should not depend on environment variables like
 
1550
        "LANGUAGE" or system-dependent information.  We allow such programs
 
1551
        to use gettext().  */
 
1552
  if (strcmp (locale, "C") == 0)
 
1553
    return locale;
 
1554
 
 
1555
  /* The highest priority value is the value of the 'LANGUAGE' environment
 
1556
     variable.  */
 
1557
  language = getenv ("LANGUAGE");
 
1558
  if (language != NULL && language[0] != '\0')
 
1559
    return language;
 
1560
#if !defined IN_LIBGLOCALE && !defined _LIBC
 
1561
  /* The next priority value is the locale name, if not defaulted.  */
 
1562
  if (locale_defaulted)
 
1563
    {
 
1564
      /* The next priority value is the default language preferences list. */
 
1565
      language_default = _nl_language_preferences_default ();
 
1566
      if (language_default != NULL)
 
1567
        return language_default;
 
1568
    }
 
1569
  /* The least priority value is the locale name, if defaulted.  */
 
1570
#endif
 
1571
  return locale;
 
1572
}
 
1573
 
 
1574
#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
 
1575
/* Returns the output charset.  */
 
1576
static const char *
 
1577
internal_function
 
1578
get_output_charset (struct binding *domainbinding)
 
1579
{
 
1580
  /* The output charset should normally be determined by the locale.  But
 
1581
     sometimes the locale is not used or not correctly set up, so we provide
 
1582
     a possibility for the user to override this: the OUTPUT_CHARSET
 
1583
     environment variable.  Moreover, the value specified through
 
1584
     bind_textdomain_codeset overrides both.  */
 
1585
  if (domainbinding != NULL && domainbinding->codeset != NULL)
 
1586
    return domainbinding->codeset;
 
1587
  else
 
1588
    {
 
1589
      /* For speed reasons, we look at the value of OUTPUT_CHARSET only
 
1590
         once.  This is a user variable that is not supposed to change
 
1591
         during a program run.  */
 
1592
      static char *output_charset_cache;
 
1593
      static int output_charset_cached;
 
1594
 
 
1595
      if (!output_charset_cached)
 
1596
        {
 
1597
          const char *value = getenv ("OUTPUT_CHARSET");
 
1598
 
 
1599
          if (value != NULL && value[0] != '\0')
 
1600
            {
 
1601
              size_t len = strlen (value) + 1;
 
1602
              char *value_copy = (char *) malloc (len);
 
1603
 
 
1604
              if (value_copy != NULL)
 
1605
                memcpy (value_copy, value, len);
 
1606
              output_charset_cache = value_copy;
 
1607
            }
 
1608
          output_charset_cached = 1;
 
1609
        }
 
1610
 
 
1611
      if (output_charset_cache != NULL)
 
1612
        return output_charset_cache;
 
1613
      else
 
1614
        {
 
1615
# ifdef _LIBC
 
1616
          return _NL_CURRENT (LC_CTYPE, CODESET);
 
1617
# else
 
1618
#  if HAVE_ICONV
 
1619
          return locale_charset ();
 
1620
#  endif
 
1621
# endif
 
1622
        }
 
1623
    }
 
1624
}
 
1625
#endif
 
1626
 
 
1627
/* @@ begin of epilog @@ */
 
1628
 
 
1629
/* We don't want libintl.a to depend on any other library.  So we
 
1630
   avoid the non-standard function stpcpy.  In GNU C Library this
 
1631
   function is available, though.  Also allow the symbol HAVE_STPCPY
 
1632
   to be defined.  */
 
1633
#if !_LIBC && !HAVE_STPCPY
 
1634
static char *
 
1635
stpcpy (char *dest, const char *src)
 
1636
{
 
1637
  while ((*dest++ = *src++) != '\0')
 
1638
    /* Do nothing. */ ;
 
1639
  return dest - 1;
 
1640
}
 
1641
#endif
 
1642
 
 
1643
#if !_LIBC && !HAVE_MEMPCPY
 
1644
static void *
 
1645
mempcpy (void *dest, const void *src, size_t n)
 
1646
{
 
1647
  return (void *) ((char *) memcpy (dest, src, n) + n);
 
1648
}
 
1649
#endif
 
1650
 
 
1651
#if !_LIBC && !HAVE_TSEARCH
 
1652
# include "tsearch.c"
 
1653
#endif
 
1654
 
 
1655
 
 
1656
#ifdef _LIBC
 
1657
/* If we want to free all resources we have to do some work at
 
1658
   program's end.  */
 
1659
libc_freeres_fn (free_mem)
 
1660
{
 
1661
  void *old;
 
1662
 
 
1663
  while (_nl_domain_bindings != NULL)
 
1664
    {
 
1665
      struct binding *oldp = _nl_domain_bindings;
 
1666
      _nl_domain_bindings = _nl_domain_bindings->next;
 
1667
      if (oldp->dirname != _nl_default_dirname)
 
1668
        /* Yes, this is a pointer comparison.  */
 
1669
        free (oldp->dirname);
 
1670
      free (oldp->codeset);
 
1671
      free (oldp);
 
1672
    }
 
1673
 
 
1674
  if (_nl_current_default_domain != _nl_default_default_domain)
 
1675
    /* Yes, again a pointer comparison.  */
 
1676
    free ((char *) _nl_current_default_domain);
 
1677
 
 
1678
  /* Remove the search tree with the known translations.  */
 
1679
  __tdestroy (root, free);
 
1680
  root = NULL;
 
1681
 
 
1682
  while (transmem_list != NULL)
 
1683
    {
 
1684
      old = transmem_list;
 
1685
      transmem_list = transmem_list->next;
 
1686
      free (old);
 
1687
    }
 
1688
}
 
1689
#endif