+++ /dev/null
-/* Handle aliases for locale names.\r
- Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.\r
- Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.\r
-\r
- This program is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2, or (at your option)\r
- any later version.\r
-\r
- This program is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with this program; if not, write to the Free Software Foundation,\r
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. */\r
-\r
-#include "intlconfig.h"\r
-\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-#include <sys/types.h>\r
-\r
-#ifdef __GNUC__\r
-# define alloca __builtin_alloca\r
-# define HAVE_ALLOCA 1\r
-#else\r
-# if defined HAVE_ALLOCA_H || defined _LIBC\r
-# include <alloca.h>\r
-# else\r
-# ifdef _AIX\r
- #pragma alloca\r
-# else\r
-# ifndef alloca\r
-char *alloca ();\r
-# endif\r
-# endif\r
-# endif\r
-#endif\r
-\r
-#if defined STDC_HEADERS || defined _LIBC\r
-# include <stdlib.h>\r
-#else\r
-char *getenv ();\r
-# ifdef HAVE_MALLOC_H\r
-# include <malloc.h>\r
-# else\r
-void free ();\r
-# endif\r
-#endif\r
-\r
-#if defined HAVE_STRING_H || defined _LIBC\r
-# ifndef _GNU_SOURCE\r
-# define _GNU_SOURCE 1\r
-# endif\r
-# include <string.h>\r
-#else\r
-# include <strings.h>\r
-# ifndef memcpy\r
-# define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)\r
-# endif\r
-#endif\r
-#if !HAVE_STRCHR && !defined _LIBC\r
-# ifndef strchr\r
-# define strchr index\r
-# endif\r
-#endif\r
-\r
-#include "gettext.h"\r
-#include "gettextP.h"\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning (disable:4113)\r
-#endif\r
-\r
-/* @@ end of prolog @@ */\r
-\r
-#ifdef _LIBC\r
-/* Rename the non ANSI C functions. This is required by the standard\r
- because some ANSI C functions will require linking with this object\r
- file and the name space must not be polluted. */\r
-# define strcasecmp __strcasecmp\r
-\r
-# define mempcpy __mempcpy\r
-# define HAVE_MEMPCPY 1\r
-\r
-/* We need locking here since we can be called from different places. */\r
-# include <bits/libc-lock.h>\r
-\r
-__libc_lock_define_initialized (static, lock);\r
-#endif\r
-\r
-\r
-/* For those loosing systems which don't have `alloca' we have to add\r
- some additional code emulating it. */\r
-#ifdef HAVE_ALLOCA\r
-/* Nothing has to be done. */\r
-# define ADD_BLOCK(list, address) /* nothing */\r
-# define FREE_BLOCKS(list) /* nothing */\r
-#else\r
-struct block_list\r
-{\r
- void *address;\r
- struct block_list *next;\r
-};\r
-# define ADD_BLOCK(list, addr) \\r
- do { \\r
- struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \\r
- /* If we cannot get a free block we cannot add the new element to \\r
- the list. */ \\r
- if (newp != NULL) { \\r
- newp->address = (addr); \\r
- newp->next = (list); \\r
- (list) = newp; \\r
- } \\r
- } while (0)\r
-# define FREE_BLOCKS(list) \\r
- do { \\r
- while (list != NULL) { \\r
- struct block_list *old = list; \\r
- list = list->next; \\r
- free (old); \\r
- } \\r
- } while (0)\r
-# undef alloca\r
-# define alloca(size) (malloc (size))\r
-#endif /* have alloca */\r
-\r
-\r
-struct alias_map\r
-{\r
- const char *alias;\r
- const char *value;\r
-};\r
-\r
-\r
-static char *string_space = NULL;\r
-static size_t string_space_act = 0;\r
-static size_t string_space_max = 0;\r
-static struct alias_map *map;\r
-static size_t nmap = 0;\r
-static size_t maxmap = 0;\r
-\r
-\r
-/* Prototypes for local functions. */\r
-static size_t read_alias_file PARAMS ((const char *fname, int fname_len))\r
- internal_function;\r
-static void extend_alias_table PARAMS ((void));\r
-static int alias_compare PARAMS ((const struct alias_map *map1,\r
- const struct alias_map *map2));\r
-\r
-\r
-const char *\r
-_nl_expand_alias (name)\r
- const char *name;\r
-{\r
- static const char *locale_alias_path = LOCALE_ALIAS_PATH;\r
- struct alias_map *retval;\r
- const char *result = NULL;\r
- size_t added;\r
-\r
-#ifdef _LIBC\r
- __libc_lock_lock (lock);\r
-#endif\r
-\r
- do\r
- {\r
- struct alias_map item;\r
-\r
- item.alias = name;\r
-\r
- if (nmap > 0)\r
- retval = (struct alias_map *) bsearch (&item, map, nmap,\r
- sizeof (struct alias_map),\r
- (int (*) PARAMS ((const void *,\r
- const void *))\r
- ) alias_compare);\r
- else\r
- retval = NULL;\r
-\r
- /* We really found an alias. Return the value. */\r
- if (retval != NULL)\r
- {\r
- result = retval->value;\r
- break;\r
- }\r
-\r
- /* Perhaps we can find another alias file. */\r
- added = 0;\r
- while (added == 0 && locale_alias_path[0] != '\0')\r
- {\r
- const char *start;\r
-\r
- while (locale_alias_path[0] == ';')/*FRANCO changed : to ; for win32*/\r
- ++locale_alias_path;\r
- start = locale_alias_path;\r
-\r
- while (locale_alias_path[0] != '\0' && locale_alias_path[0] != ';')/*FRANCO changed : to ; for win32*/\r
- ++locale_alias_path;\r
-\r
- if (start < locale_alias_path)\r
- added = read_alias_file (start, locale_alias_path - start);\r
- }\r
- }\r
- while (added != 0);\r
-\r
-#ifdef _LIBC\r
- __libc_lock_unlock (lock);\r
-#endif\r
-\r
- return result;\r
-}\r
-\r
-\r
-static size_t\r
-internal_function\r
-read_alias_file (fname, fname_len)\r
- const char *fname;\r
- int fname_len;\r
-{\r
-#ifndef HAVE_ALLOCA\r
- struct block_list *block_list = NULL;\r
-#endif\r
- FILE *fp;\r
- char *full_fname;\r
- size_t added;\r
- static const char aliasfile[] = "/locale.alias";\r
-\r
- full_fname = (char *) alloca (fname_len + sizeof aliasfile);\r
- ADD_BLOCK (block_list, full_fname);\r
-#ifdef HAVE_MEMPCPY\r
- mempcpy (mempcpy (full_fname, fname, fname_len),\r
- aliasfile, sizeof aliasfile);\r
-#else\r
- memcpy (full_fname, fname, fname_len);\r
- memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);\r
-#endif\r
-\r
- fp = fopen (full_fname, "r");\r
- if (fp == NULL)\r
- {\r
- FREE_BLOCKS (block_list);\r
- return 0;\r
- }\r
-\r
- added = 0;\r
- while (!feof (fp))\r
- {\r
- /* It is a reasonable approach to use a fix buffer here because\r
- a) we are only interested in the first two fields\r
- b) these fields must be usable as file names and so must not\r
- be that long\r
- */\r
- unsigned char buf[BUFSIZ];\r
- unsigned char *alias;\r
- unsigned char *value;\r
- unsigned char *cp;\r
-\r
- if (fgets (buf, sizeof buf, fp) == NULL)\r
- /* EOF reached. */\r
- break;\r
-\r
- /* Possibly not the whole line fits into the buffer. Ignore\r
- the rest of the line. */\r
- if (strchr (buf, '\n') == NULL)\r
- {\r
- char altbuf[BUFSIZ];\r
- do\r
- if (fgets (altbuf, sizeof altbuf, fp) == NULL)\r
- /* Make sure the inner loop will be left. The outer loop\r
- will exit at the `feof' test. */\r
- break;\r
- while (strchr (altbuf, '\n') == NULL);\r
- }\r
-\r
- cp = buf;\r
- /* Ignore leading white space. */\r
- while (isspace (cp[0]))\r
- ++cp;\r
-\r
- /* A leading '#' signals a comment line. */\r
- if (cp[0] != '\0' && cp[0] != '#')\r
- {\r
- alias = cp++;\r
- while (cp[0] != '\0' && !isspace (cp[0]))\r
- ++cp;\r
- /* Terminate alias name. */\r
- if (cp[0] != '\0')\r
- *cp++ = '\0';\r
-\r
- /* Now look for the beginning of the value. */\r
- while (isspace (cp[0]))\r
- ++cp;\r
-\r
- if (cp[0] != '\0')\r
- {\r
- size_t alias_len;\r
- size_t value_len;\r
-\r
- value = cp++;\r
- while (cp[0] != '\0' && !isspace (cp[0]))\r
- ++cp;\r
- /* Terminate value. */\r
- if (cp[0] == '\n')\r
- {\r
- /* This has to be done to make the following test\r
- for the end of line possible. We are looking for\r
- the terminating '\n' which do not overwrite here. */\r
- *cp++ = '\0';\r
- *cp = '\n';\r
- }\r
- else if (cp[0] != '\0')\r
- *cp++ = '\0';\r
-\r
- if (nmap >= maxmap)\r
- extend_alias_table ();\r
-\r
- alias_len = strlen (alias) + 1;\r
- value_len = strlen (value) + 1;\r
-\r
- if (string_space_act + alias_len + value_len > string_space_max)\r
- {\r
- /* Increase size of memory pool. */\r
- size_t new_size = (string_space_max\r
- + (alias_len + value_len > 1024\r
- ? alias_len + value_len : 1024));\r
- char *new_pool = (char *) realloc (string_space, new_size);\r
- if (new_pool == NULL)\r
- {\r
- FREE_BLOCKS (block_list);\r
- return added;\r
- }\r
- string_space = new_pool;\r
- string_space_max = new_size;\r
- }\r
-\r
- map[nmap].alias = memcpy (&string_space[string_space_act],\r
- alias, alias_len);\r
- string_space_act += alias_len;\r
-\r
- map[nmap].value = memcpy (&string_space[string_space_act],\r
- value, value_len);\r
- string_space_act += value_len;\r
-\r
- ++nmap;\r
- ++added;\r
- }\r
- }\r
- }\r
-\r
- /* Should we test for ferror()? I think we have to silently ignore\r
- errors. --drepper */\r
- fclose (fp);\r
-\r
- if (added > 0)\r
- qsort (map, nmap, sizeof (struct alias_map),\r
- (int (*) PARAMS ((const void *, const void *))) alias_compare);\r
-\r
- FREE_BLOCKS (block_list);\r
- return added;\r
-}\r
-\r
-\r
-static void\r
-extend_alias_table ()\r
-{\r
- size_t new_size;\r
- struct alias_map *new_map;\r
-\r
- new_size = maxmap == 0 ? 100 : 2 * maxmap;\r
- new_map = (struct alias_map *) realloc (map, (new_size\r
- * sizeof (struct alias_map)));\r
- if (new_map == NULL)\r
- /* Simply don't extend: we don't have any more core. */\r
- return;\r
-\r
- map = new_map;\r
- maxmap = new_size;\r
-}\r
-\r
-\r
-#ifdef _LIBC\r
-static void __attribute__ ((unused))\r
-free_mem (void)\r
-{\r
- if (string_space != NULL)\r
- free (string_space);\r
- if (map != NULL)\r
- free (map);\r
-}\r
-text_set_element (__libc_subfreeres, free_mem);\r
-#endif\r
-\r
-\r
-static int\r
-alias_compare (map1, map2)\r
- const struct alias_map *map1;\r
- const struct alias_map *map2;\r
-{\r
-#if defined _LIBC || defined HAVE_STRCASECMP\r
- return strcasecmp (map1->alias, map2->alias);\r
-#else\r
- const unsigned char *p1 = (const unsigned char *) map1->alias;\r
- const unsigned char *p2 = (const unsigned char *) map2->alias;\r
- unsigned char c1, c2;\r
-\r
- if (p1 == p2)\r
- return 0;\r
-\r
- do\r
- {\r
- /* I know this seems to be odd but the tolower() function in\r
- some systems libc cannot handle nonalpha characters. */\r
- c1 = isupper (*p1) ? tolower (*p1) : *p1;\r
- c2 = isupper (*p2) ? tolower (*p2) : *p2;\r
- if (c1 == '\0')\r
- break;\r
- ++p1;\r
- ++p2;\r
- }\r
- while (c1 == c2);\r
-\r
- return c1 - c2;\r
-#endif\r
-}\r