X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=intl%2Flocalealias.c;h=26122a01189c4ab44d1abce3ad5d5edc22db0d0c;hp=f57d76442eb40a4bb50de90f2a590024cb86c89e;hb=99a84f88c0acee0c46e9525684b5187d4192168b;hpb=6833ce8bdca2d64e14485118f2a4417b7e1cb1b1 diff --git a/intl/localealias.c b/intl/localealias.c index f57d764..26122a0 100644 --- a/intl/localealias.c +++ b/intl/localealias.c @@ -1,5 +1,5 @@ /* Handle aliases for locale names. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1995-1999, 2000-2001, 2003, 2005 Free Software Foundation, Inc. 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 @@ -13,7 +13,7 @@ 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, + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Tell glibc's to provide a prototype for mempcpy(). @@ -29,36 +29,45 @@ #include #include +#if defined _LIBC || defined HAVE___FSETLOCKING +# include +#endif #include #ifdef __GNUC__ +# undef alloca # define alloca __builtin_alloca # define HAVE_ALLOCA 1 #else -# if defined HAVE_ALLOCA_H || defined _LIBC -# include +# ifdef _MSC_VER +# include +# define alloca _alloca # else -# ifdef _AIX - #pragma alloca +# if defined HAVE_ALLOCA_H || defined _LIBC +# include # else -# ifndef alloca +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca char *alloca (); +# endif # endif # endif # endif #endif #include - #include -#if !HAVE_STRCHR && !defined _LIBC -# ifndef strchr -# define strchr index -# endif -#endif #include "gettextP.h" +#if ENABLE_RELOCATABLE +# include "relocatable.h" +#else +# define relocate(pathname) (pathname) +#endif + /* @@ end of prolog @@ */ #ifdef _LIBC @@ -71,17 +80,29 @@ char *alloca (); # define mempcpy __mempcpy # endif # define HAVE_MEMPCPY 1 +# define HAVE___FSETLOCKING 1 +#endif -/* We need locking here since we can be called from different places. */ +/* Handle multi-threaded applications. */ +#ifdef _LIBC # include - -__libc_lock_define_initialized (static, lock); +#else +# include "lock.h" #endif #ifndef internal_function # define internal_function #endif +/* 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 @@ -91,16 +112,19 @@ __libc_lock_define_initialized (static, lock); # define freea(p) free (p) #endif -#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED +#if defined _LIBC_REENTRANT || HAVE_DECL_FGETS_UNLOCKED # undef fgets # define fgets(buf, len, s) fgets_unlocked (buf, len, s) #endif -#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED +#if defined _LIBC_REENTRANT || HAVE_DECL_FEOF_UNLOCKED # undef feof # define feof(s) feof_unlocked (s) #endif +__libc_lock_define_initialized (static, lock) + + struct alias_map { const char *alias; @@ -108,34 +132,38 @@ struct alias_map }; -static char *string_space; +#ifndef _LIBC +# define libc_freeres_ptr(decl) decl +#endif + +libc_freeres_ptr (static char *string_space); static size_t string_space_act; static size_t string_space_max; -static struct alias_map *map; +libc_freeres_ptr (static struct alias_map *map); 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 size_t read_alias_file (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)); +static int extend_alias_table (void); +static int alias_compare (const struct alias_map *map1, + const struct alias_map *map2); const char * -_nl_expand_alias (name) - const char *name; +_nl_expand_alias (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 { @@ -146,8 +174,8 @@ _nl_expand_alias (name) if (nmap > 0) retval = (struct alias_map *) bsearch (&item, map, nmap, sizeof (struct alias_map), - (int (*) PARAMS ((const void *, - const void *)) + (int (*) (const void *, + const void *) ) alias_compare); else retval = NULL; @@ -179,9 +207,7 @@ _nl_expand_alias (name) } while (added != 0); -#ifdef _LIBC __libc_lock_unlock (lock); -#endif return result; } @@ -189,9 +215,7 @@ _nl_expand_alias (name) static size_t internal_function -read_alias_file (fname, fname_len) - const char *fname; - int fname_len; +read_alias_file (const char *fname, int fname_len) { FILE *fp; char *full_fname; @@ -207,40 +231,44 @@ read_alias_file (fname, fname_len) memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile); #endif - fp = fopen (full_fname, "r"); +#ifdef _LIBC + /* Note the file is opened with cancellation in the I/O functions + disabled. */ + fp = fopen (relocate (full_fname), "rc"); +#else + fp = fopen (relocate (full_fname), "r"); +#endif freea (full_fname); if (fp == NULL) 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 b) these fields must be usable as file names and so must not be that long - */ - char buf[BUFSIZ]; + We avoid a multi-kilobyte buffer here since this would use up + stack space which we might not have if the program ran out of + memory. */ + char buf[400]; char *alias; char *value; char *cp; + int complete_line; - if (fgets (buf, sizeof buf, 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); - } + /* Determine whether the line is complete. */ + complete_line = strchr (buf, '\n') != NULL; cp = buf; /* Ignore leading white space. */ @@ -263,9 +291,6 @@ read_alias_file (fname, fname_len) if (cp[0] != '\0') { - size_t alias_len; - size_t value_len; - value = cp++; while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) ++cp; @@ -281,59 +306,82 @@ read_alias_file (fname, fname_len) else if (cp[0] != '\0') *cp++ = '\0'; - if (nmap >= maxmap) - if (__builtin_expect (extend_alias_table (), 0)) - return added; +#ifdef IN_LIBGLOCALE + /* glibc's locale.alias contains entries for ja_JP and ko_KR + that make it impossible to use a Japanese or Korean UTF-8 + locale under the name "ja_JP" or "ko_KR". Ignore these + entries. */ + if (strchr (alias, '_') == NULL) +#endif + { + size_t alias_len; + size_t value_len; - alias_len = strlen (alias) + 1; - value_len = strlen (value) + 1; + if (nmap >= maxmap) + if (__builtin_expect (extend_alias_table (), 0)) + goto out; - if (string_space_act + alias_len + value_len > string_space_max) - { - /* 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; + alias_len = strlen (alias) + 1; + value_len = strlen (value) + 1; - for (i = 0; i < nmap; i++) + if (string_space_act + alias_len + value_len > string_space_max) + { + /* 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) + goto out; + + if (__builtin_expect (string_space != new_pool, 0)) { - map[i].alias += new_pool - string_space; - map[i].value += new_pool - string_space; + 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; - } + string_space = new_pool; + string_space_max = new_size; + } - map[nmap].alias = memcpy (&string_space[string_space_act], - alias, alias_len); - string_space_act += alias_len; + 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; + map[nmap].value = memcpy (&string_space[string_space_act], + value, value_len); + string_space_act += value_len; - ++nmap; - ++added; + ++nmap; + ++added; + } } } + + /* Possibly not the whole line fits into the buffer. Ignore + the rest of the line. */ + if (! complete_line) + do + if (FGETS (buf, sizeof buf, fp) == NULL) + /* Make sure the inner loop will be left. The outer loop + will exit at the `feof' test. */ + break; + while (strchr (buf, '\n') == NULL); } + out: /* Should we test for ferror()? I think we have to silently ignore errors. --drepper */ fclose (fp); if (added > 0) qsort (map, nmap, sizeof (struct alias_map), - (int (*) PARAMS ((const void *, const void *))) alias_compare); + (int (*) (const void *, const void *)) alias_compare); return added; } @@ -358,23 +406,8 @@ extend_alias_table () } -#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; - const struct alias_map *map2; +alias_compare (const struct alias_map *map1, const struct alias_map *map2) { #if defined _LIBC || defined HAVE_STRCASECMP return strcasecmp (map1->alias, map2->alias);