]>
git.ipfire.org Git - thirdparty/glibc.git/blob - intl/localealias.c
1 /* Handle aliases for locale names.
2 Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
4 This file is part of the GNU C Library. Its master source is NOT part of
5 the C library, however.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
28 #include <sys/types.h>
31 # define alloca __builtin_alloca
32 # define HAVE_ALLOCA 1
34 # if defined HAVE_ALLOCA_H || defined _LIBC
47 #if defined STDC_HEADERS || defined _LIBC
58 #if defined HAVE_STRING_H || defined _LIBC
60 # define _GNU_SOURCE 1
66 # define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
69 #if !HAVE_STRCHR && !defined _LIBC
78 /* @@ end of prolog @@ */
81 /* Rename the non ANSI C functions. This is required by the standard
82 because some ANSI C functions will require linking with this object
83 file and the name space must not be polluted. */
84 # define strcasecmp __strcasecmp
85 # define strdup __strdup
87 /* We need locking here since we can be called from different palces. */
88 # include <bits/libc-lock.h>
90 __libc_lock_define_initialized (static, lock
);
93 #ifndef internal_function
94 # define internal_function
97 /* For those loosing systems which don't have `alloca' we have to add
98 some additional code emulating it. */
100 /* Nothing has to be done. */
101 # define ADD_BLOCK(list, address) /* nothing */
102 # define FREE_BLOCKS(list) /* nothing */
107 struct block_list
*next
;
109 # define ADD_BLOCK(list, addr) \
111 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
112 /* If we cannot get a free block we cannot add the new element to \
114 if (newp != NULL) { \
115 newp->address = (addr); \
116 newp->next = (list); \
120 # define FREE_BLOCKS(list) \
122 while (list != NULL) { \
123 struct block_list *old = list; \
129 # define alloca(size) (malloc (size))
130 #endif /* have alloca */
140 static char *string_space
= NULL
;
141 static size_t string_space_act
= 0;
142 static size_t string_space_max
= 0;
143 static struct alias_map
*map
;
144 static size_t nmap
= 0;
145 static size_t maxmap
= 0;
148 /* Prototypes for local functions. */
149 static size_t read_alias_file
PARAMS ((const char *fname
, int fname_len
))
151 static void extend_alias_table
PARAMS ((void));
152 static int alias_compare
PARAMS ((const struct alias_map
*map1
,
153 const struct alias_map
*map2
));
157 _nl_expand_alias (name
)
160 static const char *locale_alias_path
= LOCALE_ALIAS_PATH
;
161 struct alias_map
*retval
;
162 const char *result
= NULL
;
166 __libc_lock_lock (lock
);
171 struct alias_map item
;
176 retval
= (struct alias_map
*) bsearch (&item
, map
, nmap
,
177 sizeof (struct alias_map
),
178 (int (*) PARAMS ((const void *,
184 /* We really found an alias. Return the value. */
187 result
= retval
->value
;
191 /* Perhaps we can find another alias file. */
193 while (added
== 0 && locale_alias_path
[0] != '\0')
197 while (locale_alias_path
[0] == ':')
199 start
= locale_alias_path
;
201 while (locale_alias_path
[0] != '\0' && locale_alias_path
[0] != ':')
204 if (start
< locale_alias_path
)
205 added
= read_alias_file (start
, locale_alias_path
- start
);
211 __libc_lock_unlock (lock
);
220 read_alias_file (fname
, fname_len
)
225 struct block_list
*block_list
= NULL
;
230 static const char aliasfile
[] = "/locale.alias";
232 full_fname
= (char *) alloca (fname_len
+ sizeof aliasfile
);
233 ADD_BLOCK (block_list
, full_fname
);
234 memcpy (full_fname
, fname
, fname_len
);
235 memcpy (&full_fname
[fname_len
], aliasfile
, sizeof aliasfile
);
237 fp
= fopen (full_fname
, "r");
240 FREE_BLOCKS (block_list
);
247 /* It is a reasonable approach to use a fix buffer here because
248 a) we are only interested in the first two fields
249 b) these fields must be usable as file names and so must not
257 if (fgets (buf
, BUFSIZ
, fp
) == NULL
)
262 /* Ignore leading white space. */
263 while (isspace (cp
[0]))
266 /* A leading '#' signals a comment line. */
267 if (cp
[0] != '\0' && cp
[0] != '#')
270 while (cp
[0] != '\0' && !isspace (cp
[0]))
272 /* Terminate alias name. */
276 /* Now look for the beginning of the value. */
277 while (isspace (cp
[0]))
287 while (cp
[0] != '\0' && !isspace (cp
[0]))
289 /* Terminate value. */
292 /* This has to be done to make the following test
293 for the end of line possible. We are looking for
294 the terminating '\n' which do not overwrite here. */
298 else if (cp
[0] != '\0')
302 extend_alias_table ();
304 alias_len
= strlen (alias
) + 1;
305 value_len
= strlen (value
) + 1;
307 if (string_space_act
+ alias_len
+ value_len
> string_space_max
)
309 /* Increase size of memory pool. */
310 size_t new_size
= (string_space_max
311 + (alias_len
+ value_len
> 1024
312 ? alias_len
+ value_len
: 1024));
313 char *new_pool
= (char *) realloc (string_space
, new_size
);
314 if (new_pool
== NULL
)
316 FREE_BLOCKS (block_list
);
319 string_space
= new_pool
;
320 string_space_max
= new_size
;
323 map
[nmap
].alias
= memcpy (&string_space
[string_space_act
],
325 string_space_act
+= alias_len
;
327 map
[nmap
].alias
= memcpy (&string_space
[string_space_act
],
329 string_space_act
+= value_len
;
336 /* Possibly not the whole line fits into the buffer. Ignore
337 the rest of the line. */
338 while (strchr (cp
, '\n') == NULL
)
341 if (fgets (buf
, BUFSIZ
, fp
) == NULL
)
342 /* Make sure the inner loop will be left. The outer loop
343 will exit at the `feof' test. */
348 /* Should we test for ferror()? I think we have to silently ignore
353 qsort (map
, nmap
, sizeof (struct alias_map
),
354 (int (*) PARAMS ((const void *, const void *))) alias_compare
);
356 FREE_BLOCKS (block_list
);
362 extend_alias_table ()
365 struct alias_map
*new_map
;
367 new_size
= maxmap
== 0 ? 100 : 2 * maxmap
;
368 new_map
= (struct alias_map
*) realloc (map
, (new_size
369 * sizeof (struct alias_map
)));
371 /* Simply don't extend: we don't have any more core. */
380 static void __attribute__ ((unused
))
383 if (string_space
!= NULL
)
388 text_set_element (__libc_subfreeres
, free_mem
);
393 alias_compare (map1
, map2
)
394 const struct alias_map
*map1
;
395 const struct alias_map
*map2
;
397 #if defined _LIBC || defined HAVE_STRCASECMP
398 return strcasecmp (map1
->alias
, map2
->alias
);
400 const unsigned char *p1
= (const unsigned char *) map1
->alias
;
401 const unsigned char *p2
= (const unsigned char *) map2
->alias
;
402 unsigned char c1
, c2
;
409 /* I know this seems to be odd but the tolower() function in
410 some systems libc cannot handle nonalpha characters. */
411 c1
= isupper (*p1
) ? tolower (*p1
) : *p1
;
412 c2
= isupper (*p2
) ? tolower (*p2
) : *p2
;