X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=intl%2Flocalealias.c;h=456e41e37d7b06049ba7cca36b421a28a93736b0;hb=1dc8717737084b93af2cd212e84edbd2cce1046c;hp=64e8ca78fa9d34ea896d8614fb7d6fe0386e9d84;hpb=4944c86a9318bc5b5578ab145a95c116ffd2c9fd;p=pspp diff --git a/intl/localealias.c b/intl/localealias.c index 64e8ca78fa..456e41e37d 100644 --- a/intl/localealias.c +++ b/intl/localealias.c @@ -1,20 +1,27 @@ -/* Handle aliases for locale names - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - Written by Ulrich Drepper , 1995. +/* Handle aliases for locale names. + Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +/* Tell glibc's to provide a prototype for mempcpy(). + This must come before because may include + , and once has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif #ifdef HAVE_CONFIG_H # include @@ -22,6 +29,9 @@ #include #include +#if defined _LIBC || defined HAVE___FSETLOCKING +# include +#endif #include #ifdef __GNUC__ @@ -41,35 +51,9 @@ char *alloca (); # endif #endif -#if defined STDC_HEADERS || defined _LIBC -# include -#else -char *getenv (); -# ifdef HAVE_MALLOC_H -# include -# else -void free (); -# endif -#endif +#include +#include -#if defined HAVE_STRING_H || defined _LIBC -# ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -# endif -# include -#else -# include -# ifndef memcpy -# define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num) -# endif -#endif -#if !HAVE_STRCHR && !defined _LIBC -# ifndef strchr -# define strchr index -# endif -#endif - -#include "gettext.h" #include "gettextP.h" /* @@ end of prolog @@ */ @@ -79,43 +63,49 @@ 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 + +# ifndef mempcpy +# define mempcpy __mempcpy +# endif +# define HAVE_MEMPCPY 1 +# define HAVE___FSETLOCKING 1 + +/* We need locking here since we can be called from different places. */ +# include + +__libc_lock_define_initialized (static, lock); #endif +#ifndef internal_function +# define internal_function +#endif -/* For those loosing systems which don't have `alloca' we have to add +/* Some optimizations for glibc. */ +#ifdef _LIBC +# define FEOF(fp) feof_unlocked (fp) +# define FGETS(buf, n, fp) fgets_unlocked (buf, n, fp) +#else +# define FEOF(fp) feof (fp) +# define FGETS(buf, n, fp) fgets (buf, n, fp) +#endif + +/* For those losing systems which don't have `alloca' we have to add some additional code emulating it. */ #ifdef HAVE_ALLOCA -/* Nothing has to be done. */ -# define ADD_BLOCK(list, address) /* nothing */ -# define FREE_BLOCKS(list) /* nothing */ +# define freea(p) /* nothing */ #else -struct block_list -{ - void *address; - struct block_list *next; -}; -# define ADD_BLOCK(list, addr) \ - do { \ - struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \ - /* If we cannot get a free block we cannot add the new element to \ - the list. */ \ - if (newp != NULL) { \ - newp->address = (addr); \ - newp->next = (list); \ - (list) = newp; \ - } \ - } while (0) -# define FREE_BLOCKS(list) \ - do { \ - while (list != NULL) { \ - struct block_list *old = list; \ - list = list->next; \ - free (old); \ - } \ - } while (0) -# undef alloca -# define alloca(size) (malloc (size)) -#endif /* have alloca */ +# define alloca(n) malloc (n) +# define freea(p) free (p) +#endif + +#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED +# undef fgets +# define fgets(buf, len, s) fgets_unlocked (buf, len, s) +#endif +#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED +# undef feof +# define feof(s) feof_unlocked (s) +#endif struct alias_map @@ -125,14 +115,18 @@ struct alias_map }; +static char *string_space; +static size_t string_space_act; +static size_t string_space_max; static struct alias_map *map; -static size_t nmap = 0; -static size_t maxmap = 0; +static size_t nmap; +static size_t maxmap; /* Prototypes for local functions. */ -static size_t read_alias_file PARAMS ((const char *fname, int fname_len)); -static void extend_alias_table PARAMS ((void)); +static size_t read_alias_file PARAMS ((const char *fname, int fname_len)) + internal_function; +static int extend_alias_table PARAMS ((void)); static int alias_compare PARAMS ((const struct alias_map *map1, const struct alias_map *map2)); @@ -141,10 +135,18 @@ const char * _nl_expand_alias (name) const char *name; { - static const char *locale_alias_path = LOCALE_ALIAS_PATH; + static const char *locale_alias_path; struct alias_map *retval; + const char *result = NULL; size_t added; +#ifdef _LIBC + __libc_lock_lock (lock); +#endif + + if (locale_alias_path == NULL) + locale_alias_path = LOCALE_ALIAS_PATH; + do { struct alias_map item; @@ -162,7 +164,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; @@ -170,11 +175,12 @@ _nl_expand_alias (name) { const char *start; - while (locale_alias_path[0] == ':') + while (locale_alias_path[0] == PATH_SEPARATOR) ++locale_alias_path; start = locale_alias_path; - while (locale_alias_path[0] != '\0' && locale_alias_path[0] != ':') + while (locale_alias_path[0] != '\0' + && locale_alias_path[0] != PATH_SEPARATOR) ++locale_alias_path; if (start < locale_alias_path) @@ -183,37 +189,46 @@ _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; { -#ifndef HAVE_ALLOCA - struct block_list *block_list = NULL; -#endif FILE *fp; char *full_fname; size_t added; static const char aliasfile[] = "/locale.alias"; 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"); + freea (full_fname); if (fp == NULL) - { - FREE_BLOCKS (block_list); - return 0; - } + return 0; + +#ifdef HAVE___FSETLOCKING + /* No threads present. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); +#endif added = 0; - while (!feof (fp)) + while (!FEOF (fp)) { /* It is a reasonable approach to use a fix buffer here because a) we are only interested in the first two fields @@ -225,36 +240,49 @@ read_alias_file (fname, fname_len) char *value; 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])) + while (isspace ((unsigned char) cp[0])) ++cp; /* A leading '#' signals a comment line. */ if (cp[0] != '\0' && cp[0] != '#') { alias = cp++; - while (cp[0] != '\0' && !isspace (cp[0])) + while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) ++cp; /* Terminate alias name. */ if (cp[0] != '\0') *cp++ = '\0'; /* Now look for the beginning of the value. */ - while (isspace (cp[0])) + while (isspace ((unsigned char) cp[0])) ++cp; 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])) + while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) ++cp; /* Terminate value. */ if (cp[0] == '\n') @@ -269,44 +297,49 @@ read_alias_file (fname, fname_len) *cp++ = '\0'; 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); + if (__builtin_expect (extend_alias_table (), 0)) return added; - } - memcpy (tp, alias, len); - map[nmap].alias = tp; - len = strlen (value) + 1; - tp = (char *) malloc (len); - if (tp == NULL) + alias_len = strlen (alias) + 1; + value_len = strlen (value) + 1; + + 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) + return added; + + if (__builtin_expect (string_space != new_pool, 0)) + { + size_t i; + + for (i = 0; i < nmap; i++) + { + map[i].alias += new_pool - string_space; + map[i].value += new_pool - string_space; + } + } + + 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 @@ -317,34 +350,42 @@ read_alias_file (fname, fname_len) qsort (map, nmap, sizeof (struct alias_map), (int (*) PARAMS ((const void *, const void *))) alias_compare); - FREE_BLOCKS (block_list); return added; } -static void +static int extend_alias_table () { size_t new_size; 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); + return -1; map = new_map; maxmap = new_size; + return 0; } +#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;