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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [intl/] [localealias.c] - Blame information for rev 15

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

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

powered by: WebSVN 2.1.0

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