summaryrefslogtreecommitdiff
path: root/intl/localealias.c
diff options
context:
space:
mode:
Diffstat (limited to 'intl/localealias.c')
-rw-r--r--intl/localealias.c140
1 files changed, 93 insertions, 47 deletions
diff --git a/intl/localealias.c b/intl/localealias.c
index 00d91941b9..bca555a610 100644
--- a/intl/localealias.c
+++ b/intl/localealias.c
@@ -1,5 +1,5 @@
-/* Handle aliases for locale names
- Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+/* Handle aliases for locale names.
+ Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
This program is free software; you can redistribute it and/or modify
@@ -79,6 +79,14 @@ void free ();
because some ANSI C functions will require linking with this object
file and the name space must not be polluted. */
# define strcasecmp __strcasecmp
+
+# define mempcpy __mempcpy
+# define HAVE_MEMPCPY 1
+
+/* We need locking here since we can be called from different places. */
+# include <bits/libc-lock.h>
+
+__libc_lock_define_initialized (static, lock);
#endif
@@ -125,13 +133,17 @@ struct alias_map
};
+static char *string_space = NULL;
+static size_t string_space_act = 0;
+static size_t string_space_max = 0;
static struct alias_map *map;
static size_t nmap = 0;
static size_t maxmap = 0;
/* Prototypes for local functions. */
-static size_t read_alias_file PARAMS ((const char *fname, int fname_len));
+static size_t read_alias_file PARAMS ((const char *fname, int fname_len))
+ internal_function;
static void extend_alias_table PARAMS ((void));
static int alias_compare PARAMS ((const struct alias_map *map1,
const struct alias_map *map2));
@@ -143,8 +155,13 @@ _nl_expand_alias (name)
{
static const char *locale_alias_path = LOCALE_ALIAS_PATH;
struct alias_map *retval;
+ const char *result = NULL;
size_t added;
+#ifdef _LIBC
+ __libc_lock_lock (lock);
+#endif
+
do
{
struct alias_map item;
@@ -162,7 +179,10 @@ _nl_expand_alias (name)
/* We really found an alias. Return the value. */
if (retval != NULL)
- return retval->value;
+ {
+ result = retval->value;
+ break;
+ }
/* Perhaps we can find another alias file. */
added = 0;
@@ -183,11 +203,16 @@ _nl_expand_alias (name)
}
while (added != 0);
- return NULL;
+#ifdef _LIBC
+ __libc_lock_unlock (lock);
+#endif
+
+ return result;
}
static size_t
+internal_function
read_alias_file (fname, fname_len)
const char *fname;
int fname_len;
@@ -202,8 +227,13 @@ read_alias_file (fname, fname_len)
full_fname = (char *) alloca (fname_len + sizeof aliasfile);
ADD_BLOCK (block_list, full_fname);
+#ifdef HAVE_MEMPCPY
+ mempcpy (mempcpy (full_fname, fname, fname_len),
+ aliasfile, sizeof aliasfile);
+#else
memcpy (full_fname, fname, fname_len);
memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
+#endif
fp = fopen (full_fname, "r");
if (fp == NULL)
@@ -220,15 +250,28 @@ read_alias_file (fname, fname_len)
b) these fields must be usable as file names and so must not
be that long
*/
- char buf[BUFSIZ];
- char *alias;
- char *value;
- char *cp;
+ unsigned char buf[BUFSIZ];
+ unsigned char *alias;
+ unsigned char *value;
+ unsigned char *cp;
- if (fgets (buf, BUFSIZ, fp) == NULL)
+ if (fgets (buf, sizeof buf, fp) == NULL)
/* EOF reached. */
break;
+ /* Possibly not the whole line fits into the buffer. Ignore
+ the rest of the line. */
+ if (strchr (buf, '\n') == NULL)
+ {
+ char altbuf[BUFSIZ];
+ do
+ if (fgets (altbuf, sizeof altbuf, fp) == NULL)
+ /* Make sure the inner loop will be left. The outer loop
+ will exit at the `feof' test. */
+ break;
+ while (strchr (altbuf, '\n') == NULL);
+ }
+
cp = buf;
/* Ignore leading white space. */
while (isspace (cp[0]))
@@ -250,8 +293,8 @@ read_alias_file (fname, fname_len)
if (cp[0] != '\0')
{
- char *tp;
- size_t len;
+ size_t alias_len;
+ size_t value_len;
value = cp++;
while (cp[0] != '\0' && !isspace (cp[0]))
@@ -271,42 +314,37 @@ read_alias_file (fname, fname_len)
if (nmap >= maxmap)
extend_alias_table ();
- /* We cannot depend on strdup available in the libc. Sigh! */
- len = strlen (alias) + 1;
- tp = (char *) malloc (len);
- if (tp == NULL)
- {
- FREE_BLOCKS (block_list);
- return added;
- }
- memcpy (tp, alias, len);
- map[nmap].alias = tp;
+ alias_len = strlen (alias) + 1;
+ value_len = strlen (value) + 1;
- len = strlen (value) + 1;
- tp = (char *) malloc (len);
- if (tp == NULL)
+ if (string_space_act + alias_len + value_len > string_space_max)
{
- FREE_BLOCKS (block_list);
- return added;
+ /* Increase size of memory pool. */
+ size_t new_size = (string_space_max
+ + (alias_len + value_len > 1024
+ ? alias_len + value_len : 1024));
+ char *new_pool = (char *) realloc (string_space, new_size);
+ if (new_pool == NULL)
+ {
+ FREE_BLOCKS (block_list);
+ return added;
+ }
+ string_space = new_pool;
+ string_space_max = new_size;
}
- memcpy (tp, value, len);
- map[nmap].value = tp;
+
+ map[nmap].alias = memcpy (&string_space[string_space_act],
+ alias, alias_len);
+ string_space_act += alias_len;
+
+ map[nmap].value = memcpy (&string_space[string_space_act],
+ value, value_len);
+ string_space_act += value_len;
++nmap;
++added;
}
}
-
- /* Possibly not the whole line fits into the buffer. Ignore
- the rest of the line. */
- while (strchr (cp, '\n') == NULL)
- {
- cp = buf;
- if (fgets (buf, BUFSIZ, fp) == NULL)
- /* Make sure the inner loop will be left. The outer loop
- will exit at the `feof' test. */
- *cp = '\n';
- }
}
/* Should we test for ferror()? I think we have to silently ignore
@@ -329,22 +367,30 @@ extend_alias_table ()
struct alias_map *new_map;
new_size = maxmap == 0 ? 100 : 2 * maxmap;
- new_map = (struct alias_map *) malloc (new_size
- * sizeof (struct alias_map));
+ new_map = (struct alias_map *) realloc (map, (new_size
+ * sizeof (struct alias_map)));
if (new_map == NULL)
/* Simply don't extend: we don't have any more core. */
return;
- memcpy (new_map, map, nmap * sizeof (struct alias_map));
-
- if (maxmap != 0)
- free (map);
-
map = new_map;
maxmap = new_size;
}
+#ifdef _LIBC
+static void __attribute__ ((unused))
+free_mem (void)
+{
+ if (string_space != NULL)
+ free (string_space);
+ if (map != NULL)
+ free (map);
+}
+text_set_element (__libc_subfreeres, free_mem);
+#endif
+
+
static int
alias_compare (map1, map2)
const struct alias_map *map1;