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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [intl/] [l10nflist.c] - Blame information for rev 779

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

Line No. Rev Author Line
1 728 jeremybenn
/* Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
2
   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
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 stpcpy().
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
#include <string.h>
31
 
32
#if defined _LIBC || defined HAVE_ARGZ_H
33
# include <argz.h>
34
#endif
35
#include <ctype.h>
36
#include <sys/types.h>
37
#include <stdlib.h>
38
 
39
#include "loadinfo.h"
40
 
41
/* On some strange systems still no definition of NULL is found.  Sigh!  */
42
#ifndef NULL
43
# if defined __STDC__ && __STDC__
44
#  define NULL ((void *) 0)
45
# else
46
#  define NULL 0
47
# endif
48
#endif
49
 
50
/* @@ end of prolog @@ */
51
 
52
#ifdef _LIBC
53
/* Rename the non ANSI C functions.  This is required by the standard
54
   because some ANSI C functions will require linking with this object
55
   file and the name space must not be polluted.  */
56
# ifndef stpcpy
57
#  define stpcpy(dest, src) __stpcpy(dest, src)
58
# endif
59
#else
60
# ifndef HAVE_STPCPY
61
static char *stpcpy PARAMS ((char *dest, const char *src));
62
# endif
63
#endif
64
 
65
/* Pathname support.
66
   ISSLASH(C)           tests whether C is a directory separator character.
67
   IS_ABSOLUTE_PATH(P)  tests whether P is an absolute path.  If it is not,
68
                        it may be concatenated to a directory pathname.
69
 */
70
#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
71
  /* Win32, OS/2, DOS */
72
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
73
# define HAS_DEVICE(P) \
74
    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
75
     && (P)[1] == ':')
76
# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
77
#else
78
  /* Unix */
79
# define ISSLASH(C) ((C) == '/')
80
# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
81
#endif
82
 
83
/* Define function which are usually not available.  */
84
 
85
#if !defined _LIBC && !defined HAVE___ARGZ_COUNT
86
/* Returns the number of strings in ARGZ.  */
87
static size_t argz_count__ PARAMS ((const char *argz, size_t len));
88
 
89
static size_t
90
argz_count__ (argz, len)
91
     const char *argz;
92
     size_t len;
93
{
94
  size_t count = 0;
95
  while (len > 0)
96
    {
97
      size_t part_len = strlen (argz);
98
      argz += part_len + 1;
99
      len -= part_len + 1;
100
      count++;
101
    }
102
  return count;
103
}
104
# undef __argz_count
105
# define __argz_count(argz, len) argz_count__ (argz, len)
106
#else
107
# ifdef _LIBC
108
#  define __argz_count(argz, len) INTUSE(__argz_count) (argz, len)
109
# endif
110
#endif  /* !_LIBC && !HAVE___ARGZ_COUNT */
111
 
112
#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
113
/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
114
   except the last into the character SEP.  */
115
static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
116
 
117
static void
118
argz_stringify__ (argz, len, sep)
119
     char *argz;
120
     size_t len;
121
     int sep;
122
{
123
  while (len > 0)
124
    {
125
      size_t part_len = strlen (argz);
126
      argz += part_len;
127
      len -= part_len + 1;
128
      if (len > 0)
129
        *argz++ = sep;
130
    }
131
}
132
# undef __argz_stringify
133
# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
134
#else
135
# ifdef _LIBC
136
#  define __argz_stringify(argz, len, sep) \
137
  INTUSE(__argz_stringify) (argz, len, sep)
138
# endif
139
#endif  /* !_LIBC && !HAVE___ARGZ_STRINGIFY */
140
 
141
#if !defined _LIBC && !defined HAVE___ARGZ_NEXT
142
static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
143
                                  const char *entry));
144
 
145
static char *
146
argz_next__ (argz, argz_len, entry)
147
     char *argz;
148
     size_t argz_len;
149
     const char *entry;
150
{
151
  if (entry)
152
    {
153
      if (entry < argz + argz_len)
154
        entry = strchr (entry, '\0') + 1;
155
 
156
      return entry >= argz + argz_len ? NULL : (char *) entry;
157
    }
158
  else
159
    if (argz_len > 0)
160
      return argz;
161
    else
162
      return 0;
163
}
164
# undef __argz_next
165
# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
166
#endif  /* !_LIBC && !HAVE___ARGZ_NEXT */
167
 
168
 
169
/* Return number of bits set in X.  */
170
static int pop PARAMS ((int x));
171
 
172
static inline int
173
pop (x)
174
     int x;
175
{
176
  /* We assume that no more than 16 bits are used.  */
177
  x = ((x & ~0x5555) >> 1) + (x & 0x5555);
178
  x = ((x & ~0x3333) >> 2) + (x & 0x3333);
179
  x = ((x >> 4) + x) & 0x0f0f;
180
  x = ((x >> 8) + x) & 0xff;
181
 
182
  return x;
183
}
184
 
185
 
186
struct loaded_l10nfile *
187
_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
188
                    territory, codeset, normalized_codeset, modifier, special,
189
                    sponsor, revision, filename, do_allocate)
190
     struct loaded_l10nfile **l10nfile_list;
191
     const char *dirlist;
192
     size_t dirlist_len;
193
     int mask;
194
     const char *language;
195
     const char *territory;
196
     const char *codeset;
197
     const char *normalized_codeset;
198
     const char *modifier;
199
     const char *special;
200
     const char *sponsor;
201
     const char *revision;
202
     const char *filename;
203
     int do_allocate;
204
{
205
  char *abs_filename;
206
  struct loaded_l10nfile **lastp;
207
  struct loaded_l10nfile *retval;
208
  char *cp;
209
  size_t dirlist_count;
210
  size_t entries;
211
  int cnt;
212
 
213
  /* If LANGUAGE contains an absolute directory specification, we ignore
214
     DIRLIST.  */
215
  if (IS_ABSOLUTE_PATH (language))
216
    dirlist_len = 0;
217
 
218
  /* Allocate room for the full file name.  */
219
  abs_filename = (char *) malloc (dirlist_len
220
                                  + strlen (language)
221
                                  + ((mask & TERRITORY) != 0
222
                                     ? strlen (territory) + 1 : 0)
223
                                  + ((mask & XPG_CODESET) != 0
224
                                     ? strlen (codeset) + 1 : 0)
225
                                  + ((mask & XPG_NORM_CODESET) != 0
226
                                     ? strlen (normalized_codeset) + 1 : 0)
227
                                  + (((mask & XPG_MODIFIER) != 0
228
                                      || (mask & CEN_AUDIENCE) != 0)
229
                                     ? strlen (modifier) + 1 : 0)
230
                                  + ((mask & CEN_SPECIAL) != 0
231
                                     ? strlen (special) + 1 : 0)
232
                                  + (((mask & CEN_SPONSOR) != 0
233
                                      || (mask & CEN_REVISION) != 0)
234
                                     ? (1 + ((mask & CEN_SPONSOR) != 0
235
                                             ? strlen (sponsor) : 0)
236
                                        + ((mask & CEN_REVISION) != 0
237
                                           ? strlen (revision) + 1 : 0)) : 0)
238
                                  + 1 + strlen (filename) + 1);
239
 
240
  if (abs_filename == NULL)
241
    return NULL;
242
 
243
  /* Construct file name.  */
244
  cp = abs_filename;
245
  if (dirlist_len > 0)
246
    {
247
      memcpy (cp, dirlist, dirlist_len);
248
      __argz_stringify (cp, dirlist_len, PATH_SEPARATOR);
249
      cp += dirlist_len;
250
      cp[-1] = '/';
251
    }
252
 
253
  cp = stpcpy (cp, language);
254
 
255
  if ((mask & TERRITORY) != 0)
256
    {
257
      *cp++ = '_';
258
      cp = stpcpy (cp, territory);
259
    }
260
  if ((mask & XPG_CODESET) != 0)
261
    {
262
      *cp++ = '.';
263
      cp = stpcpy (cp, codeset);
264
    }
265
  if ((mask & XPG_NORM_CODESET) != 0)
266
    {
267
      *cp++ = '.';
268
      cp = stpcpy (cp, normalized_codeset);
269
    }
270
  if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
271
    {
272
      /* This component can be part of both syntaces but has different
273
         leading characters.  For CEN we use `+', else `@'.  */
274
      *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
275
      cp = stpcpy (cp, modifier);
276
    }
277
  if ((mask & CEN_SPECIAL) != 0)
278
    {
279
      *cp++ = '+';
280
      cp = stpcpy (cp, special);
281
    }
282
  if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0)
283
    {
284
      *cp++ = ',';
285
      if ((mask & CEN_SPONSOR) != 0)
286
        cp = stpcpy (cp, sponsor);
287
      if ((mask & CEN_REVISION) != 0)
288
        {
289
          *cp++ = '_';
290
          cp = stpcpy (cp, revision);
291
        }
292
    }
293
 
294
  *cp++ = '/';
295
  stpcpy (cp, filename);
296
 
297
  /* Look in list of already loaded domains whether it is already
298
     available.  */
299
  lastp = l10nfile_list;
300
  for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
301
    if (retval->filename != NULL)
302
      {
303
        int compare = strcmp (retval->filename, abs_filename);
304
        if (compare == 0)
305
          /* We found it!  */
306
          break;
307
        if (compare < 0)
308
          {
309
            /* It's not in the list.  */
310
            retval = NULL;
311
            break;
312
          }
313
 
314
        lastp = &retval->next;
315
      }
316
 
317
  if (retval != NULL || do_allocate == 0)
318
    {
319
      free (abs_filename);
320
      return retval;
321
    }
322
 
323
  dirlist_count = (dirlist_len > 0 ? __argz_count (dirlist, dirlist_len) : 1);
324
 
325
  /* Allocate a new loaded_l10nfile.  */
326
  retval =
327
    (struct loaded_l10nfile *)
328
    malloc (sizeof (*retval)
329
            + (((dirlist_count << pop (mask)) + (dirlist_count > 1 ? 1 : 0))
330
               * sizeof (struct loaded_l10nfile *)));
331
  if (retval == NULL)
332
    return NULL;
333
 
334
  retval->filename = abs_filename;
335
 
336
  /* We set retval->data to NULL here; it is filled in later.
337
     Setting retval->decided to 1 here means that retval does not
338
     correspond to a real file (dirlist_count > 1) or is not worth
339
     looking up (if an unnormalized codeset was specified).  */
340
  retval->decided = (dirlist_count > 1
341
                     || ((mask & XPG_CODESET) != 0
342
                         && (mask & XPG_NORM_CODESET) != 0));
343
  retval->data = NULL;
344
 
345
  retval->next = *lastp;
346
  *lastp = retval;
347
 
348
  entries = 0;
349
  /* Recurse to fill the inheritance list of RETVAL.
350
     If the DIRLIST is a real list (i.e. DIRLIST_COUNT > 1), the RETVAL
351
     entry does not correspond to a real file; retval->filename contains
352
     colons.  In this case we loop across all elements of DIRLIST and
353
     across all bit patterns dominated by MASK.
354
     If the DIRLIST is a single directory or entirely redundant (i.e.
355
     DIRLIST_COUNT == 1), we loop across all bit patterns dominated by
356
     MASK, excluding MASK itself.
357
     In either case, we loop down from MASK to 0.  This has the effect
358
     that the extra bits in the locale name are dropped in this order:
359
     first the modifier, then the territory, then the codeset, then the
360
     normalized_codeset.  */
361
  for (cnt = dirlist_count > 1 ? mask : mask - 1; cnt >= 0; --cnt)
362
    if ((cnt & ~mask) == 0
363
        && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
364
        && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
365
      {
366
        if (dirlist_count > 1)
367
          {
368
            /* Iterate over all elements of the DIRLIST.  */
369
            char *dir = NULL;
370
 
371
            while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
372
                   != NULL)
373
              retval->successor[entries++]
374
                = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1,
375
                                      cnt, language, territory, codeset,
376
                                      normalized_codeset, modifier, special,
377
                                      sponsor, revision, filename, 1);
378
          }
379
        else
380
          retval->successor[entries++]
381
            = _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len,
382
                                  cnt, language, territory, codeset,
383
                                  normalized_codeset, modifier, special,
384
                                  sponsor, revision, filename, 1);
385
      }
386
  retval->successor[entries] = NULL;
387
 
388
  return retval;
389
}
390
 
391
/* Normalize codeset name.  There is no standard for the codeset
392
   names.  Normalization allows the user to use any of the common
393
   names.  The return value is dynamically allocated and has to be
394
   freed by the caller.  */
395
const char *
396
_nl_normalize_codeset (codeset, name_len)
397
     const char *codeset;
398
     size_t name_len;
399
{
400
  int len = 0;
401
  int only_digit = 1;
402
  char *retval;
403
  char *wp;
404
  size_t cnt;
405
 
406
  for (cnt = 0; cnt < name_len; ++cnt)
407
    if (isalnum ((unsigned char) codeset[cnt]))
408
      {
409
        ++len;
410
 
411
        if (isalpha ((unsigned char) codeset[cnt]))
412
          only_digit = 0;
413
      }
414
 
415
  retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
416
 
417
  if (retval != NULL)
418
    {
419
      if (only_digit)
420
        wp = stpcpy (retval, "iso");
421
      else
422
        wp = retval;
423
 
424
      for (cnt = 0; cnt < name_len; ++cnt)
425
        if (isalpha ((unsigned char) codeset[cnt]))
426
          *wp++ = tolower ((unsigned char) codeset[cnt]);
427
        else if (isdigit ((unsigned char) codeset[cnt]))
428
          *wp++ = codeset[cnt];
429
 
430
      *wp = '\0';
431
    }
432
 
433
  return (const char *) retval;
434
}
435
 
436
 
437
/* @@ begin of epilog @@ */
438
 
439
/* We don't want libintl.a to depend on any other library.  So we
440
   avoid the non-standard function stpcpy.  In GNU C Library this
441
   function is available, though.  Also allow the symbol HAVE_STPCPY
442
   to be defined.  */
443
#if !_LIBC && !HAVE_STPCPY
444
static char *
445
stpcpy (dest, src)
446
     char *dest;
447
     const char *src;
448
{
449
  while ((*dest++ = *src++) != '\0')
450
    /* Do nothing. */ ;
451
  return dest - 1;
452
}
453
#endif

powered by: WebSVN 2.1.0

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