OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.18.0/] [newlib/] [libc/] [sys/] [linux/] [intl/] [loadmsgcat.c] - Blame information for rev 258

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 207 jeremybenn
#include <newlib.h>
2
 
3
#ifdef _MB_CAPABLE 
4
 
5
/* Load needed message catalogs.
6
   Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
7
   This file is part of the GNU C Library.
8
 
9
   The GNU C Library is free software; you can redistribute it and/or
10
   modify it under the terms of the GNU Lesser General Public
11
   License as published by the Free Software Foundation; either
12
   version 2.1 of the License, or (at your option) any later version.
13
 
14
   The GNU C Library is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
   Lesser General Public License for more details.
18
 
19
   You should have received a copy of the GNU Lesser General Public
20
   License along with the GNU C Library; if not, write to the Free
21
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22
   02111-1307 USA.  */
23
 
24
/* Tell glibc's <string.h> to provide a prototype for mempcpy().
25
   This must come before <config.h> because <config.h> may include
26
   <features.h>, and once <features.h> has been included, it's too late.  */
27
#ifndef _GNU_SOURCE
28
# define _GNU_SOURCE    1
29
#endif
30
 
31
#ifdef HAVE_CONFIG_H
32
# include <config.h>
33
#endif
34
 
35
#include <ctype.h>
36
#include <errno.h>
37
#include <fcntl.h>
38
#include <sys/types.h>
39
#include <sys/stat.h>
40
 
41
#ifdef __GNUC__
42
# define alloca __builtin_alloca
43
# define HAVE_ALLOCA 1
44
#else
45
# if defined HAVE_ALLOCA_H || defined _LIBC
46
#  include <alloca.h>
47
# else
48
#  ifdef _AIX
49
 #pragma alloca
50
#  else
51
#   ifndef alloca
52
char *alloca ();
53
#   endif
54
#  endif
55
# endif
56
#endif
57
 
58
#if defined STDC_HEADERS || defined _LIBC
59
# include <stdlib.h>
60
#endif
61
 
62
#if defined HAVE_STRING_H || defined _LIBC
63
# include <string.h>
64
#else
65
# include <strings.h>
66
#endif
67
 
68
#if defined HAVE_UNISTD_H || defined _LIBC
69
# include <unistd.h>
70
#endif
71
 
72
#ifdef _LIBC
73
# include <langinfo.h>
74
# include <locale.h>
75
#endif
76
 
77
#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
78
    || (defined _LIBC && defined _POSIX_MAPPED_FILES)
79
# include <sys/mman.h>
80
# undef HAVE_MMAP
81
# define HAVE_MMAP      1
82
#else
83
# undef HAVE_MMAP
84
#endif
85
 
86
#include "gettext.h"
87
#include "gettextP.h"
88
 
89
#ifdef _GLIBC
90
# include "localeinfo.h"
91
#endif
92
 
93
/* @@ end of prolog @@ */
94
 
95
#ifdef _LIBC
96
/* Rename the non ISO C functions.  This is required by the standard
97
   because some ISO C functions will require linking with this object
98
   file and the name space must not be polluted.  */
99
# define open   __open
100
# define close  __close
101
# define read   __read
102
# define mmap   __mmap
103
# define munmap __munmap
104
#endif
105
 
106
/* Names for the libintl functions are a problem.  They must not clash
107
   with existing names and they should follow ANSI C.  But this source
108
   code is also used in GNU C Library where the names have a __
109
   prefix.  So we have to make a difference here.  */
110
#ifdef _LIBC
111
# define PLURAL_PARSE __gettextparse
112
#else
113
# define PLURAL_PARSE gettextparse__
114
#endif
115
 
116
/* For those losing systems which don't have `alloca' we have to add
117
   some additional code emulating it.  */
118
#ifdef HAVE_ALLOCA
119
# define freea(p) /* nothing */
120
#else
121
# define alloca(n) malloc (n)
122
# define freea(p) free (p)
123
#endif
124
 
125
/* We need a sign, whether a new catalog was loaded, which can be associated
126
   with all translations.  This is important if the translations are
127
   cached by one of GCC's features.  */
128
int _nl_msg_cat_cntr;
129
 
130
#if defined __GNUC__ \
131
    || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
132
 
133
/* These structs are the constant expression for the germanic plural
134
   form determination.  It represents the expression  "n != 1".  */
135
static const struct expression plvar =
136
{
137
  .nargs = 0,
138
  .operation = var,
139
};
140
static const struct expression plone =
141
{
142
  .nargs = 0,
143
  .operation = num,
144
  .val =
145
  {
146
    .num = 1
147
  }
148
};
149
static struct expression germanic_plural =
150
{
151
  .nargs = 2,
152
  .operation = not_equal,
153
  .val =
154
  {
155
    .args =
156
    {
157
      [0] = (struct expression *) &plvar,
158
      [1] = (struct expression *) &plone
159
    }
160
  }
161
};
162
 
163
# define INIT_GERMANIC_PLURAL()
164
 
165
#else
166
 
167
/* For compilers without support for ISO C 99 struct/union initializers:
168
   Initialization at run-time.  */
169
 
170
static struct expression plvar;
171
static struct expression plone;
172
static struct expression germanic_plural;
173
 
174
static void
175
init_germanic_plural ()
176
{
177
  if (plone.val.num == 0)
178
    {
179
      plvar.nargs = 0;
180
      plvar.operation = var;
181
 
182
      plone.nargs = 0;
183
      plone.operation = num;
184
      plone.val.num = 1;
185
 
186
      germanic_plural.nargs = 2;
187
      germanic_plural.operation = not_equal;
188
      germanic_plural.val.args[0] = &plvar;
189
      germanic_plural.val.args[1] = &plone;
190
    }
191
}
192
 
193
# define INIT_GERMANIC_PLURAL() init_germanic_plural ()
194
 
195
#endif
196
 
197
 
198
/* Initialize the codeset dependent parts of an opened message catalog.
199
   Return the header entry.  */
200
const char *
201
internal_function
202
_nl_init_domain_conv (domain_file, domain, domainbinding)
203
     struct loaded_l10nfile *domain_file;
204
     struct loaded_domain *domain;
205
     struct binding *domainbinding;
206
{
207
  /* Find out about the character set the file is encoded with.
208
     This can be found (in textual form) in the entry "".  If this
209
     entry does not exist or if this does not contain the `charset='
210
     information, we will assume the charset matches the one the
211
     current locale and we don't have to perform any conversion.  */
212
  char *nullentry;
213
  size_t nullentrylen;
214
 
215
  /* Preinitialize fields, to avoid recursion during _nl_find_msg.  */
216
  domain->codeset_cntr =
217
    (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
218
#ifdef _GLIBC
219
  domain->conv = (__gconv_t) -1;
220
#else
221
# if HAVE_ICONV
222
  domain->conv = (iconv_t) -1;
223
# endif
224
#endif
225
  domain->conv_tab = NULL;
226
 
227
  /* Get the header entry.  */
228
  nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
229
 
230
  if (nullentry != NULL)
231
    {
232
#if defined _LIBC || HAVE_ICONV
233
      const char *charsetstr;
234
 
235
      charsetstr = strstr (nullentry, "charset=");
236
      if (charsetstr != NULL)
237
        {
238
          size_t len;
239
          char *charset;
240
          const char *outcharset;
241
 
242
          charsetstr += strlen ("charset=");
243
          len = strcspn (charsetstr, " \t\n");
244
 
245
          charset = (char *) alloca (len + 1);
246
# if defined _LIBC || HAVE_MEMPCPY
247
          *((char *) mempcpy (charset, charsetstr, len)) = '\0';
248
# else
249
          memcpy (charset, charsetstr, len);
250
          charset[len] = '\0';
251
# endif
252
 
253
          /* The output charset should normally be determined by the
254
             locale.  But sometimes the locale is not used or not correctly
255
             set up, so we provide a possibility for the user to override
256
             this.  Moreover, the value specified through
257
             bind_textdomain_codeset overrides both.  */
258
          if (domainbinding != NULL && domainbinding->codeset != NULL)
259
            outcharset = domainbinding->codeset;
260
          else
261
            {
262
              outcharset = getenv ("OUTPUT_CHARSET");
263
              if (outcharset == NULL || outcharset[0] == '\0')
264
                {
265
# ifdef _GLIBC
266
                  outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
267
# else
268
#  if HAVE_ICONV
269
                  extern const char *__locale_msgcharset (void);
270
                  outcharset = __locale_msgcharset ();
271
#  endif
272
# endif
273
                }
274
            }
275
 
276
# ifdef _GLIBC
277
          /* We always want to use transliteration.  */
278
          outcharset = norm_add_slashes (outcharset, "TRANSLIT");
279
          charset = norm_add_slashes (charset, NULL);
280
          if (__gconv_open (outcharset, charset, &domain->conv,
281
                            GCONV_AVOID_NOCONV)
282
              != __GCONV_OK)
283
            domain->conv = (__gconv_t) -1;
284
# else
285
#  if HAVE_ICONV
286
          /* When using GNU libiconv, we want to use transliteration.  */
287
#   if _LIBICONV_VERSION
288
          len = strlen (outcharset);
289
          {
290
            char *tmp = (char *) alloca (len + 10 + 1);
291
            memcpy (tmp, outcharset, len);
292
            memcpy (tmp + len, "//TRANSLIT", 10 + 1);
293
            outcharset = tmp;
294
          }
295
#   endif
296
          domain->conv = iconv_open (outcharset, charset);
297
#   if _LIBICONV_VERSION
298
          freea (outcharset);
299
#   endif
300
#  endif
301
# endif
302
 
303
          freea (charset);
304
        }
305
#endif /* _LIBC || HAVE_ICONV */
306
    }
307
 
308
  return nullentry;
309
}
310
 
311
/* Frees the codeset dependent parts of an opened message catalog.  */
312
void
313
internal_function
314
_nl_free_domain_conv (domain)
315
     struct loaded_domain *domain;
316
{
317
  if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
318
    free (domain->conv_tab);
319
 
320
#ifdef _GLIBC
321
  if (domain->conv != (__gconv_t) -1)
322
    __gconv_close (domain->conv);
323
#else
324
# if HAVE_ICONV
325
  if (domain->conv != (iconv_t) -1)
326
    iconv_close (domain->conv);
327
# endif
328
#endif
329
}
330
 
331
/* Load the message catalogs specified by FILENAME.  If it is no valid
332
   message catalog do nothing.  */
333
void
334
internal_function
335
_nl_load_domain (domain_file, domainbinding)
336
     struct loaded_l10nfile *domain_file;
337
     struct binding *domainbinding;
338
{
339
  int fd;
340
  size_t size;
341
#ifdef _LIBC
342
  struct stat64 st;
343
#else
344
  struct stat st;
345
#endif
346
  struct mo_file_header *data = (struct mo_file_header *) -1;
347
  int use_mmap = 0;
348
  struct loaded_domain *domain;
349
  const char *nullentry;
350
 
351
  domain_file->decided = 1;
352
  domain_file->data = NULL;
353
 
354
  /* Note that it would be useless to store domainbinding in domain_file
355
     because domainbinding might be == NULL now but != NULL later (after
356
     a call to bind_textdomain_codeset).  */
357
 
358
  /* If the record does not represent a valid locale the FILENAME
359
     might be NULL.  This can happen when according to the given
360
     specification the locale file name is different for XPG and CEN
361
     syntax.  */
362
  if (domain_file->filename == NULL)
363
    return;
364
 
365
  /* Try to open the addressed file.  */
366
  fd = open (domain_file->filename, O_RDONLY);
367
  if (fd == -1)
368
    return;
369
 
370
  /* We must know about the size of the file.  */
371
  if (
372
#ifdef _LIBC
373
      __builtin_expect (fstat64 (fd, &st) != 0, 0)
374
#else
375
      __builtin_expect (fstat (fd, &st) != 0, 0)
376
#endif
377
      || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
378
      || __builtin_expect (size < sizeof (struct mo_file_header), 0))
379
    {
380
      /* Something went wrong.  */
381
      close (fd);
382
      return;
383
    }
384
 
385
#ifdef HAVE_MMAP
386
  /* Now we are ready to load the file.  If mmap() is available we try
387
     this first.  If not available or it failed we try to load it.  */
388
  data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
389
                                         MAP_PRIVATE, fd, 0);
390
 
391
  if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
392
    {
393
      /* mmap() call was successful.  */
394
      close (fd);
395
      use_mmap = 1;
396
    }
397
#endif
398
 
399
  /* If the data is not yet available (i.e. mmap'ed) we try to load
400
     it manually.  */
401
  if (data == (struct mo_file_header *) -1)
402
    {
403
      size_t to_read;
404
      char *read_ptr;
405
 
406
      data = (struct mo_file_header *) malloc (size);
407
      if (data == NULL)
408
        return;
409
 
410
      to_read = size;
411
      read_ptr = (char *) data;
412
      do
413
        {
414
          long int nb = (long int) read (fd, read_ptr, to_read);
415
          if (nb <= 0)
416
            {
417
#ifdef EINTR
418
              if (nb == -1 && errno == EINTR)
419
                continue;
420
#endif
421
              close (fd);
422
              return;
423
            }
424
          read_ptr += nb;
425
          to_read -= nb;
426
        }
427
      while (to_read > 0);
428
 
429
      close (fd);
430
    }
431
 
432
  /* Using the magic number we can test whether it really is a message
433
     catalog file.  */
434
  if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
435
                        0))
436
    {
437
      /* The magic number is wrong: not a message catalog file.  */
438
#ifdef HAVE_MMAP
439
      if (use_mmap)
440
        munmap ((caddr_t) data, size);
441
      else
442
#endif
443
        free (data);
444
      return;
445
    }
446
 
447
  domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
448
  if (domain == NULL)
449
    return;
450
  domain_file->data = domain;
451
 
452
  domain->data = (char *) data;
453
  domain->use_mmap = use_mmap;
454
  domain->mmap_size = size;
455
  domain->must_swap = data->magic != _MAGIC;
456
 
457
  /* Fill in the information about the available tables.  */
458
  switch (W (domain->must_swap, data->revision))
459
    {
460
    case 0:
461
      domain->nstrings = W (domain->must_swap, data->nstrings);
462
      domain->orig_tab = (struct string_desc *)
463
        ((char *) data + W (domain->must_swap, data->orig_tab_offset));
464
      domain->trans_tab = (struct string_desc *)
465
        ((char *) data + W (domain->must_swap, data->trans_tab_offset));
466
      domain->hash_size = W (domain->must_swap, data->hash_tab_size);
467
      domain->hash_tab = (nls_uint32 *)
468
        ((char *) data + W (domain->must_swap, data->hash_tab_offset));
469
      break;
470
    default:
471
      /* This is an invalid revision.  */
472
#ifdef HAVE_MMAP
473
      if (use_mmap)
474
        munmap ((caddr_t) data, size);
475
      else
476
#endif
477
        free (data);
478
      free (domain);
479
      domain_file->data = NULL;
480
      return;
481
    }
482
 
483
  /* Now initialize the character set converter from the character set
484
     the file is encoded with (found in the header entry) to the domain's
485
     specified character set or the locale's character set.  */
486
  nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
487
 
488
  /* Also look for a plural specification.  */
489
  if (nullentry != NULL)
490
    {
491
      const char *plural;
492
      const char *nplurals;
493
 
494
      plural = strstr (nullentry, "plural=");
495
      nplurals = strstr (nullentry, "nplurals=");
496
      if (plural == NULL || nplurals == NULL)
497
        goto no_plural;
498
      else
499
        {
500
          /* First get the number.  */
501
          char *endp;
502
          unsigned long int n;
503
          struct parse_args args;
504
 
505
          nplurals += 9;
506
          while (*nplurals != '\0' && isspace (*nplurals))
507
            ++nplurals;
508
#if defined HAVE_STRTOUL || defined _LIBC
509
          n = strtoul (nplurals, &endp, 10);
510
#else
511
          for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
512
            n = n * 10 + (*endp - '0');
513
#endif
514
          domain->nplurals = n;
515
          if (nplurals == endp)
516
            goto no_plural;
517
 
518
          /* Due to the restrictions bison imposes onto the interface of the
519
             scanner function we have to put the input string and the result
520
             passed up from the parser into the same structure which address
521
             is passed down to the parser.  */
522
          plural += 7;
523
          args.cp = plural;
524
          if (PLURAL_PARSE (&args) != 0)
525
            goto no_plural;
526
          domain->plural = args.res;
527
        }
528
    }
529
  else
530
    {
531
      /* By default we are using the Germanic form: singular form only
532
         for `one', the plural form otherwise.  Yes, this is also what
533
         English is using since English is a Germanic language.  */
534
    no_plural:
535
      INIT_GERMANIC_PLURAL ();
536
      domain->plural = &germanic_plural;
537
      domain->nplurals = 2;
538
    }
539
}
540
 
541
 
542
#ifdef _LIBC
543
void
544
internal_function
545
_nl_unload_domain (domain)
546
     struct loaded_domain *domain;
547
{
548
  if (domain->plural != &germanic_plural)
549
    __gettext_free_exp (domain->plural);
550
 
551
  _nl_free_domain_conv (domain);
552
 
553
# ifdef _POSIX_MAPPED_FILES
554
  if (domain->use_mmap)
555
    munmap ((caddr_t) domain->data, domain->mmap_size);
556
  else
557
# endif /* _POSIX_MAPPED_FILES */
558
    free ((void *) domain->data);
559
 
560
  free (domain);
561
}
562
#endif
563
 
564
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.