diff options
Diffstat (limited to 'locale')
-rw-r--r-- | locale/C-collate.c | 1 | ||||
-rw-r--r-- | locale/C-ctype.c | 1 | ||||
-rw-r--r-- | locale/C-messages.c | 1 | ||||
-rw-r--r-- | locale/C-monetary.c | 1 | ||||
-rw-r--r-- | locale/C-numeric.c | 1 | ||||
-rw-r--r-- | locale/C-time.c | 1 | ||||
-rw-r--r-- | locale/Makefile | 2 | ||||
-rw-r--r-- | locale/findlocale.c | 192 | ||||
-rw-r--r-- | locale/lc-collate.c | 4 | ||||
-rw-r--r-- | locale/loadlocale.c | 194 | ||||
-rw-r--r-- | locale/localeinfo.h | 34 | ||||
-rw-r--r-- | locale/programs/charset.h | 2 | ||||
-rw-r--r-- | locale/programs/config.h | 1 | ||||
-rw-r--r-- | locale/programs/ld-collate.c | 51 | ||||
-rw-r--r-- | locale/programs/ld-ctype.c | 116 | ||||
-rw-r--r-- | locale/programs/ld-messages.c | 2 | ||||
-rw-r--r-- | locale/programs/ld-monetary.c | 2 | ||||
-rw-r--r-- | locale/programs/ld-numeric.c | 2 | ||||
-rw-r--r-- | locale/programs/ld-time.c | 2 | ||||
-rw-r--r-- | locale/programs/localedef.c | 48 | ||||
-rw-r--r-- | locale/setlocale.c | 450 | ||||
-rw-r--r-- | locale/weight.h | 4 |
22 files changed, 675 insertions, 437 deletions
diff --git a/locale/C-collate.c b/locale/C-collate.c index ec467fc8aa..3b89e4fbe8 100644 --- a/locale/C-collate.c +++ b/locale/C-collate.c @@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */ const struct locale_data _nl_C_LC_COLLATE = { + _nl_C_name, NULL, 0, /* no file mapped */ 0, }; diff --git a/locale/C-ctype.c b/locale/C-ctype.c index 95ac311570..ea990da8af 100644 --- a/locale/C-ctype.c +++ b/locale/C-ctype.c @@ -896,6 +896,7 @@ const char _nl_C_LC_CTYPE_width[256] = const struct locale_data _nl_C_LC_CTYPE = { + _nl_C_name, NULL, 0, /* no file mapped */ 13, { diff --git a/locale/C-messages.c b/locale/C-messages.c index b118c13f92..c6ce5b758d 100644 --- a/locale/C-messages.c +++ b/locale/C-messages.c @@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */ const struct locale_data _nl_C_LC_MESSAGES = { + _nl_C_name, NULL, 0, /* no file mapped */ 4, { diff --git a/locale/C-monetary.c b/locale/C-monetary.c index befb429106..b661a57493 100644 --- a/locale/C-monetary.c +++ b/locale/C-monetary.c @@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */ const struct locale_data _nl_C_LC_MONETARY = { + _nl_C_name, NULL, 0, /* no file mapped */ 15, { diff --git a/locale/C-numeric.c b/locale/C-numeric.c index feb20c81ce..6298f7000f 100644 --- a/locale/C-numeric.c +++ b/locale/C-numeric.c @@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */ const struct locale_data _nl_C_LC_NUMERIC = { + _nl_C_name, NULL, 0, /* no file mapped */ 3, { diff --git a/locale/C-time.c b/locale/C-time.c index 4bab361cc2..a595e6b251 100644 --- a/locale/C-time.c +++ b/locale/C-time.c @@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */ const struct locale_data _nl_C_LC_TIME = { + _nl_C_name, NULL, 0, /* no file mapped */ 45, { diff --git a/locale/Makefile b/locale/Makefile index 7399eda735..6b208b71a6 100644 --- a/locale/Makefile +++ b/locale/Makefile @@ -28,7 +28,7 @@ distribute = localeinfo.h categories.def \ charmap-kw.gperf charmap-kw.h locfile-token.h \ locfile-kw.gperf locfile-kw.h linereader.h \ locales.h locfile.h stringtrans.h -routines = setlocale loadlocale localeconv nl_langinfo +routines = setlocale findlocale loadlocale localeconv nl_langinfo categories = ctype messages monetary numeric time collate aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc others = localedef locale diff --git a/locale/findlocale.c b/locale/findlocale.c new file mode 100644 index 0000000000..35b1971aa9 --- /dev/null +++ b/locale/findlocale.c @@ -0,0 +1,192 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. +Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996. + +The GNU C Library 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 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include <locale.h> +#include <stdlib.h> +#include <string.h> + +#include "localeinfo.h" + + +/* Constant data defined in setlocale.c. */ +extern const struct locale_data *const _nl_C[]; + + +static inline char * +copy (const char *string) +{ + size_t len; + char *new; + len = strlen (string) + 1; + new = (char *) malloc (len); + return new != NULL ? memcpy (new, string, len) : NULL; +} + + +/* For each category we keep a list of records for the locale files + which are somehow addressed. */ +static struct loaded_l10nfile *locale_file_list[LC_ALL]; + + +const struct locale_data * +_nl_find_locale (const char *locale_path, size_t locale_path_len, + int category, char **name) +{ + int mask; + /* Name of the locale for this category. */ + char *loc_name; + const char *language; + const char *modifier; + const char *territory; + const char *codeset; + const char *normalized_codeset; + const char *special; + const char *sponsor; + const char *revision; + struct loaded_l10nfile *locale_file; + + if ((*name)[0] == '\0') + { + /* The user decides which locale to use by setting environment + variables. */ + *name = getenv ("LC_ALL"); + if (*name == NULL || (*name)[0] == '\0') + *name = getenv (_nl_category_names[category]); + if (*name == NULL || (*name)[0] == '\0') + *name = getenv ("LANG"); + if (*name == NULL || (*name)[0] == '\0') + *name = (char *) _nl_C_name; + } + + if (strcmp (*name, _nl_C_name) == 0 || strcmp (*name, "POSIX") == 0) + { + /* We need not load anything. The needed data is contained in + the library itself. */ + *name = (char *) _nl_C_name; + return _nl_C[category]; + } + + /* We really have to load some data. First see whether the name is + an alias. Please note that this makes it impossible to have "C" + or "POSIX" as aliases. */ + loc_name = _nl_expand_alias (*name); + if (loc_name == NULL) + /* It is no alias. */ + loc_name = *name; + + /* Make a writable copy of the locale name. */ + loc_name = copy (loc_name); + + /* LOCALE can consist of up to four recognized parts for the XPG syntax: + + language[_territory[.codeset]][@modifier] + + and six parts for the CEN syntax: + + language[_territory][+audience][+special][,sponsor][_revision] + + Beside the first all of them are allowed to be missing. If the + full specified locale is not found, the less specific one are + looked for. The various part will be stripped of according to + the following order: + (1) revision + (2) sponsor + (3) special + (4) codeset + (5) normalized codeset + (6) territory + (7) audience/modifier + */ + mask = _nl_explode_name (loc_name, &language, &modifier, &territory, + &codeset, &normalized_codeset, &special, + &sponsor, &revision); + + /* If exactly this locale was already asked for we have an entry with + the complete name. */ + locale_file = _nl_make_l10nflist (&locale_file_list[category], + locale_path, locale_path_len, mask, + language, territory, codeset, + normalized_codeset, modifier, special, + sponsor, revision, + _nl_category_names[category], 0); + + if (locale_file == NULL) + { + /* Find status record for addressed locale file. We have to search + through all directories in the locale path. */ + locale_file = _nl_make_l10nflist (&locale_file_list[category], + locale_path, locale_path_len, mask, + language, territory, codeset, + normalized_codeset, modifier, special, + sponsor, revision, + _nl_category_names[category], 1); + if (locale_file == NULL) + /* This means we are out of core. */ + return NULL; + } + else + /* If the addressed locale is already available it should be freed. + If we would not do this switching back and force between two + locales would slowly eat up all memory.*/ + free (loc_name); + + if (locale_file->decided == 0) + _nl_load_locale (locale_file, category); + + if (locale_file->data == NULL) + { + int cnt; + for (cnt = 0; locale_file->successor[cnt] != NULL; ++cnt) + { + if (locale_file->successor[cnt]->decided == 0) + _nl_load_locale (locale_file->successor[cnt], category); + if (locale_file->successor[cnt]->data != NULL) + break; + } + /* Move the entry we found (or NULL) to the first place of + successors. */ + locale_file->successor[0] = locale_file->successor[cnt]; + locale_file = locale_file->successor[cnt]; + } + + if (locale_file == NULL) + return NULL; + + /* Determine the locale name for which loading succeeded. This + information comes from the file name. The form is + <path>/<locale>/LC_foo. We must extract this <locale> part. */ + if (((struct locale_data *) locale_file->data)->name == NULL) + { + char *newp, *cp, *endp; + + endp = strrchr (locale_file->filename, '/'); + cp = endp - 1; + while (cp[-1] != '/') + --cp; + newp = (char *) malloc (endp - cp + 1); + if (newp == NULL) + return NULL; + memcpy (newp, cp, endp - cp); + newp[endp - cp] = '\0'; + ((struct locale_data *) locale_file->data)->name = newp; + } + *name = (char *) ((struct locale_data *) locale_file->data)->name; + + return (struct locale_data *) locale_file->data; +} diff --git a/locale/lc-collate.c b/locale/lc-collate.c index 911477b6bd..23643b29c8 100644 --- a/locale/lc-collate.c +++ b/locale/lc-collate.c @@ -22,8 +22,8 @@ Boston, MA 02111-1307, USA. */ _NL_CURRENT_DEFINE (LC_COLLATE); -const u32_t *__collate_table; -const u32_t *__collate_extra; +const u_int32_t *__collate_table; +const u_int32_t *__collate_extra; void diff --git a/locale/loadlocale.c b/locale/loadlocale.c index 68f9c7a48d..93b9e95593 100644 --- a/locale/loadlocale.c +++ b/locale/loadlocale.c @@ -1,6 +1,6 @@ -/* Functions to read locale data files. -Copyright (C) 1995, 1996 Free Software Foundation, Inc. +/* Copyright (C) 1996 Free Software Foundation, Inc. This file is part of the GNU C Library. +Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -14,20 +14,21 @@ Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ #include <errno.h> #include <fcntl.h> -#include <unistd.h> #include <stdlib.h> #include <string.h> -#include <stdio.h> -#include <sys/stat.h> +#include <unistd.h> #include <sys/mman.h> +#include <sys/stat.h> + #include "localeinfo.h" -const size_t _nl_category_num_items[] = + +static const size_t _nl_category_num_items[] = { #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \ [category] = _NL_ITEM_INDEX (_NL_NUM_##category), @@ -54,8 +55,8 @@ static const enum value_type *_nl_value_types[] = }; -struct locale_data * -_nl_load_locale (int category, char **name) +void +_nl_load_locale (struct loaded_l10nfile *file, int category) { int fd; struct @@ -66,7 +67,9 @@ _nl_load_locale (int category, char **name) } *filedata; struct stat st; struct locale_data *newdata; + int save_err; int swap = 0; + size_t cnt; inline unsigned int SWAP (const unsigned int *inw) { const unsigned char *inc = (const unsigned char *) inw; @@ -74,98 +77,86 @@ _nl_load_locale (int category, char **name) return *inw; return (inc[3] << 24) | (inc[2] << 16) | (inc[1] << 8) | inc[0]; } - unsigned int i; - if ((*name)[0] == '\0') + file->decided = 1; + file->data = NULL; + + fd = __open (file->filename, O_RDONLY); + if (fd < 0) + /* Cannot open the file. */ + return; + + if (__fstat (fd, &st) < 0) + goto puntfd; + if (S_ISDIR (st.st_mode)) { - *name = getenv ("LC_ALL"); - if (! *name || (*name)[0] == '\0') - *name = getenv (_nl_category_names[category]); - if (! *name || (*name)[0] == '\0') - *name = getenv ("LANG"); - if (! *name || (*name)[0] == '\0') - *name = (char *) "local"; + /* LOCALE/LC_foo is a directory; open LOCALE/LC_foo/SYS_LC_foo + instead. */ + char *newp; + + __close (fd); + + newp = (char *) alloca (strlen (file->filename) + + 5 + _nl_category_name_sizes[category] + 1); + __stpcpy (__stpcpy (__stpcpy (newp, file->filename), "/SYS_"), + _nl_category_names[category]); + + fd = __open (newp, O_RDONLY); + if (fd < 0) + return; + + if (__fstat (fd, &st) < 0) + goto puntfd; } - { - const char *catname = _nl_category_names[category]; - size_t namelen = strlen (*name); - size_t catlen = strlen (catname); - char file[sizeof LOCALE_PATH + 1 + namelen + catlen * 2 + 4]; - if (strchr (*name, '/') != NULL) - sprintf (file, "%s/%s", *name, catname); - else - sprintf (file, "%s/%s/%s", LOCALE_PATH, *name, catname); - fd = __open (file, O_RDONLY); - if (fd < 0) - return NULL; - if (__fstat (fd, &st) < 0) - goto puntfd; - if (S_ISDIR (st.st_mode)) - { - /* LOCALE/LC_foo is a directory; open LOCALE/LC_foo/SYS_LC_foo - instead. */ - __close (fd); - memcpy (stpcpy (strchr (file, '\0'), "SYS_"), catname, catlen); - fd = __open (file, O_RDONLY); - if (fd < 0) - return NULL; - if (__fstat (fd, &st) < 0) - goto puntfd; - } - } - - { - /* Map in the file's data. */ - int save = errno; + /* Map in the file's data. */ + save_err = errno; #ifndef MAP_COPY - /* Linux seems to lack read-only copy-on-write. */ + /* Linux seems to lack read-only copy-on-write. */ #define MAP_COPY MAP_PRIVATE #endif #ifndef MAP_FILE - /* Some systems do not have this flag; it is superfluous. */ + /* Some systems do not have this flag; it is superfluous. */ #define MAP_FILE 0 #endif #ifndef MAP_INHERIT - /* Some systems might lack this; they lose. */ + /* Some systems might lack this; they lose. */ #define MAP_INHERIT 0 #endif - filedata = (void *) __mmap ((caddr_t) 0, st.st_size, - PROT_READ, MAP_FILE|MAP_COPY|MAP_INHERIT, - fd, 0); - if (filedata == (void *) -1) - { - if (errno == ENOSYS) - { - /* No mmap; allocate a buffer and read from the file. */ - filedata = malloc (st.st_size); - if (filedata) - { - off_t to_read = st.st_size; - ssize_t nread; - char *p = (char *) filedata; - while (to_read > 0) - { - nread = __read (fd, p, to_read); - if (nread <= 0) - { - free (filedata); - if (nread == 0) - errno = EINVAL; /* Bizarreness going on. */ - goto puntfd; - } - p += nread; - to_read -= nread; - } - } - else - goto puntfd; - errno = save; - } - else - goto puntfd; - } - } + filedata = (void *) __mmap ((caddr_t) 0, st.st_size, PROT_READ, + MAP_FILE|MAP_COPY|MAP_INHERIT, fd, 0); + if (filedata == (void *) -1) + { + if (errno == ENOSYS) + { + /* No mmap; allocate a buffer and read from the file. */ + filedata = malloc (st.st_size); + if (filedata != NULL) + { + off_t to_read = st.st_size; + ssize_t nread; + char *p = (char *) filedata; + while (to_read > 0) + { + nread = __read (fd, p, to_read); + if (nread <= 0) + { + free (filedata); + if (nread == 0) + errno = EINVAL; /* Bizarreness going on. */ + goto puntfd; + } + p += nread; + to_read -= nread; + } + } + else + goto puntfd; + errno = save_err; + } + else + goto puntfd; + } if (filedata->magic == LIMAGIC (category)) /* Good data file in our byte order. */ @@ -181,7 +172,7 @@ _nl_load_locale (int category, char **name) __munmap ((caddr_t) filedata, st.st_size); puntfd: __close (fd); - return NULL; + return; } } @@ -201,41 +192,46 @@ _nl_load_locale (int category, char **name) if (! newdata) goto puntmap; + newdata->name = NULL; /* This will be filled if necessary in findlocale.c. */ newdata->filedata = (void *) filedata; newdata->filesize = st.st_size; newdata->nstrings = W (filedata->nstrings); - for (i = 0; i < newdata->nstrings; ++i) + for (cnt = 0; cnt < newdata->nstrings; ++cnt) { - unsigned int idx = W (filedata->strindex[i]); + off_t idx = W (filedata->strindex[cnt]); if (idx >= newdata->filesize) { free (newdata); errno = EINVAL; goto puntmap; } - if (_nl_value_types[category][i] == word) - newdata->values[i].word = W (*((u32_t *) (newdata->filedata + idx))); + if (_nl_value_types[category][cnt] == word) + newdata->values[cnt].word = W (*((u_int32_t *) (newdata->filedata + + idx))); else - newdata->values[i].string = newdata->filedata + idx; + newdata->values[cnt].string = newdata->filedata + idx; } __close (fd); - return newdata; + file->data = newdata; } void -_nl_free_locale (struct locale_data *data) +_nl_free_locale (const struct locale_data *data) { int save = errno; - if (! data) + if (data == NULL) /* Ignore a null pointer, like free does. */ return; + if (data->name != NULL) + free ((void *) data->name); if (__munmap ((caddr_t) data->filedata, data->filesize) < 0) { if (errno == ENOSYS) free ((void *) data->filedata); errno = save; } - free (data); + free ((void *) data); } + diff --git a/locale/localeinfo.h b/locale/localeinfo.h index a3049a51dd..ac14626dc0 100644 --- a/locale/localeinfo.h +++ b/locale/localeinfo.h @@ -24,17 +24,20 @@ Cambridge, MA 02139, USA. */ #include <langinfo.h> #include <sys/types.h> +#include "../intl/loadinfo.h" /* For loaded_l10nfile definition. */ + /* Magic number at the beginning of a locale data file for CATEGORY. */ #define LIMAGIC(category) (0x960316de ^ (category)) /* Two special weight constants for the collation data. */ -#define FORWARD_CHAR 0xfffffffd -#define ELLIPSIS_CHAR 0xfffffffe -#define IGNORE_CHAR 0xffffffff +#define FORWARD_CHAR ((wchar_t) 0xfffffffd) +#define ELLIPSIS_CHAR ((wchar_t) 0xfffffffe) +#define IGNORE_CHAR ((wchar_t) 0xffffffff) /* Structure describing locale data in core for a category. */ struct locale_data { + const char *name; const char *filedata; /* Region mapping the file data. */ off_t filesize; /* Size of the file (and the region). */ @@ -78,9 +81,13 @@ extern const struct locale_data *_nl_current_##category; #include "categories.def" #undef DEFINE_CATEGORY -extern const char *const _nl_category_names[LC_ALL]; +extern const char *const _nl_category_names[LC_ALL + 1]; +extern const size_t _nl_category_name_sizes[LC_ALL + 1]; extern const struct locale_data * *const _nl_current[LC_ALL]; +/* Name of the standard locale. */ +extern const char _nl_C_name[]; + /* Extract the current CATEGORY locale's string for ITEM. */ #define _NL_CURRENT(category, item) \ (_nl_current_##category->values[_NL_ITEM_INDEX (item)].string) @@ -96,18 +103,21 @@ extern const struct locale_data * *const _nl_current[LC_ALL]; /* Load the locale data for CATEGORY from the file specified by *NAME. If *NAME is "", use environment variables as specified by POSIX, - and fill in *NAME with the actual name used. */ -extern struct locale_data *_nl_load_locale (int category, char **name); + and fill in *NAME with the actual name used. The directories + listed in LOCALE_PATH are searched for the locale files. */ +extern const struct locale_data *_nl_find_locale (const char *locale_path, + size_t locale_path_len, + int category, char **name); -/* Free the locale data read in by a `_nl_load_locale' call. */ -extern void _nl_free_locale (struct locale_data *); +/* Try to load the file described by FILE. */ +extern void _nl_load_locale (struct loaded_l10nfile *file, int category); +/* Free the locale data read in by a `_nl_load_locale' call. */ +extern void _nl_free_locale (const struct locale_data *); -/* XXX For now. */ -typedef unsigned int u32_t; /* Global variables for LC_COLLATE category data. */ -extern const u32_t *__collate_table; -extern const u32_t *__collate_extra; +extern const u_int32_t *__collate_table; +extern const u_int32_t *__collate_extra; #endif /* localeinfo.h */ diff --git a/locale/programs/charset.h b/locale/programs/charset.h index 1e8819c662..2885bf1d1a 100644 --- a/locale/programs/charset.h +++ b/locale/programs/charset.h @@ -53,7 +53,7 @@ struct charset_t /* We need one value to mark the error case. Let's use 0xffffffff. I.e., it is placed in the last page of ISO 10646. For now only the first is used and we have plenty of room. */ -#define ILLEGAL_CHAR_VALUE 0xffffffffu +#define ILLEGAL_CHAR_VALUE ((wchar_t) 0xffffffffu) /* Prototypes for charmap handling functions. */ diff --git a/locale/programs/config.h b/locale/programs/config.h index 4aa406d755..6c67813f93 100644 --- a/locale/programs/config.h +++ b/locale/programs/config.h @@ -24,7 +24,6 @@ typedef int wint_t; -typedef unsigned short int u16_t; #include_next <config.h> diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c index 598b963fc0..6643ae85c8 100644 --- a/locale/programs/ld-collate.c +++ b/locale/programs/ld-collate.c @@ -253,7 +253,7 @@ collate_finish (struct localedef_t *locale, struct charset_t *charset) |* XXX We should test whether really an unspecified character *| |* exists before giving the message. *| \**************************************************************/ - u32_t weight; + u_int32_t weight; error (0, 0, _("no definition of `UNDEFINED'")); @@ -262,7 +262,7 @@ collate_finish (struct localedef_t *locale, struct charset_t *charset) for (cnt = 0; cnt < collate->nrules; ++cnt) { - u32_t one = 1; + u_int32_t one = 1; obstack_grow (&collate->element_mem, &one, sizeof (one)); } @@ -286,7 +286,7 @@ void collate_output (struct localedef_t *locale, const char *output_path) { struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate; - u32_t table_size, table_best, level_best, sum_best; + u_int32_t table_size, table_best, level_best, sum_best; void *last; element_t *pelem; wchar_t *name; @@ -294,11 +294,11 @@ collate_output (struct localedef_t *locale, const char *output_path) const size_t nelems = _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE); struct iovec iov[2 + nelems]; struct locale_file data; - u32_t idx[nelems]; + u_int32_t idx[nelems]; struct obstack non_simple; size_t cnt, entry_size; - u32_t undefined_offset = UINT_MAX; - u32_t *table, *extra, *table2, *extra2; + u_int32_t undefined_offset = UINT_MAX; + u_int32_t *table, *extra, *table2, *extra2; size_t extra_len; sum_best = UINT_MAX; @@ -352,12 +352,12 @@ Computing table size for collation information might take a while..."), iov[1].iov_len = sizeof (idx); iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_NRULES)].iov_base = &collate->nrules; - iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_NRULES)].iov_len = sizeof (u32_t); + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_NRULES)].iov_len = sizeof (u_int32_t); - table = (u32_t *) alloca (collate->nrules * sizeof (u32_t)); + table = (u_int32_t *) alloca (collate->nrules * sizeof (u_int32_t)); iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_RULES)].iov_base = table; iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_RULES)].iov_len - = collate->nrules * sizeof (u32_t); + = collate->nrules * sizeof (u_int32_t); /* Another trick here. Describing the collation method needs only a few bits (3, to be exact). But the binary file should be accessible by maschines with both endianesses and so we store both @@ -366,15 +366,16 @@ Computing table size for collation information might take a while..."), table[cnt] = collate->rules[cnt] | SWAPU32 (collate->rules[cnt]); iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_HASH_SIZE)].iov_base = &table_best; - iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_HASH_SIZE)].iov_len = sizeof (u32_t); + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_HASH_SIZE)].iov_len = sizeof (u_int32_t); iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_HASH_LAYERS)].iov_base = &level_best; - iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_HASH_LAYERS)].iov_len = sizeof (u32_t); + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_HASH_LAYERS)].iov_len + = sizeof (u_int32_t); entry_size = 1 + MAX (collate->nrules, 2); - table = (u32_t *) alloca (table_best * level_best * entry_size - * sizeof (table[0])); + table = (u_int32_t *) alloca (table_best * level_best * entry_size + * sizeof (table[0])); memset (table, '\0', table_best * level_best * entry_size * sizeof (table[0])); @@ -382,7 +383,7 @@ Computing table size for collation information might take a while..."), /* Macros for inserting in output table. */ #define ADD_VALUE(expr) \ do { \ - u32_t to_write = (u32_t) expr; \ + u_int32_t to_write = (u_int32_t) expr; \ obstack_grow (&non_simple, &to_write, sizeof (to_write)); \ } while (0) @@ -393,7 +394,7 @@ Computing table size for collation information might take a while..."), ADD_VALUE (len); \ \ wlen = wcslen (pelem->name); \ - obstack_grow (&non_simple, pelem->name, (wlen + 1) * sizeof (u32_t)); \ + obstack_grow (&non_simple, pelem->name, (wlen + 1) * sizeof (u_int32_t)); \ \ idx = collate->nrules; \ for (cnt = 0; cnt < collate->nrules; ++cnt) \ @@ -417,14 +418,14 @@ Computing table size for collation information might take a while..."), table[(level * table_best + slot) * entry_size + 1] \ = FORWARD_CHAR; \ table[(level * table_best + slot) * entry_size + 2] \ - = obstack_object_size (&non_simple) / sizeof (u32_t); \ + = obstack_object_size (&non_simple) / sizeof (u_int32_t); \ \ /* Here we have to construct the non-simple table entry. First \ compute the total length of this entry. */ \ for (runp = (pelem); runp != NULL; runp = runp->next) \ if (runp->ordering != NULL) \ { \ - u32_t value; \ + u_int32_t value; \ size_t cnt; \ \ value = 1 + wcslen (runp->name) + 1; \ @@ -513,7 +514,7 @@ Computing table size for collation information might take a while..."), { /* We have to fill in the information from the UNDEFINED entry. */ - table[cnt * entry_size] = (u32_t) cnt; + table[cnt * entry_size] = (u_int32_t) cnt; if (collate->undefined.ordering_len == collate->nrules) { @@ -593,18 +594,18 @@ Computing table size for collation information might take a while..."), /* Finish the extra block. */ extra_len = obstack_object_size (&non_simple); - extra = (u32_t *) obstack_finish (&non_simple); - assert ((extra_len % sizeof (u32_t)) == 0); + extra = (u_int32_t *) obstack_finish (&non_simple); + assert ((extra_len % sizeof (u_int32_t)) == 0); /* Now we have to build the two array for the other byte ordering. */ - table2 = (u32_t *) alloca (table_best * level_best * entry_size - * sizeof (table[0])); - extra2 = (u32_t *) alloca (extra_len); + table2 = (u_int32_t *) alloca (table_best * level_best * entry_size + * sizeof (table[0])); + extra2 = (u_int32_t *) alloca (extra_len); for (cnt = 0; cnt < table_best * level_best * entry_size; ++cnt) table2[cnt] = SWAPU32 (table[cnt]); - for (cnt = 0; cnt < extra_len / sizeof (u32_t); ++cnt) + for (cnt = 0; cnt < extra_len / sizeof (u_int32_t); ++cnt) extra2[cnt] = SWAPU32 (extra2[cnt]); /* Store table adresses and lengths. */ @@ -639,7 +640,7 @@ Computing table size for collation information might take a while..."), #endif iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_UNDEFINED)].iov_base = &undefined_offset; - iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_UNDEFINED)].iov_len = sizeof (u32_t); + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_UNDEFINED)].iov_len = sizeof (u_int32_t); /* Update idx array. */ idx[0] = iov[0].iov_len + iov[1].iov_len; diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c index 99e9ebe3fa..79e01ba69b 100644 --- a/locale/programs/ld-ctype.c +++ b/locale/programs/ld-ctype.c @@ -59,9 +59,9 @@ void *xrealloc (void *__ptr, size_t __n); /* To be compatible with former implementations we for now restrict the number of bits for character classes to 16. When compatibility is not necessary anymore increase the number to 32. */ -#define char_class_t u16_t +#define char_class_t u_int16_t #define CHAR_CLASS_TRANS SWAPU16 -#define char_class32_t u32_t +#define char_class32_t u_int32_t #define CHAR_CLASS32_TRANS SWAPU32 @@ -72,13 +72,13 @@ struct locale_ctype_t size_t charnames_max; size_t charnames_act; - /* We will allow up to 8 * sizeof(u32_t) - 1 character classes. */ -#define MAX_NR_CHARCLASS (8 * sizeof (u32_t) - 1) + /* We will allow up to 8 * sizeof(u_int32_t) - 1 character classes. */ +#define MAX_NR_CHARCLASS (8 * sizeof (u_int32_t) - 1) int nr_charclass; const char *classnames[MAX_NR_CHARCLASS]; unsigned long int current_class_mask; unsigned int last_class_char; - u32_t *class_collection; + u_int32_t *class_collection; size_t class_collection_max; size_t class_collection_act; unsigned long int class_done; @@ -87,7 +87,7 @@ struct locale_ctype_t increase it. But I doubt it will. --drepper@gnu */ #define MAX_NR_CHARMAP 16 const char *mapnames[MAX_NR_CHARMAP]; - u32_t *map_collection[MAX_NR_CHARMAP]; + u_int32_t *map_collection[MAX_NR_CHARMAP]; unsigned int map_collection_max[MAX_NR_CHARMAP]; unsigned int map_collection_act[MAX_NR_CHARMAP]; size_t map_collection_nr; @@ -97,16 +97,16 @@ struct locale_ctype_t int tolower_done; /* The arrays for the binary representation. */ - u32_t plane_size; - u32_t plane_cnt; + u_int32_t plane_size; + u_int32_t plane_cnt; char_class_t *ctype_b; char_class32_t *ctype32_b; - u32_t *names_el; - u32_t *names_eb; - u32_t **map_eb; - u32_t **map_el; - u32_t *class_name_ptr; - u32_t *map_name_ptr; + u_int32_t *names_el; + u_int32_t *names_eb; + u_int32_t **map_eb; + u_int32_t **map_el; + u_int32_t *class_name_ptr; + u_int32_t *map_name_ptr; unsigned char *width; }; @@ -117,8 +117,8 @@ static void ctype_class_newP (struct linereader *lr, static void ctype_map_newP (struct linereader *lr, struct locale_ctype_t *ctype, const char *name, struct charset_t *charset); -static u32_t *find_idx (struct locale_ctype_t *ctype, u32_t **table, - size_t *max, size_t *act, unsigned int idx); +static u_int32_t *find_idx (struct locale_ctype_t *ctype, u_int32_t **table, + size_t *max, size_t *act, unsigned int idx); static void set_class_defaults (struct locale_ctype_t *ctype, struct charset_t *charset); static void allocate_arrays (struct locale_ctype_t *ctype, @@ -167,8 +167,9 @@ ctype_startup (struct linereader *lr, struct localedef_t *locale, ctype_class_newP (lr, ctype, "alnum"); ctype->class_collection_max = charset->mb_cur_max == 1 ? 256 : 512; - ctype->class_collection = (u32_t *) xmalloc (sizeof (unsigned long int) - * ctype->class_collection_max); + ctype->class_collection + = (u_int32_t *) xmalloc (sizeof (unsigned long int) + * ctype->class_collection_max); memset (ctype->class_collection, '\0', sizeof (unsigned long int) * ctype->class_collection_max); ctype->class_collection_act = 256; @@ -348,7 +349,7 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset, struct iovec iov[2 + nelems + ctype->nr_charclass + ctype->map_collection_nr]; struct locale_file data; - u32_t idx[nelems]; + u_int32_t idx[nelems]; size_t elem, cnt, offset, total; @@ -397,20 +398,20 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset, CTYPE_DATA (_NL_CTYPE_TOUPPER_EB, ctype->map_eb[0], (ctype->plane_size * ctype->plane_cnt + 128) - * sizeof (u32_t)); + * sizeof (u_int32_t)); CTYPE_DATA (_NL_CTYPE_TOLOWER_EB, ctype->map_eb[1], (ctype->plane_size * ctype->plane_cnt + 128) - * sizeof (u32_t)); + * sizeof (u_int32_t)); CTYPE_DATA (_NL_CTYPE_TOUPPER_EL, ctype->map_el[0], (ctype->plane_size * ctype->plane_cnt + 128) - * sizeof (u32_t)); + * sizeof (u_int32_t)); CTYPE_DATA (_NL_CTYPE_TOLOWER_EL, ctype->map_el[1], (ctype->plane_size * ctype->plane_cnt + 128) - * sizeof (u32_t)); + * sizeof (u_int32_t)); CTYPE_DATA (_NL_CTYPE_CLASS32, ctype->ctype32_b, @@ -418,16 +419,16 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset, * sizeof (char_class32_t))); CTYPE_DATA (_NL_CTYPE_NAMES_EB, - ctype->names_eb, - ctype->plane_size * ctype->plane_cnt * sizeof (u32_t)); + ctype->names_eb, (ctype->plane_size * ctype->plane_cnt + * sizeof (u_int32_t))); CTYPE_DATA (_NL_CTYPE_NAMES_EL, - ctype->names_el, - ctype->plane_size * ctype->plane_cnt * sizeof (u32_t)); + ctype->names_el, (ctype->plane_size * ctype->plane_cnt + * sizeof (u_int32_t))); CTYPE_DATA (_NL_CTYPE_HASH_SIZE, - &ctype->plane_size, sizeof (u32_t)); + &ctype->plane_size, sizeof (u_int32_t)); CTYPE_DATA (_NL_CTYPE_HASH_LAYERS, - &ctype->plane_cnt, sizeof (u32_t)); + &ctype->plane_cnt, sizeof (u_int32_t)); case _NL_ITEM_INDEX (_NL_CTYPE_CLASS_NAMES): /* The class name array. */ @@ -485,7 +486,7 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset, iov[2 + elem + offset].iov_len = ((ctype->plane_size * ctype->plane_cnt + 128) - * sizeof (u32_t)); + * sizeof (u_int32_t)); if (elem + 1 < nelems) idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len; @@ -825,10 +826,10 @@ implementation limit: no more than %d character maps allowed"), else ctype->map_collection_max[cnt] = max_chars; - ctype->map_collection[cnt] = - (u32_t *) xmalloc (sizeof (u32_t) * ctype->map_collection_max[cnt]); + ctype->map_collection[cnt] = (u_int32_t *) + xmalloc (sizeof (u_int32_t) * ctype->map_collection_max[cnt]); memset (ctype->map_collection[cnt], '\0', - sizeof (u32_t) * ctype->map_collection_max[cnt]); + sizeof (u_int32_t) * ctype->map_collection_max[cnt]); ctype->map_collection_act[cnt] = 256; ++ctype->map_collection_nr; @@ -837,8 +838,8 @@ implementation limit: no more than %d character maps allowed"), /* We have to be prepared that TABLE, MAX, and ACT can be NULL. This is possible if we only want ot extend the name array. */ -static u32_t * -find_idx (struct locale_ctype_t *ctype, u32_t **table, size_t *max, +static u_int32_t * +find_idx (struct locale_ctype_t *ctype, u_int32_t **table, size_t *max, size_t *act, unsigned int idx) { size_t cnt; @@ -878,8 +879,9 @@ find_idx (struct locale_ctype_t *ctype, u32_t **table, size_t *max, while (*max <= cnt); *table = - (u32_t *) xrealloc (*table, *max * sizeof (unsigned long int)); - memset (&(*table)[old_max], '\0', (*max - old_max) * sizeof (u32_t)); + (u_int32_t *) xrealloc (*table, *max * sizeof (unsigned long int)); + memset (&(*table)[old_max], '\0', + (*max - old_max) * sizeof (u_int32_t)); } (*table)[cnt] = 0; @@ -1219,10 +1221,12 @@ Computing table size for character classes might take a while..."), # define NAMES_B2 ctype->names_el #endif - ctype->names_eb = (u32_t *) xcalloc (ctype->plane_size * ctype->plane_cnt, - sizeof (u32_t)); - ctype->names_el = (u32_t *) xcalloc (ctype->plane_size * ctype->plane_cnt, - sizeof (u32_t)); + ctype->names_eb = (u_int32_t *) xcalloc (ctype->plane_size + * ctype->plane_cnt, + sizeof (u_int32_t)); + ctype->names_el = (u_int32_t *) xcalloc (ctype->plane_size + * ctype->plane_cnt, + sizeof (u_int32_t)); for (idx = 1; idx < 256; ++idx) NAMES_B1[idx] = idx; @@ -1286,10 +1290,10 @@ Computing table size for character classes might take a while..."), = TRANS32 (ctype->class_collection[idx]); /* Room for table of mappings. */ - ctype->map_eb = (u32_t **) xmalloc (ctype->map_collection_nr - * sizeof (u32_t *)); - ctype->map_el = (u32_t **) xmalloc (ctype->map_collection_nr - * sizeof (u32_t *)); + ctype->map_eb = (u_int32_t **) xmalloc (ctype->map_collection_nr + * sizeof (u_int32_t *)); + ctype->map_el = (u_int32_t **) xmalloc (ctype->map_collection_nr + * sizeof (u_int32_t *)); /* Fill in all mappings. */ for (idx = 0; idx < ctype->map_collection_nr; ++idx) @@ -1297,12 +1301,12 @@ Computing table size for character classes might take a while..."), unsigned int idx2; /* Allocate table. */ - ctype->map_eb[idx] = (u32_t *) xmalloc ((ctype->plane_size - * ctype->plane_cnt + 128) - * sizeof (u32_t)); - ctype->map_el[idx] = (u32_t *) xmalloc ((ctype->plane_size - * ctype->plane_cnt + 128) - * sizeof (u32_t)); + ctype->map_eb[idx] = (u_int32_t *) xmalloc ((ctype->plane_size + * ctype->plane_cnt + 128) + * sizeof (u_int32_t)); + ctype->map_el[idx] = (u_int32_t *) xmalloc ((ctype->plane_size + * ctype->plane_cnt + 128) + * sizeof (u_int32_t)); #if __BYTE_ORDER == __LITTLE_ENDIAN # define MAP_B1 ctype->map_el @@ -1314,7 +1318,7 @@ Computing table size for character classes might take a while..."), /* Copy default value (identity mapping). */ memcpy (&MAP_B1[idx][128], NAMES_B1, - ctype->plane_size * ctype->plane_cnt * sizeof (u32_t)); + ctype->plane_size * ctype->plane_cnt * sizeof (u_int32_t)); /* Copy values from collection. */ for (idx2 = 0; idx2 < ctype->map_collection_act[idx]; ++idx2) @@ -1336,10 +1340,10 @@ Computing table size for character classes might take a while..."), } /* Extra array for class and map names. */ - ctype->class_name_ptr = (u32_t *) xmalloc (ctype->nr_charclass - * sizeof (u32_t)); - ctype->map_name_ptr = (u32_t *) xmalloc (ctype->map_collection_nr - * sizeof (u32_t)); + ctype->class_name_ptr = (u_int32_t *) xmalloc (ctype->nr_charclass + * sizeof (u_int32_t)); + ctype->map_name_ptr = (u_int32_t *) xmalloc (ctype->map_collection_nr + * sizeof (u_int32_t)); /* Array for width information. Because the expected width are very small we use only one single byte. This save space and we need diff --git a/locale/programs/ld-messages.c b/locale/programs/ld-messages.c index ebd5054b02..ede616768d 100644 --- a/locale/programs/ld-messages.c +++ b/locale/programs/ld-messages.c @@ -128,7 +128,7 @@ messages_output (struct localedef_t *locale, const char *output_path) = locale->categories[LC_MESSAGES].messages; struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES)]; struct locale_file data; - u32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES)]; + u_int32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES)]; size_t cnt = 0; if ((locale->binary & (1 << LC_MESSAGES)) != 0) diff --git a/locale/programs/ld-monetary.c b/locale/programs/ld-monetary.c index 18e27866fb..a717377a8b 100644 --- a/locale/programs/ld-monetary.c +++ b/locale/programs/ld-monetary.c @@ -182,7 +182,7 @@ monetary_output (struct localedef_t *locale, const char *output_path) = locale->categories[LC_MONETARY].monetary; struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)]; struct locale_file data; - u32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)]; + u_int32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)]; size_t cnt = 0; if ((locale->binary & (1 << LC_MONETARY)) != 0) diff --git a/locale/programs/ld-numeric.c b/locale/programs/ld-numeric.c index 0b5fe2afe5..dcee7bdb4e 100644 --- a/locale/programs/ld-numeric.c +++ b/locale/programs/ld-numeric.c @@ -102,7 +102,7 @@ numeric_output (struct localedef_t *locale, const char *output_path) struct locale_numeric_t *numeric = locale->categories[LC_NUMERIC].numeric; struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC)]; struct locale_file data; - u32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC)]; + u_int32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC)]; size_t cnt = 0; if ((locale->binary & (1 << LC_NUMERIC)) != 0) diff --git a/locale/programs/ld-time.c b/locale/programs/ld-time.c index 2587faccdc..e031b24edc 100644 --- a/locale/programs/ld-time.c +++ b/locale/programs/ld-time.c @@ -117,7 +117,7 @@ time_output (struct localedef_t *locale, const char *output_path) struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_TIME) + time->cur_num_alt_digits]; struct locale_file data; - u32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TIME)]; + u_int32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TIME)]; size_t cnt, last_idx, num; if ((locale->binary & (1 << LC_TIME)) != 0) diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c index 72eb2d36e2..e9fb6d57a6 100644 --- a/locale/programs/localedef.c +++ b/locale/programs/localedef.c @@ -1,6 +1,6 @@ /* Copyright (C) 1995, 1996 Free Software Foundation, Inc. This file is part of the GNU C Library. -Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>. +Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -36,6 +36,7 @@ Boston, MA 02111-1307, USA. */ #include "error.h" #include "charset.h" #include "locfile.h" +#include "../intl/loadinfo.h" /* Undefine the following line in the production version. */ /* #define NDEBUG 1 */ @@ -95,7 +96,7 @@ void *xmalloc (size_t __n); /* Prototypes for local functions. */ static void usage (int status) __attribute__ ((noreturn)); static void error_print (void); -static const char *construct_output_path (const char *path); +static const char *construct_output_path (char *path); int @@ -424,25 +425,50 @@ error_print () contain a '/' character it is a relativ path. Otherwise it names the locale this definition is for. */ static const char * -construct_output_path (const char *path) +construct_output_path (char *path) { + char *normal = NULL; char *result; if (strchr (path, '/') == NULL) { - /* This is a system path. */ - int path_max_len = pathconf (LOCALE_PATH, _PC_PATH_MAX) + 1; - result = (char *) xmalloc (path_max_len); + /* This is a system path. First examine whether the locale name + contains a reference to the codeset. This should be + normalized. */ + char *startp, *endp; + + startp = path; + /* We must be prepared for finding a CEN name or a location of + the introducing `.' where it is not possible anymore. */ + while (*startp != '\0' && *startp != '@' && *startp != '.' + && *startp != '+' && *startp != ',') + ++startp; + if (*startp == '.') + { + /* We found a codeset specification. Now find the end. */ + endp = ++startp; + while (*endp != '\0' && *endp != '@') + ++endp; + + if (endp > startp) + normal = _nl_normalize_codeset (startp, endp - startp); + } - snprintf (result, path_max_len, "%s/%s", LOCALE_PATH, path); + /* We put an additional '\0' at the end of the string because at + the end of the function we need another byte for the trailing + '/'. */ + if (normal == NULL) + asprintf (&result, "%s/%s\0", LOCALE_PATH, path); + else + asprintf (&result, "%s/%.*s%s%s\0", LOCALE_PATH, startp - path, path, + normal, endp); } else { - char *t; - /* This is a user path. */ + /* This is a user path. Please note the additional byte in the + memory allocation. */ result = xmalloc (strlen (path) + 2); - t = stpcpy (result, path); - *t = '\0'; + strcpy (result, path); } errno = 0; diff --git a/locale/setlocale.c b/locale/setlocale.c index 70ec6eba6e..c0d6fcdc4e 100644 --- a/locale/setlocale.c +++ b/locale/setlocale.c @@ -13,14 +13,17 @@ Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ +#include <alloca.h> +#include <argz.h> #include <errno.h> -#include <string.h> -#include <stdlib.h> #include <locale.h> -#include <langinfo.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + #include "localeinfo.h" /* For each category declare two external variables (with weak references): @@ -33,20 +36,19 @@ Cambridge, MA 02139, USA. */ #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \ extern const struct locale_data *_nl_current_##category; \ extern const struct locale_data _nl_C_##category; \ -/* XXX The linker is broken so we cannot do the weak symbols right just now. */ -/* weak_symbol (_nl_current_##category) weak_symbol (_nl_C_##category) */ +weak_symbol (_nl_current_##category) weak_symbol (_nl_C_##category) #include "categories.def" #undef DEFINE_CATEGORY /* Array indexed by category of pointers to _nl_current_CATEGORY slots. Elements are zero for categories whose data is never used. */ -const struct locale_data * *const _nl_current[] = -{ +static const struct locale_data * *const _nl_current[] = + { #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \ - [category] = &_nl_current_##category, + [category] = &_nl_current_##category, #include "categories.def" #undef DEFINE_CATEGORY -}; + }; /* Array indexed by category of pointers to _nl_C_CATEGORY slots. Elements are zero for categories whose data is never used. */ @@ -67,6 +69,7 @@ const char *const _nl_category_names[] = [category] = category_name, #include "categories.def" #undef DEFINE_CATEGORY + [LC_ALL] = "LC_ALL" }; /* An array of their lengths, for convenience. */ const size_t _nl_category_name_sizes[] = @@ -75,6 +78,7 @@ const size_t _nl_category_name_sizes[] = [category] = sizeof (category_name) - 1, #include "categories.def" #undef DEFINE_CATEGORY + [LC_ALL] = sizeof ("LC_ALL") - 1 }; @@ -98,256 +102,257 @@ void (*const _nl_category_postload[]) (void) = }; +/* Name of our standard locale. */ const char _nl_C_name[] = "C"; /* Name of current locale for each individual category. Each is malloc'd unless it is nl_C_name. */ -const char *_nl_current_names[] = +static const char *_nl_current_names[] = { #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \ - _nl_C_name, + [category] = _nl_C_name, #include "categories.def" #undef DEFINE_CATEGORY + [LC_ALL] = _nl_C_name /* For LC_ALL. */ }; -/* Composite LC_ALL name for current locale. - This is malloc'd unless it's _nl_C_name. */ -char *_nl_current_composite_name = (char *) _nl_C_name; -/* Switch to the locale called NAME in CATEGORY. Return a string - describing the locale. This string can be used as the NAME argument in - a later call. If NAME is NULL, don't switch locales, but return the - current one. If NAME is "", switch to a locale based on the environment - variables, as per POSIX. Return NULL on error. */ +/* Use this when we come along an error. */ +#define ERROR_RETURN \ + do { \ + errno = EINVAL; \ + return NULL; \ + } while (0) -char * -setlocale (int category, const char *name) + +static inline char * +clever_copy (const char *string) { - /* Return a malloc'd copy of STRING. */ - char *copy (const char *string) - { - size_t len = strlen (string) + 1; - char *new = malloc (len); - return new ? memcpy (new, string, len) : NULL; - } + size_t len; + char *new; + + if (strcmp (string, "C") == 0 || strcmp (string, "POSIX") == 0) + /* This return is dangerous because the returned string might be + placed in read-only memory. But everything should be set up to + handle this case. */ + return (char *) _nl_C_name; + + len = strlen (string) + 1; + new = (char *) malloc (len); + return new != NULL ? memcpy (new, string, len) : NULL; +} - /* Construct a new composite name. */ - char *new_composite_name (int category, char *newnames[LC_ALL]) - { - size_t lens[LC_ALL], cumlen = 0; - int i; - char *new, *p; - int same = 1; - - for (i = 0; i < LC_ALL; ++i) - { - char *name = (category == LC_ALL ? newnames[i] : - category == i ? newnames[0] : - (char *) _nl_current_names[i]); - lens[i] = strlen (name); - cumlen += _nl_category_name_sizes[i] + 1 + lens[i] + 1; - if (i > 0 && same && strcmp (name, newnames[0])) - same = 0; - } - - if (same) - { - /* All the categories use the same name. */ - new = malloc (lens[0] + 1); - if (! new) - { - if (!strcmp (newnames[0], "C") || !strcmp (newnames[0], "POSIX")) - return (char *) _nl_C_name; - return NULL; - } - memcpy (new, newnames[0], lens[0] + 1); - return new; - } - new = malloc (cumlen); - if (! new) - return NULL; - p = new; - for (i = 0; i < LC_ALL; ++i) - { - /* Add "CATEGORY=NAME;" to the string. */ - char *name = (category == LC_ALL ? newnames[i] : - category == i ? newnames[0] : - (char *) _nl_current_names[i]); - memcpy (p, _nl_category_names[i], _nl_category_name_sizes[i]); - p += _nl_category_name_sizes[i]; - *p++ = '='; - memcpy (p, name, lens[i]); - p += lens[i]; - *p++ = ';'; - } - p[-1] = '\0'; /* Clobber the last ';'. */ - return new; - } - /* Put COMPOSITE in _nl_current_composite_name and free the old value. */ - void setcomposite (char *composite) +/* Construct a new composite name. */ +static inline char * +new_composite_name (int category, char *newnames[LC_ALL]) +{ + size_t last_len; + size_t cumlen = 0; + int i; + char *new, *p; + int same = 1; + + for (i = 0; i < LC_ALL; ++i) { - char *old = _nl_current_composite_name; - _nl_current_composite_name = composite; - if (old != _nl_C_name) - free (old); + char *name = (category == LC_ALL ? newnames[i] : + category == i ? newnames[0] : + (char *) _nl_current_names[i]); + last_len = strlen (name); + cumlen += _nl_category_name_sizes[i] + 1 + last_len + 1; + if (i > 0 && same && strcmp (name, newnames[0]) != 0) + same = 0; } - /* Put NAME in _nl_current_names and free the old value. */ - void setname (int category, const char *name) + + if (same) { - const char *oldname = _nl_current_names[category]; - _nl_current_names[category] = name; - if (oldname != _nl_C_name) - free ((char *) oldname); + /* All the categories use the same name. */ + if (strcmp (newnames[0], "C") == 0 || strcmp (newnames[0], "POSIX") == 0) + return (char *) _nl_C_name; + + new = malloc (last_len + 1); + if (new == NULL) + return NULL; + + memcpy (new, newnames[0], last_len + 1); + return new; } - /* Put DATA in *_nl_current[CATEGORY] and free the old value. */ - void setdata (int category, struct locale_data *data) + + new = malloc (cumlen); + if (new == NULL) + return NULL; + p = new; + for (i = 0; i < LC_ALL; ++i) { - if (_nl_current[category]) - { - const struct locale_data *olddata = *_nl_current[category]; - *_nl_current[category] = data; - if (_nl_category_postload[category]) - (*_nl_category_postload[category]) (); - if (olddata != _nl_C[category]) - _nl_free_locale ((struct locale_data *) olddata); - } + /* Add "CATEGORY=NAME;" to the string. */ + char *name = (category == LC_ALL ? newnames[i] : + category == i ? newnames[0] : + (char *) _nl_current_names[i]); + p = __stpcpy (p, _nl_category_names[i]); + *p++ = '='; + p = __stpcpy (p, name); + *p++ = ';'; } + p[-1] = '\0'; /* Clobber the last ';'. */ + return new; +} - const char *current_name; - char *composite; - if (category < 0 || category > LC_ALL) +/* Put NAME in _nl_current_names. */ +static inline void +setname (int category, const char *name) +{ + if (_nl_current[category] == NULL + && _nl_current_names[category] != _nl_C_name) + free ((void *) _nl_current_names[category]); + + _nl_current_names[category] = name; +} + + +/* Put DATA in *_nl_current[CATEGORY]. */ +static inline void +setdata (int category, const struct locale_data *data) +{ + if (_nl_current[category] != NULL) { - errno = EINVAL; - return NULL; + *_nl_current[category] = data; + if (_nl_category_postload[category]) + (*_nl_category_postload[category]) (); } +} - if (category == LC_ALL) - current_name = _nl_current_composite_name; - else - current_name = _nl_current_names[category]; - if (name == NULL) - /* Return the name of the current locale. */ - return (char *) current_name; +char * +setlocale (int category, const char *locale) +{ + char *locpath_var; + char *locale_path; + size_t locale_path_len; + char *composite; - if (name == current_name) + /* Sanity check for CATEGORY argument. */ + if (category < 0 || category > LC_ALL) + ERROR_RETURN; + + /* Does user want name of current locale? */ + if (locale == NULL) + return (char *) _nl_current_names[category]; + + if (strcmp (locale, _nl_current_names[category]) == 0) /* Changing to the same thing. */ - return (char *) current_name; + return (char *) _nl_current_names[category]; + + /* We perhaps really have to load some data. So we determine the + path in which to look for the data now. But this environment + variable must only be used when the binary has no SUID or SGID + bit set. */ + locale_path = NULL; + locale_path_len = 0; + + locpath_var = getenv ("LOCPATH"); + if (locpath_var != NULL && locpath_var[0] != '\0' + && __getuid () == __geteuid () && __getgid () == __getegid ()) + if (__argz_create_sep (locpath_var, ':', + &locale_path, &locale_path_len) != 0) + return NULL; + if (__argz_append (&locale_path, &locale_path_len, + LOCALE_PATH, sizeof (LOCALE_PATH)) != 0) + return NULL; + if (category == LC_ALL) { - const size_t len = strlen (name) + 1; + /* The user wants to set all categories. The desired locales + for the individual categories can be selected by using a + composite locale name. This is a semi-colon separated list + of entries of the form `CATEGORY=VALUE'. */ char *newnames[LC_ALL]; - char *p; - struct locale_data *newdata[LC_ALL]; + const struct locale_data *newdata[LC_ALL]; /* Set all name pointers to the argument name. */ for (category = 0; category < LC_ALL; ++category) - newnames[category] = (char *) name; - - p = strchr (name, ';'); - if (p) + newnames[category] = (char *) locale; + + if (strchr (locale, ';') != NULL) { - /* This is a composite name. Make a local copy and split it up. */ - int i; - char *n = alloca (len); - memcpy (n, name, len); + /* This is a composite name. Make a copy and split it up. */ + char *np = strdupa (locale); + char *cp; + int cnt; - while ((p = strchr (n, '=')) != NULL) + while ((cp = strchr (np, '=')) != NULL) { - for (i = 0; i < LC_ALL; ++i) - if (_nl_category_name_sizes[i] == p - n && - !memcmp (_nl_category_names[i], n, p - n)) + for (cnt = 0; cnt < LC_ALL; ++cnt) + if (cp - np == _nl_category_name_sizes[cnt] + && memcmp (np, _nl_category_names[cnt], cp - np) == 0) break; - if (i == LC_ALL) - { - /* Bogus category name. */ - errno = EINVAL; - return NULL; - } - if (i < LC_ALL) + + if (cnt == LC_ALL) + /* Bogus category name. */ + ERROR_RETURN; + + /* Found the category this clause sets. */ + newnames[cnt] = ++cp; + cp = strchr (cp, ';'); + if (cp != NULL) { - /* Found the category this clause sets. */ - char *end = strchr (++p, ';'); - newnames[i] = p; - if (end) - { - /* Examine the next clause. */ - *end = '\0'; - n = end + 1; - } - else - /* This was the last clause. We are done. */ - break; + /* Examine the next clause. */ + *cp = '\0'; + np = cp + 1; } + else + /* This was the last clause. We are done. */ + break; } - for (i = 0; i < LC_ALL; ++i) - if (newnames[i] == name) + for (cnt = 0; cnt < LC_ALL; ++cnt) + if (newnames[cnt] == locale) /* The composite name did not specify all categories. */ - return NULL; + ERROR_RETURN; } /* Load the new data for each category. */ while (category-- > 0) /* Only actually load the data if anything will use it. */ - if (_nl_current[category]) + if (_nl_current[category] != NULL) { - newdata[category] = _nl_load_locale (category, + newdata[category] = _nl_find_locale (locale_path, locale_path_len, + category, &newnames[category]); - if (newdata[category]) - newnames[category] = copy (newnames[category]); - if (! newdata[category] || ! newnames[category]) + + if (newdata[category] == NULL) { - if (!strcmp (newnames[category], "C") || - !strcmp (newnames[category], "POSIX")) - { - /* Loading from a file failed, but this is a request - for the default locale. Use the built-in data. */ - if (! newdata[category]) - newdata[category] - = (struct locale_data *) _nl_C[category]; - newnames[category] = (char *) _nl_C_name; - } - else - { - /* Loading this part of the locale failed. - Abort the composite load. */ - abort_composite: - while (++category < LC_ALL) - { - if (_nl_current[category]) - _nl_free_locale (newdata[category]); - if (newnames[category] != _nl_C_name) - free (newnames[category]); - } - return NULL; - } + /* Loading this part of the locale failed. Abort the + composite load. */ + int save_errno; + abort_composite: + save_errno = errno; + + while (++category < LC_ALL) + if (_nl_current[category] != NULL) + _nl_free_locale (newdata[category]); + else + if (_nl_current[category] == NULL + && newnames[category] != _nl_C_name) + free (newnames[category]); + + errno = save_errno; + return NULL; } } else { /* The data is never used; just change the name. */ - newnames[category] = copy (newnames[category]); - if (! newnames[category]) - { - if (!strcmp (newnames[category], "C") || - !strcmp (newnames[category], "POSIX")) - newnames[category] = (char *) _nl_C_name; - else - { - while (++category < LC_ALL) - if (newnames[category] != _nl_C_name) - free (newnames[category]); - } - } + newnames[category] = clever_copy (newnames[category]); + if (newnames[category] == NULL) + goto abort_composite; } + /* Create new composite name. */ composite = new_composite_name (LC_ALL, newnames); - if (! composite) + if (composite == NULL) { category = -1; goto abort_composite; @@ -359,46 +364,45 @@ setlocale (int category, const char *name) setdata (category, newdata[category]); setname (category, newnames[category]); } - setcomposite (composite); + setname (LC_ALL, composite); return composite; } else { - char *newname = copy (name); - if (! newname) + const struct locale_data *newdata; + char *newname; + + if (_nl_current[category] != NULL) { - if (!strcmp (name, "C") || !strcmp (name, "POSIX")) - newname = (char *) _nl_C_name; - else + /* Only actually load the data if anything will use it. */ + newname = (char *) locale; + newdata = _nl_find_locale (locale_path, locale_path_len, category, + (char **) &newname); + if (newdata == NULL) return NULL; } + /* Create new composite name. */ composite = new_composite_name (category, &newname); - if (! composite) + if (composite == NULL) { - if (newname != _nl_C_name) - free (newname); + /* If anything went wrong free what we managed to allocate + so far. */ + int save_errno = errno; + + if (_nl_current[category] != NULL) + _nl_free_locale (newdata); + + errno = save_errno; return NULL; } - /* Only actually load the data if anything will use it. */ - if (_nl_current[category]) - { - struct locale_data *newdata = _nl_load_locale (category, - (char **) &name); - if (! newdata) - { - if (!strcmp (name, "C") || !strcmp (name, "POSIX")) - newdata = (struct locale_data *) _nl_C[category]; - else - return NULL; - } - setdata (category, newdata); - } + if (_nl_current[category] != NULL) + setdata (category, newdata); setname (category, newname); - setcomposite (composite); + setname (LC_ALL, composite); return newname; } diff --git a/locale/weight.h b/locale/weight.h index 128b63168d..904a154f82 100644 --- a/locale/weight.h +++ b/locale/weight.h @@ -35,7 +35,7 @@ typedef struct weight_t struct weight_t *next; struct data_pair { - size_t number; + int number; const u_int32_t *value; } data[0]; } weight_t; @@ -115,7 +115,7 @@ get_weight (const STRING_TYPE **str, weight_t *result) { size_t idx; - /* This is a comparison between a u32_t array (aka wchar_t) and + /* This is a comparison between a u_int32_t array (aka wchar_t) and an 8-bit string. */ for (idx = 0; __collate_extra[slot + 2 + idx] != 0; ++idx) if (__collate_extra[slot + 2 + idx] != (u_int32_t) str[idx]) |