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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.17.0/] [newlib/] [libc/] [sys/] [linux/] [intl/] [localealias.c] - Blame information for rev 438

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

Line No. Rev Author Line
1 148 jeremybenn
#include <newlib.h>
2
 
3
#ifdef _MB_CAPABLE
4
 
5
/* Handle aliases for locale names.
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 <stdio.h>
37
#if defined _GLIBC || defined HAVE___FSETLOCKING
38
# include <stdio_ext.h>
39
#endif
40
#include <sys/types.h>
41
 
42
#ifdef __GNUC__
43
# define alloca __builtin_alloca
44
# define HAVE_ALLOCA 1
45
#else
46
# if defined HAVE_ALLOCA_H || defined _LIBC
47
#  include <alloca.h>
48
# else
49
#  ifdef _AIX
50
 #pragma alloca
51
#  else
52
#   ifndef alloca
53
char *alloca ();
54
#   endif
55
#  endif
56
# endif
57
#endif
58
 
59
#if defined STDC_HEADERS || defined _LIBC
60
# include <stdlib.h>
61
#else
62
# ifdef HAVE_MALLOC_H
63
#  include <malloc.h>
64
# else
65
void free ();
66
# endif
67
#endif
68
 
69
#if defined HAVE_STRING_H || defined _LIBC
70
# include <string.h>
71
#else
72
# include <strings.h>
73
# ifndef memcpy
74
#  define memcpy(Dst, Src, Num) (bcopy (Src, Dst, Num), (Dst))
75
# endif
76
#endif
77
#if !HAVE_STRCHR && !defined _LIBC
78
# ifndef strchr
79
#  define strchr index
80
# endif
81
#endif
82
 
83
#include "gettextP.h"
84
 
85
/* @@ end of prolog @@ */
86
 
87
#ifdef _LIBC
88
/* Rename the non ANSI C functions.  This is required by the standard
89
   because some ANSI C functions will require linking with this object
90
   file and the name space must not be polluted.  */
91
 
92
#ifdef _GLIBC
93
# define strcasecmp __strcasecmp
94
# ifndef mempcpy
95
#  define mempcpy __mempcpy
96
# endif
97
# define HAVE_MEMPCPY   1
98
# define HAVE___FSETLOCKING     1
99
#endif
100
 
101
/* We need locking here since we can be called from different places.  */
102
# include <bits/libc-lock.h>
103
 
104
__libc_lock_define_initialized (static, lock);
105
#endif
106
 
107
#ifndef internal_function
108
# define internal_function
109
#endif
110
 
111
/* Some optimizations for glibc.  */
112
#ifdef _GLIBC
113
# define FEOF(fp)               feof_unlocked (fp)
114
# define FGETS(buf, n, fp)      fgets_unlocked (buf, n, fp)
115
#else
116
# define FEOF(fp)               feof (fp)
117
# define FGETS(buf, n, fp)      fgets (buf, n, fp)
118
#endif
119
 
120
/* For those losing systems which don't have `alloca' we have to add
121
   some additional code emulating it.  */
122
#ifdef HAVE_ALLOCA
123
# define freea(p) /* nothing */
124
#else
125
# define alloca(n) malloc (n)
126
# define freea(p) free (p)
127
#endif
128
 
129
#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED
130
# undef fgets
131
# define fgets(buf, len, s) fgets_unlocked (buf, len, s)
132
#endif
133
#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED
134
# undef feof
135
# define feof(s) feof_unlocked (s)
136
#endif
137
 
138
 
139
struct alias_map
140
{
141
  const char *alias;
142
  const char *value;
143
};
144
 
145
 
146
static char *string_space;
147
static size_t string_space_act;
148
static size_t string_space_max;
149
static struct alias_map *map;
150
static size_t nmap;
151
static size_t maxmap;
152
 
153
 
154
/* Prototypes for local functions.  */
155
static size_t read_alias_file PARAMS ((const char *fname, int fname_len))
156
     internal_function;
157
static int extend_alias_table PARAMS ((void));
158
static int alias_compare PARAMS ((const struct alias_map *map1,
159
                                  const struct alias_map *map2));
160
 
161
 
162
const char *
163
_nl_expand_alias (name)
164
    const char *name;
165
{
166
  static const char *locale_alias_path = LOCALE_ALIAS_PATH;
167
  struct alias_map *retval;
168
  const char *result = NULL;
169
  size_t added;
170
 
171
#ifdef _LIBC
172
  __libc_lock_lock (lock);
173
#endif
174
 
175
  do
176
    {
177
      struct alias_map item;
178
 
179
      item.alias = name;
180
 
181
      if (nmap > 0)
182
        retval = (struct alias_map *) bsearch (&item, map, nmap,
183
                                               sizeof (struct alias_map),
184
                                               (int (*) PARAMS ((const void *,
185
                                                                 const void *))
186
                                                ) alias_compare);
187
      else
188
        retval = NULL;
189
 
190
      /* We really found an alias.  Return the value.  */
191
      if (retval != NULL)
192
        {
193
          result = retval->value;
194
          break;
195
        }
196
 
197
      /* Perhaps we can find another alias file.  */
198
      added = 0;
199
      while (added == 0 && locale_alias_path[0] != '\0')
200
        {
201
          const char *start;
202
 
203
          while (locale_alias_path[0] == ':')
204
            ++locale_alias_path;
205
          start = locale_alias_path;
206
 
207
          while (locale_alias_path[0] != '\0' && locale_alias_path[0] != ':')
208
            ++locale_alias_path;
209
 
210
          if (start < locale_alias_path)
211
            added = read_alias_file (start, locale_alias_path - start);
212
        }
213
    }
214
  while (added != 0);
215
 
216
#ifdef _LIBC
217
  __libc_lock_unlock (lock);
218
#endif
219
 
220
  return result;
221
}
222
 
223
 
224
static size_t
225
internal_function
226
read_alias_file (fname, fname_len)
227
     const char *fname;
228
     int fname_len;
229
{
230
  FILE *fp;
231
  char *full_fname;
232
  size_t added;
233
  static const char aliasfile[] = "/locale.alias";
234
 
235
  full_fname = (char *) alloca (fname_len + sizeof aliasfile);
236
#ifdef HAVE_MEMPCPY
237
  mempcpy (mempcpy (full_fname, fname, fname_len),
238
           aliasfile, sizeof aliasfile);
239
#else
240
  memcpy (full_fname, fname, fname_len);
241
  memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
242
#endif
243
 
244
  fp = fopen (full_fname, "r");
245
  freea (full_fname);
246
  if (fp == NULL)
247
    return 0;
248
 
249
#ifdef HAVE___FSETLOCKING
250
  /* No threads present.  */
251
  __fsetlocking (fp, FSETLOCKING_BYCALLER);
252
#endif
253
 
254
  added = 0;
255
  while (!FEOF (fp))
256
    {
257
      /* It is a reasonable approach to use a fix buffer here because
258
         a) we are only interested in the first two fields
259
         b) these fields must be usable as file names and so must not
260
            be that long
261
       */
262
      char buf[BUFSIZ];
263
      char *alias;
264
      char *value;
265
      char *cp;
266
 
267
      if (FGETS (buf, sizeof buf, fp) == NULL)
268
        /* EOF reached.  */
269
        break;
270
 
271
      /* Possibly not the whole line fits into the buffer.  Ignore
272
         the rest of the line.  */
273
      if (strchr (buf, '\n') == NULL)
274
        {
275
          char altbuf[BUFSIZ];
276
          do
277
            if (FGETS (altbuf, sizeof altbuf, fp) == NULL)
278
              /* Make sure the inner loop will be left.  The outer loop
279
                 will exit at the `feof' test.  */
280
              break;
281
          while (strchr (altbuf, '\n') == NULL);
282
        }
283
 
284
      cp = buf;
285
      /* Ignore leading white space.  */
286
      while (isspace (cp[0]))
287
        ++cp;
288
 
289
      /* A leading '#' signals a comment line.  */
290
      if (cp[0] != '\0' && cp[0] != '#')
291
        {
292
          alias = cp++;
293
          while (cp[0] != '\0' && !isspace (cp[0]))
294
            ++cp;
295
          /* Terminate alias name.  */
296
          if (cp[0] != '\0')
297
            *cp++ = '\0';
298
 
299
          /* Now look for the beginning of the value.  */
300
          while (isspace (cp[0]))
301
            ++cp;
302
 
303
          if (cp[0] != '\0')
304
            {
305
              size_t alias_len;
306
              size_t value_len;
307
 
308
              value = cp++;
309
              while (cp[0] != '\0' && !isspace (cp[0]))
310
                ++cp;
311
              /* Terminate value.  */
312
              if (cp[0] == '\n')
313
                {
314
                  /* This has to be done to make the following test
315
                     for the end of line possible.  We are looking for
316
                     the terminating '\n' which do not overwrite here.  */
317
                  *cp++ = '\0';
318
                  *cp = '\n';
319
                }
320
              else if (cp[0] != '\0')
321
                *cp++ = '\0';
322
 
323
              if (nmap >= maxmap)
324
                if (__builtin_expect (extend_alias_table (), 0))
325
                  return added;
326
 
327
              alias_len = strlen (alias) + 1;
328
              value_len = strlen (value) + 1;
329
 
330
              if (string_space_act + alias_len + value_len > string_space_max)
331
                {
332
                  /* Increase size of memory pool.  */
333
                  size_t new_size = (string_space_max
334
                                     + (alias_len + value_len > 1024
335
                                        ? alias_len + value_len : 1024));
336
                  char *new_pool = (char *) realloc (string_space, new_size);
337
                  if (new_pool == NULL)
338
                    return added;
339
 
340
                  if (__builtin_expect (string_space != new_pool, 0))
341
                    {
342
                      size_t i;
343
 
344
                      for (i = 0; i < nmap; i++)
345
                        {
346
                          map[i].alias += new_pool - string_space;
347
                          map[i].value += new_pool - string_space;
348
                        }
349
                    }
350
 
351
                  string_space = new_pool;
352
                  string_space_max = new_size;
353
                }
354
 
355
              map[nmap].alias = memcpy (&string_space[string_space_act],
356
                                        alias, alias_len);
357
              string_space_act += alias_len;
358
 
359
              map[nmap].value = memcpy (&string_space[string_space_act],
360
                                        value, value_len);
361
              string_space_act += value_len;
362
 
363
              ++nmap;
364
              ++added;
365
            }
366
        }
367
    }
368
 
369
  /* Should we test for ferror()?  I think we have to silently ignore
370
     errors.  --drepper  */
371
  fclose (fp);
372
 
373
  if (added > 0)
374
    qsort (map, nmap, sizeof (struct alias_map),
375
           (int (*) PARAMS ((const void *, const void *))) alias_compare);
376
 
377
  return added;
378
}
379
 
380
 
381
static int
382
extend_alias_table ()
383
{
384
  size_t new_size;
385
  struct alias_map *new_map;
386
 
387
  new_size = maxmap == 0 ? 100 : 2 * maxmap;
388
  new_map = (struct alias_map *) realloc (map, (new_size
389
                                                * sizeof (struct alias_map)));
390
  if (new_map == NULL)
391
    /* Simply don't extend: we don't have any more core.  */
392
    return -1;
393
 
394
  map = new_map;
395
  maxmap = new_size;
396
  return 0;
397
}
398
 
399
 
400
#ifdef _LIBC
401
static void __attribute__ ((unused))
402
free_mem (void)
403
{
404
  if (string_space != NULL)
405
    free (string_space);
406
  if (map != NULL)
407
    free (map);
408
}
409
text_set_element (__libc_subfreeres, free_mem);
410
#endif
411
 
412
 
413
static int
414
alias_compare (map1, map2)
415
     const struct alias_map *map1;
416
     const struct alias_map *map2;
417
{
418
#if defined _LIBC || defined HAVE_STRCASECMP
419
  return strcasecmp (map1->alias, map2->alias);
420
#else
421
  const unsigned char *p1 = (const unsigned char *) map1->alias;
422
  const unsigned char *p2 = (const unsigned char *) map2->alias;
423
  unsigned char c1, c2;
424
 
425
  if (p1 == p2)
426
    return 0;
427
 
428
  do
429
    {
430
      /* I know this seems to be odd but the tolower() function in
431
         some systems libc cannot handle nonalpha characters.  */
432
      c1 = isupper (*p1) ? tolower (*p1) : *p1;
433
      c2 = isupper (*p2) ? tolower (*p2) : *p2;
434
      if (c1 == '\0')
435
        break;
436
      ++p1;
437
      ++p2;
438
    }
439
  while (c1 == c2);
440
 
441
  return c1 - c2;
442
#endif
443
}
444
 
445
#endif /* _MB_CAPABLE */

powered by: WebSVN 2.1.0

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