diff options
68 files changed, 1684 insertions, 955 deletions
@@ -1,5 +1,134 @@ +Fri May 3 13:32:08 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + + * intl/Makefile (CPPFLAGS): Change $(nlsdir) to $(i18ndir) in + LOCALE_ALIAS_PATH. + +Fri May 3 03:14:02 1996 Ulrich Drepper <drepper@cygnus.com> + + * intl/Makefile (routines): Add l10nflist and explodename. + (distribute): Add loadinfo.h and locale.alias. + (install-others): New variable to install locale.alias. + + * intl/dcgettext.c, intl/finddomain.c, intl/gettextP.h, + intl/loadmsgcat.c: Adapt for upcoming gettext-0.10.13. Some code + is now shared with the locale implementation. + + * intl/explodename.c, intl/l10nflist.c, intl/loadinfo.h: New file. + Extracted from finddomain.c. This is also used in the locale + implementation. + + * intl/locale.alias: New file. Locale alias database compatible + with X Window System's locale alias file. Can now be used in + locale and gettext code. + + * libio/stdio.h: Add prototypes for asprint and vasprintf. + + * locale/C-collate.c, locale/C-ctype.c, locale/C-messages.c, + locale/C-monetary.c, locale/C-numeric.c, locale/C-time.c: Add new + field in structure with name of locale ("C" in this case). + + * locale/Makefile (routines): Add findlocale. + + * locale/findlocale.c: New file. Instead of trying to load the + directly described file we now try to be much smarter when this + fails. Use the same code as gettext does. + + * locale/loadlocale.c, locale/setlocale.c: Rewrite to know about + new loading scheme. + + * locale/localeinfo.h: Adapt prototypes and declarations for new + setlocale implementation. Remove definition of u32_t type. We + now use u_int32_t from <sys/types.h>. + + * locale/programs/charset.h (ILLEGAL_CHAR_VALUE): Provide type + with constant. + + * locale/programs/config.h, locale/lc-collate.c, + locale/localeinfo.h, locale/programs/ld-collate.c, + locale/programs/ld-ctype.c, locale/programs/ld-messages.c, + locale/programs/ld-monetary.c, locale/programs/ld-numeric.c, + locale/programs/ld-time.c, locale/weight.h, string/strcoll.c: + Change to use u_int32_t and u_int16_t. + + * locale/programs/localedef.c (construct_output_path): Change name + of output locale to contain normalized form of the character set + portion. + + * string/Makefile (routines): Add agrz-ctsep and argz-next. + (tests): Add tst-strlen. + + * string/argz-ctsep.c: New file. Implement reverse operation + from argz-stringify. + + * string/argz-next.c: Non-inline version of function from argz.h. + + * string/argz.h, string/envz.h: Make usable as global header file. + + * string/envz.c: Fix declarations to use size_t where prototypes + say so. + + * string/tst-strlen.c: New file. Another test for critical + situation in strlen implementations. + + * sysdeps/i386/i586/strlen.S: Fix bug with highest byte in word + being zero. + + * wctype/test_wctype.c: Fix controlling comparison after change to + 32 bit character class array. + +Fri May 3 12:53:12 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + + * sysdeps/unix/sysv/linux/sys/socket.h: Remove spurious doubled line. + +Thu May 2 22:50:52 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * sysdeps/unix/sysv/linux/getpriority.c: New file. + * sysdeps/unix/sysv/linux/syscalls.list: Add s_getpriority. + +Thu May 2 22:41:31 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * sysdeps/unix/sysv/linux/m68k/fpu_control.h (_FPU_DEFAULT): + Disable all exceptions. + +Thu May 2 22:33:14 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * sysdeps/m68k/fpu/e_acos.c, sysdeps/m68k/fpu/e_acosf.c, + sysdeps/m68k/fpu/e_fmod.c, sysdeps/m68k/fpu/e_fmodf.c, + sysdeps/m68k/fpu/isinfl.c, sysdeps/m68k/fpu/isnanl.c, + sysdeps/m68k/fpu/s_atan.c, sysdeps/m68k/fpu/s_atanf.c, + sysdeps/m68k/fpu/s_frexp.c, sysdeps/m68k/fpu/s_frexpf.c, + sysdeps/m68k/fpu/s_ilogb.c, sysdeps/m68k/fpu/s_ilogbf.c, + sysdeps/m68k/fpu/s_isinf.c, sysdeps/m68k/fpu/s_isinff.c, + sysdeps/m68k/fpu/s_ldexp.c, sysdeps/m68k/fpu/s_ldexpf.c, + sysdeps/m68k/fpu/s_modf.c, sysdeps/m68k/fpu/s_modff.c: Don't + define __NO_MATH_INLINES, which is already defined on command + line. + +Thu May 2 22:18:28 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * sysdeps/libm-ieee754/e_j0f.c (__ieee754_j0f, __ieee754_y0f): + Replace 0x80000000 by 0x48000000. + * sysdeps/libm-ieee754/e_j1f.c (__ieee754_j1f): Likewise. + +Thu May 2 21:30:33 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * sunrpc/svc_simple.c: Make global variable pl local to + registerrpc. + +Thu May 2 00:24:04 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * time/Makefile (tz-cflags): New variable. + (CFLAGS-tzfile.c): New variable. + (CFLAGS-zic.c): Add $(tz-cflags). + (tz-cc): Remove variable. + ($(objpfx)tzfile.o, $(objpfx)zic.o): Remove targets. + Wed May 1 09:10:04 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + * sysdeps/mach/hurd/getcwd.c: Jump out of both loops when we find a + name, instead of checking for reaching end of buffer, which happens + when the match is the last entry in the buffer. + * time/strftime.c: Use canonical autoconf nugget for time.h+sys/time.h include. diff --git a/intl/Makefile b/intl/Makefile index 159d1b1534..9d97088d4a 100644 --- a/intl/Makefile +++ b/intl/Makefile @@ -21,19 +21,26 @@ subdir = intl headers = libintl.h routines = bindtextdom dcgettext dgettext gettext \ - finddomain loadmsgcat localealias textdomain -distribute = gettext.h gettextP.h hash-string.h + finddomain loadmsgcat localealias textdomain \ + l10nflist explodename +distribute = gettext.h gettextP.h hash-string.h loadinfo.h locale.alias + +install-others = $(localedir)/locale.alias include ../Rules CPPFLAGS += -D'GNULOCALEDIR="$(localedir)"' \ - -D'LOCALE_ALIAS_PATH="$(localedir):$(nlsdir)"' + -D'LOCALE_ALIAS_PATH="$(localedir):$(i18ndir)"' + +$(localedir)/locale.alias: locale.alias + $(do-install) ifdef gettext-srcdir %.h:: ../gpl2lgpl.sed $(gettext-srcdir)/intl/%.glibc; $(copysrc) %.c:: ../gpl2lgpl.sed $(gettext-srcdir)/intl/%.c; $(copysrc) %.h:: ../gpl2lgpl.sed $(gettext-srcdir)/intl/%.h; $(copysrc) +locale.alias:: ../gpl2lgpl.sed $(gettext-srcdir)/misc/locale.alias; $(copysrc) define copysrc sed -f $^ > $@.new diff --git a/intl/dcgettext.c b/intl/dcgettext.c index 7d739d32c3..6c8963f720 100644 --- a/intl/dcgettext.c +++ b/intl/dcgettext.c @@ -1,8 +1,6 @@ /* dcgettext.c -- implementation of the dcgettext(3) function - Copyright (C) 1995 Free Software Foundation, Inc. - -This file is part of the GNU C Library. Its master source is NOT part of -the C library, however. The master source lives in /gd/gnu/lib. +Copyright (C) 1995, 1996 Free Software Foundation, Inc. +Written 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 @@ -16,8 +14,8 @@ 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. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -155,7 +153,7 @@ const char _nl_default_dirname[] = GNULOCALEDIR; struct binding *_nl_domain_bindings; /* Prototypes for local functions. */ -static char *find_msg PARAMS ((struct loaded_domain *domain, +static char *find_msg PARAMS ((struct loaded_l10nfile *domain_file, const char *msgid)); static const char *category_to_name PARAMS ((int category)); static const char *guess_category_value PARAMS ((int category, @@ -180,7 +178,7 @@ DCGETTEXT (domainname, msgid, category) const char *msgid; int category; { - struct loaded_domain *domain; + struct loaded_l10nfile *domain; struct binding *binding; const char *categoryname; const char *categoryvalue; @@ -355,18 +353,21 @@ weak_alias (__dcgettext, dcgettext); static char * -find_msg (domain, msgid) - struct loaded_domain *domain; +find_msg (domain_file, msgid) + struct loaded_l10nfile *domain_file; const char *msgid; { size_t top, act, bottom; + struct loaded_domain *domain; - if (domain->decided == 0) - _nl_load_domain (domain); + if (domain_file->decided == 0) + _nl_load_domain (domain_file); - if (domain->data == NULL) + if (domain_file->data == NULL) return NULL; + domain = (struct loaded_domain *) domain_file->data; + /* Locate the MSGID and its translation. */ if (domain->hash_size > 2 && domain->hash_tab != NULL) { @@ -439,7 +440,8 @@ find_msg (domain, msgid) /* Return string representation of locale CATEGORY. */ -static const char *category_to_name (category) +static const char * +category_to_name (category) int category; { const char *retval; diff --git a/intl/explodename.c b/intl/explodename.c new file mode 100644 index 0000000000..2fd8be014d --- /dev/null +++ b/intl/explodename.c @@ -0,0 +1,167 @@ +/* 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>, 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 +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 <stdlib.h> +#include <string.h> + +#include "loadinfo.h" + +int +_nl_explode_name (name, language, modifier, territory, codeset, + normalized_codeset, special, sponsor, revision) + char *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; +{ + enum { undecided, xpg, cen } syntax; + char *cp; + int mask; + + *modifier = NULL; + *territory = NULL; + *codeset = NULL; + *normalized_codeset = NULL; + *special = NULL; + *sponsor = NULL; + *revision = NULL; + + /* Now we determine the single parts of the locale name. First + look for the language. Termination symbols are `_' and `@' if + we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ + mask = 0; + syntax = undecided; + *language = cp = name; + while (cp[0] != '\0' && cp[0] != '_' && cp[0] != '@' + && cp[0] != '+' && cp[0] != ',') + ++cp; + + if (*language == cp) + /* This does not make sense: language has to be specified. Use + this entry as it is without exploding. Perhaps it is an alias. */ + cp = strchr (*language, '\0'); + else if (cp[0] == '_') + { + /* Next is the territory. */ + cp[0] = '\0'; + *territory = ++cp; + + while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@' + && cp[0] != '+' && cp[0] != ',' && cp[0] != '_') + ++cp; + + mask |= TERRITORY; + + if (cp[0] == '.') + { + /* Next is the codeset. */ + syntax = xpg; + cp[0] = '\0'; + *codeset = ++cp; + + while (cp[0] != '\0' && cp[0] != '@') + ++cp; + + mask |= XPG_CODESET; + + if (*codeset != cp && (*codeset)[0] != '\0') + { + *normalized_codeset = _nl_normalize_codeset (*codeset, + cp - *codeset); + if (strcmp (*codeset, *normalized_codeset) == 0) + free ((char *) *normalized_codeset); + else + mask |= XPG_NORM_CODESET; + } + } + } + + if (cp[0] == '@' || (syntax != xpg && cp[0] == '+')) + { + /* Next is the modifier. */ + syntax = cp[0] == '@' ? xpg : cen; + cp[0] = '\0'; + *modifier = ++cp; + + while (syntax == cen && cp[0] != '\0' && cp[0] != '+' + && cp[0] != ',' && cp[0] != '_') + ++cp; + + mask |= XPG_MODIFIER | CEN_AUDIENCE; + } + + if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_')) + { + syntax = cen; + + if (cp[0] == '+') + { + /* Next is special application (CEN syntax). */ + cp[0] = '\0'; + *special = ++cp; + + while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_') + ++cp; + + mask |= CEN_SPECIAL; + } + + if (cp[0] == ',') + { + /* Next is sponsor (CEN syntax). */ + cp[0] = '\0'; + *sponsor = ++cp; + + while (cp[0] != '\0' && cp[0] != '_') + ++cp; + + mask |= CEN_SPONSOR; + } + + if (cp[0] == '_') + { + /* Next is revision (CEN syntax). */ + cp[0] = '\0'; + *revision = ++cp; + + mask |= CEN_REVISION; + } + } + + /* For CEN sytnax values it might be important to have the + separator character in the file name, not for XPG syntax. */ + if (syntax == xpg) + { + if (*territory != NULL && (*territory)[0] == '\0') + mask &= ~TERRITORY; + + if (*codeset != NULL && (*codeset)[0] == '\0') + mask &= ~XPG_CODESET; + + if (*modifier != NULL && (*modifier)[0] == '\0') + mask &= ~XPG_MODIFIER; + } + + return mask; +} diff --git a/intl/finddomain.c b/intl/finddomain.c index 3ced26fa4b..bb4609e864 100644 --- a/intl/finddomain.c +++ b/intl/finddomain.c @@ -1,9 +1,6 @@ /* finddomain.c -- handle list of needed message catalogs - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. - -This file is part of the GNU C Library. Its master source is NOT part of -the C library, however. The master source lives in /gd/gnu/lib. +Copyright (C) 1995, 1996 Free Software Foundation, Inc. +Written 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 @@ -17,8 +14,8 @@ 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. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -71,39 +68,8 @@ void free (); # define stpcpy(dest, src) __stpcpy(dest, src) #endif -/* Encoding of locale name parts. */ -#define CEN_REVISION 1 -#define CEN_SPONSOR 2 -#define CEN_SPECIAL 4 -#define XPG_NORM_CODESET 8 -#define XPG_CODESET 16 -#define TERRITORY 32 -#define CEN_AUDIENCE 64 -#define XPG_MODIFIER 128 - -#define CEN_SPECIFIC (CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE) -#define XPG_SPECIFIC (XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER) - - /* List of already loaded domains. */ -static struct loaded_domain *_nl_loaded_domains; - -/* Prototypes for local functions. */ -static struct loaded_domain *make_entry_rec PARAMS ((const char *dirname, - int mask, - const char *language, - const char *territory, - const char *codeset, - const char *normalized_codeset, - const char *modifier, - const char *special, - const char *sponsor, - const char *revision, - const char *domainname, - int do_allocate)); - -/* Normalize name of selected codeset. */ -static const char *normalize_codeset PARAMS ((const char *codeset)); +static struct loaded_l10nfile *_nl_loaded_domains; /* Substitution for systems lacking this function in their C library. */ #if !_LIBC && !HAVE_STPCPY @@ -115,29 +81,25 @@ static char *stpcpy__ PARAMS ((char *dest, const char *src)); /* Return a data structure describing the message catalog described by the DOMAINNAME and CATEGORY parameters with respect to the currently established bindings. */ -struct loaded_domain * +struct loaded_l10nfile * _nl_find_domain (dirname, locale, domainname) const char *dirname; char *locale; const char *domainname; { - enum { undecided, xpg, cen } syntax; - struct loaded_domain *retval; + struct loaded_l10nfile *retval; const char *language; - const char *modifier = NULL; - const char *territory = NULL; - const char *codeset = NULL; - const char *normalized_codeset = NULL; - const char *special = NULL; - const char *sponsor = NULL; - const char *revision = NULL; - const char *alias_value = NULL; - char *cp; + const char *modifier; + const char *territory; + const char *codeset; + const char *normalized_codeset; + const char *special; + const char *sponsor; + const char *revision; + const char *alias_value; int mask; - /* CATEGORYVALUE now possibly contains a colon separated list of - locales. Each single locale can consist of up to four recognized - parts for the XPG syntax: + /* LOCALE can consist of up to four recognized parts for the XPG syntax: language[_territory[.codeset]][@modifier] @@ -160,15 +122,16 @@ _nl_find_domain (dirname, locale, domainname) /* If we have already tested for this locale entry there has to be one data set in the list of loaded domains. */ - retval = make_entry_rec (dirname, 0, locale, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, domainname, 0); + retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, + strlen (dirname) + 1, 0, locale, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, domainname, 0); if (retval != NULL) { /* We know something about this locale. */ int cnt; if (retval->decided == 0) - _nl_load_domain (retval); /* @@@ */ + _nl_load_domain (retval); if (retval->data != NULL) return retval; @@ -181,8 +144,6 @@ _nl_find_domain (dirname, locale, domainname) if (retval->successor[cnt]->data != NULL) break; } - - /* We really found some usable information. */ return cnt >= 0 ? retval : NULL; /* NOTREACHED */ } @@ -204,123 +165,16 @@ _nl_find_domain (dirname, locale, domainname) /* Now we determine the single parts of the locale name. First look for the language. Termination symbols are `_' and `@' if we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ - mask = 0; - syntax = undecided; - language = cp = locale; - while (cp[0] != '\0' && cp[0] != '_' && cp[0] != '@' - && cp[0] != '+' && cp[0] != ',') - ++cp; - - if (language == cp) - /* This does not make sense: language has to be specified. Use - this entry as it is without exploding. Perhaps it is an alias. */ - cp = strchr (language, '\0'); - else if (cp[0] == '_') - { - /* Next is the territory. */ - cp[0] = '\0'; - territory = ++cp; - - while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@' - && cp[0] != '+' && cp[0] != ',' && cp[0] != '_') - ++cp; - - mask |= TERRITORY; - - if (cp[0] == '.') - { - /* Next is the codeset. */ - syntax = xpg; - cp[0] = '\0'; - codeset = ++cp; - - while (cp[0] != '\0' && cp[0] != '@') - ++cp; - - mask |= XPG_CODESET; - - if (codeset != cp && codeset[0] != '\0') - { - normalized_codeset = normalize_codeset (codeset); - if (strcmp (codeset, normalized_codeset) == 0) - free ((char *) normalized_codeset); - else - mask |= XPG_NORM_CODESET; - } - } - } - - if (cp[0] == '@' || (syntax != xpg && cp[0] == '+')) - { - /* Next is the modifier. */ - syntax = cp[0] == '@' ? xpg : cen; - cp[0] = '\0'; - modifier = ++cp; - - while (syntax == cen && cp[0] != '\0' && cp[0] != '+' - && cp[0] != ',' && cp[0] != '_') - ++cp; - - mask |= XPG_MODIFIER | CEN_AUDIENCE; - } - - if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_')) - { - syntax = cen; - - if (cp[0] == '+') - { - /* Next is special application (CEN syntax). */ - cp[0] = '\0'; - special = ++cp; - - while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_') - ++cp; - - mask |= CEN_SPECIAL; - } - - if (cp[0] == ',') - { - /* Next is sponsor (CEN syntax). */ - cp[0] = '\0'; - sponsor = ++cp; - - while (cp[0] != '\0' && cp[0] != '_') - ++cp; - - mask |= CEN_SPONSOR; - } - - if (cp[0] == '_') - { - /* Next is revision (CEN syntax). */ - cp[0] = '\0'; - revision = ++cp; - - mask |= CEN_REVISION; - } - } - - /* For CEN sytnax values it might be important to have the - separator character in the file name, not for XPG syntax. */ - if (syntax == xpg) - { - if (territory != NULL && territory[0] == '\0') - mask &= ~TERRITORY; - - if (codeset != NULL && codeset[0] == '\0') - mask &= ~XPG_CODESET; - - if (modifier != NULL && modifier[0] == '\0') - mask &= ~XPG_MODIFIER; - } + mask = _nl_explode_name (locale, &language, &modifier, &territory, + &codeset, &normalized_codeset, &special, + &sponsor, &revision); /* Create all possible locale entries which might be interested in generalzation. */ - retval = make_entry_rec (dirname, mask, language, territory, codeset, - normalized_codeset, modifier, special, sponsor, - revision, domainname, 1); + retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, + strlen (dirname) + 1, mask, language, territory, + codeset, normalized_codeset, modifier, special, + sponsor, revision, domainname, 1); if (retval == NULL) /* This means we are out of core. */ return NULL; @@ -336,12 +190,7 @@ _nl_find_domain (dirname, locale, domainname) _nl_load_domain (retval->successor[cnt]); if (retval->successor[cnt]->data != NULL) break; - - /* Signal that locale is not available. */ - retval->successor[cnt] = NULL; } - if (retval->successor[cnt] == NULL) - retval = NULL; } /* The room for an alias was dynamically allocated. Free it now. */ @@ -351,215 +200,6 @@ _nl_find_domain (dirname, locale, domainname) return retval; } - -static struct loaded_domain * -make_entry_rec (dirname, mask, language, territory, codeset, - normalized_codeset, modifier, special, sponsor, revision, - domain, do_allocate) - const char *dirname; - int mask; - const char *language; - const char *territory; - const char *codeset; - const char *normalized_codeset; - const char *modifier; - const char *special; - const char *sponsor; - const char *revision; - const char *domain; - int do_allocate; -{ - char *filename = NULL; - struct loaded_domain *last = NULL; - struct loaded_domain *retval; - char *cp; - size_t entries; - int cnt; - - - /* Process the current entry described by the MASK only when it is - valid. Because the mask can have in the first call bits from - both syntaces set this is necessary to prevent constructing - illegal local names. */ - /* FIXME: Rewrite because test is necessary only in first round. */ - if ((mask & CEN_SPECIFIC) == 0 || (mask & XPG_SPECIFIC) == 0 - || ((mask & XPG_CODESET) != 0 && (mask & XPG_NORM_CODESET) != 0)) - { - /* Allocate room for the full file name. */ - filename = (char *) malloc (strlen (dirname) + 1 - + strlen (language) - + ((mask & TERRITORY) != 0 - ? strlen (territory) + 1 : 0) - + ((mask & XPG_CODESET) != 0 - ? strlen (codeset) + 1 : 0) - + ((mask & XPG_NORM_CODESET) != 0 - ? strlen (normalized_codeset) + 1 : 0) - + ((mask & XPG_MODIFIER) != 0 ? - strlen (modifier) + 1 : 0) - + ((mask & CEN_SPECIAL) != 0 - ? strlen (special) + 1 : 0) - + ((mask & CEN_SPONSOR) != 0 - ? strlen (sponsor) + 1 : 0) - + ((mask & CEN_REVISION) != 0 - ? strlen (revision) + 1 : 0) + 1 - + strlen (domain) + 1); - - if (filename == NULL) - return NULL; - - retval = NULL; - last = NULL; - - /* Construct file name. */ - cp = stpcpy (filename, dirname); - *cp++ = '/'; - cp = stpcpy (cp, language); - - if ((mask & TERRITORY) != 0) - { - *cp++ = '_'; - cp = stpcpy (cp, territory); - } - if ((mask & XPG_CODESET) != 0) - { - *cp++ = '.'; - cp = stpcpy (cp, codeset); - } - if ((mask & XPG_NORM_CODESET) != 0) - { - *cp++ = '.'; - cp = stpcpy (cp, normalized_codeset); - } - if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0) - { - /* This component can be part of both syntaces but has different - leading characters. For CEN we use `+', else `@'. */ - *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@'; - cp = stpcpy (cp, modifier); - } - if ((mask & CEN_SPECIAL) != 0) - { - *cp++ = '+'; - cp = stpcpy (cp, special); - } - if ((mask & CEN_SPONSOR) != 0) - { - *cp++ = ','; - cp = stpcpy (cp, sponsor); - } - if ((mask & CEN_REVISION) != 0) - { - *cp++ = '_'; - cp = stpcpy (cp, revision); - } - - *cp++ = '/'; - stpcpy (cp, domain); - - /* Look in list of already loaded domains whether it is already - available. */ - last = NULL; - for (retval = _nl_loaded_domains; retval != NULL; retval = retval->next) - if (retval->filename != NULL) - { - int compare = strcmp (retval->filename, filename); - if (compare == 0) - /* We found it! */ - break; - if (compare < 0) - { - /* It's not in the list. */ - retval = NULL; - break; - } - - last = retval; - } - - if (retval != NULL || do_allocate == 0) - { - free (filename); - return retval; - } - } - - retval = (struct loaded_domain *) malloc (sizeof (*retval)); - if (retval == NULL) - return NULL; - - retval->filename = filename; - retval->decided = 0; - - if (last == NULL) - { - retval->next = _nl_loaded_domains; - _nl_loaded_domains = retval; - } - else - { - retval->next = last->next; - last->next = retval; - } - - entries = 0; - for (cnt = 254; cnt >= 0; --cnt) - if (cnt < mask && (cnt & ~mask) == 0 - && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0) - && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0)) - retval->successor[entries++] = make_entry_rec (dirname, cnt, - language, territory, - codeset, - normalized_codeset, - modifier, special, - sponsor, revision, - domain, 1); - retval->successor[entries] = NULL; - - return retval; -} - - -static const char * -normalize_codeset (codeset) - const char *codeset; -{ - int len = 0; - int only_digit = 1; - const char *cp; - char *retval; - char *wp; - - for (cp = codeset; cp[0] != '\0'; ++cp) - if (isalnum (cp[0])) - { - ++len; - - if (isalpha (cp[0])) - only_digit = 0; - } - - retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1); - - if (retval != NULL) - { - if (only_digit) - wp = stpcpy (retval, "ISO"); - else - wp = retval; - - for (cp = codeset; cp[0] != '\0'; ++cp) - if (isalpha (cp[0])) - *wp++ = toupper (cp[0]); - else if (isdigit (cp[0])) - *wp++ = cp[0]; - - *wp = '\0'; - } - - return (const char *) retval; -} - - /* @@ begin of epilog @@ */ /* We don't want libintl.a to depend on any other library. So we diff --git a/intl/gettextP.h b/intl/gettextP.h index 34196a0859..c37adaba0f 100644 --- a/intl/gettextP.h +++ b/intl/gettextP.h @@ -1,8 +1,6 @@ /* gettextP.h -- header describing internals of gettext library - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - -This file is part of the GNU C Library. Its master source is NOT part of -the C library, however. The master source lives in /gd/gnu/lib. +Copyright (C) 1995, 1996 Free Software Foundation, Inc. +Written 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 @@ -16,12 +14,14 @@ 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. */ #ifndef _GETTEXTP_H #define _GETTEXTP_H +#include "loadinfo.h" + /* @@ end of prolog @@ */ #ifndef PARAMS @@ -49,12 +49,6 @@ SWAP (i) struct loaded_domain { - struct loaded_domain *next; - struct loaded_domain *successor[63]; - - const char *filename; - int decided; - const char *data; int must_swap; nls_uint32 nstrings; @@ -71,12 +65,10 @@ struct binding char *dirname; }; -struct loaded_domain *_nl_find_domain PARAMS ((const char *__dirname, - char *__locale, - const char *__domainname)); -void _nl_load_domain PARAMS ((struct loaded_domain *__domain)); - -const char *_nl_expand_alias PARAMS ((const char *__name)); +struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname, + char *__locale, + const char *__domainname)); +void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain)); /* @@ begin of epilog @@ */ diff --git a/intl/l10nflist.c b/intl/l10nflist.c new file mode 100644 index 0000000000..b0fdf51d73 --- /dev/null +++ b/intl/l10nflist.c @@ -0,0 +1,262 @@ +/* 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>, 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 +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 <argz.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +#include "loadinfo.h" + +/* Return number of bits set in X. */ +static int pop __P ((int x)); + +static inline int +pop (x) + int x; +{ + /* We assume that no more than 16 bits are used. */ + x = ((x & ~0x5555) >> 1) + (x & 0x5555); + x = ((x & ~0x3333) >> 2) + (x & 0x3333); + x = ((x >> 4) + x) & 0x0f0f; + x = ((x >> 8) + x) & 0xff; + + return x; +} + + +struct loaded_l10nfile * +_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language, + territory, codeset, normalized_codeset, modifier, special, + sponsor, revision, filename, do_allocate) + struct loaded_l10nfile **l10nfile_list; + const char *dirlist; + size_t dirlist_len; + int mask; + const char *language; + const char *territory; + const char *codeset; + const char *normalized_codeset; + const char *modifier; + const char *special; + const char *sponsor; + const char *revision; + const char *filename; + int do_allocate; +{ + char *abs_filename; + struct loaded_l10nfile *last = NULL; + struct loaded_l10nfile *retval; + char *cp; + size_t entries; + int cnt; + + /* Allocate room for the full file name. */ + abs_filename = (char *) malloc (dirlist_len + + strlen (language) + + ((mask & TERRITORY) != 0 + ? strlen (territory) + 1 : 0) + + ((mask & XPG_CODESET) != 0 + ? strlen (codeset) + 1 : 0) + + ((mask & XPG_NORM_CODESET) != 0 + ? strlen (normalized_codeset) + 1 : 0) + + (((mask & XPG_MODIFIER) != 0 + || (mask & CEN_AUDIENCE) != 0) ? + strlen (modifier) + 1 : 0) + + ((mask & CEN_SPECIAL) != 0 + ? strlen (special) + 1 : 0) + + ((mask & CEN_SPONSOR) != 0 + ? strlen (sponsor) + 1 : 0) + + ((mask & CEN_REVISION) != 0 + ? strlen (revision) + 1 : 0) + + 1 + strlen (filename) + 1); + + if (abs_filename == NULL) + return NULL; + + retval = NULL; + last = NULL; + + /* Construct file name. */ + memcpy (abs_filename, dirlist, dirlist_len); + __argz_stringify (abs_filename, dirlist_len, ':'); + cp = abs_filename + (dirlist_len - 1); + *cp++ = '/'; + cp = stpcpy (cp, language); + + if ((mask & TERRITORY) != 0) + { + *cp++ = '_'; + cp = stpcpy (cp, territory); + } + if ((mask & XPG_CODESET) != 0) + { + *cp++ = '.'; + cp = stpcpy (cp, codeset); + } + if ((mask & XPG_NORM_CODESET) != 0) + { + *cp++ = '.'; + cp = stpcpy (cp, normalized_codeset); + } + if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0) + { + /* This component can be part of both syntaces but has different + leading characters. For CEN we use `+', else `@'. */ + *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@'; + cp = stpcpy (cp, modifier); + } + if ((mask & CEN_SPECIAL) != 0) + { + *cp++ = '+'; + cp = stpcpy (cp, special); + } + if ((mask & CEN_SPONSOR) != 0) + { + *cp++ = ','; + cp = stpcpy (cp, sponsor); + } + if ((mask & CEN_REVISION) != 0) + { + *cp++ = '_'; + cp = stpcpy (cp, revision); + } + + *cp++ = '/'; + stpcpy (cp, filename); + + /* Look in list of already loaded domains whether it is already + available. */ + last = NULL; + for (retval = *l10nfile_list; retval != NULL; retval = retval->next) + if (retval->filename != NULL) + { + int compare = strcmp (retval->filename, abs_filename); + if (compare == 0) + /* We found it! */ + break; + if (compare < 0) + { + /* It's not in the list. */ + retval = NULL; + break; + } + + last = retval; + } + + if (retval != NULL || do_allocate == 0) + { + free (abs_filename); + return retval; + } + + retval = (struct loaded_l10nfile *) + malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len) + * (1 << pop (mask)) + * sizeof (struct loaded_l10nfile *))); + if (retval == NULL) + return NULL; + + retval->filename = abs_filename; + retval->decided = (__argz_count (dirlist, dirlist_len) != 1 + || ((mask & XPG_CODESET) != 0 + && (mask & XPG_NORM_CODESET) != 0)); + retval->data = NULL; + + if (last == NULL) + { + retval->next = *l10nfile_list; + *l10nfile_list = retval; + } + else + { + retval->next = last->next; + last->next = retval; + } + + entries = 0; + /* If the DIRLIST is a real list the RETVAL entry correcponds not to + a real file. So we have to use the DIRLIST separation machanism + of the inner loop. */ + cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask; + for (; cnt >= 0; --cnt) + if ((cnt & ~mask) == 0 + && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0) + && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0)) + { + /* Iterate over all elements of the DIRLIST. */ + char *dir = NULL; + + while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir)) + != NULL) + retval->successor[entries++] + = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt, + language, territory, codeset, + normalized_codeset, modifier, special, + sponsor, revision, filename, 1); + } + retval->successor[entries] = NULL; + + return retval; +} + +/* Normalize codeset name. There is no standard for the codeset + names. Normalization allows the user to use any of the common + names. */ +const char * +_nl_normalize_codeset (codeset, name_len) + const char *codeset; + size_t name_len; +{ + int len = 0; + int only_digit = 1; + char *retval; + char *wp; + size_t cnt; + + for (cnt = 0; cnt < name_len; ++cnt) + if (isalnum (codeset[cnt])) + { + ++len; + + if (isalpha (codeset[cnt])) + only_digit = 0; + } + + retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1); + + if (retval != NULL) + { + if (only_digit) + wp = stpcpy (retval, "ISO"); + else + wp = retval; + + for (cnt = 0; cnt < name_len; ++cnt) + if (isalpha (codeset[cnt])) + *wp++ = tolower (codeset[cnt]); + else if (isdigit (codeset[cnt])) + *wp++ = codeset[cnt]; + + *wp = '\0'; + } + + return (const char *) retval; +} diff --git a/intl/loadinfo.h b/intl/loadinfo.h new file mode 100644 index 0000000000..00aa1c9d85 --- /dev/null +++ b/intl/loadinfo.h @@ -0,0 +1,48 @@ +/* Encoding of locale name parts. */ +#define CEN_REVISION 1 +#define CEN_SPONSOR 2 +#define CEN_SPECIAL 4 +#define XPG_NORM_CODESET 8 +#define XPG_CODESET 16 +#define TERRITORY 32 +#define CEN_AUDIENCE 64 +#define XPG_MODIFIER 128 + +#define CEN_SPECIFIC (CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE) +#define XPG_SPECIFIC (XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER) + + +struct loaded_l10nfile +{ + const char *filename; + int decided; + + const void *data; + + struct loaded_l10nfile *next; + struct loaded_l10nfile *successor[1]; +}; + + +extern const char *_nl_normalize_codeset __P ((const char *codeset, + size_t name_len)); + +extern struct loaded_l10nfile * +_nl_make_l10nflist __P ((struct loaded_l10nfile **l10nfile_list, + const char *dirlist, size_t dirlist_len, int mask, + const char *language, const char *territory, + const char *codeset, const char *normalized_codeset, + const char *modifier, const char *special, + const char *sponsor, const char *revision, + const char *filename, int do_allocate)); + + +extern const char *_nl_expand_alias __P ((const char *name)); + +extern int _nl_explode_name __P ((char *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)); diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c index 0f5bfd5b9d..1daf72a09f 100644 --- a/intl/loadmsgcat.c +++ b/intl/loadmsgcat.c @@ -1,8 +1,6 @@ /* loadmsgcat.c -- load needed message catalogs - Copyright (C) 1995 Software Foundation, Inc. - -This file is part of the GNU C Library. Its master source is NOT part of -the C library, however. The master source lives in /gd/gnu/lib. +Copyright (C) 1995, 1996 Free Software Foundation, Inc. +Written 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 @@ -16,8 +14,8 @@ 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. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -65,8 +63,8 @@ int _nl_msg_cat_cntr; /* Load the message catalogs specified by FILENAME. If it is no valid message catalog do nothing. */ void -_nl_load_domain (domain) - struct loaded_domain *domain; +_nl_load_domain (domain_file) + struct loaded_l10nfile *domain_file; { int fd; struct stat st; @@ -75,19 +73,20 @@ _nl_load_domain (domain) || defined _LIBC int use_mmap = 0; #endif + struct loaded_domain *domain; - domain->decided = 1; - domain->data = NULL; + domain_file->decided = 1; + domain_file->data = NULL; /* If the record does not represent a valid locale the FILENAME might be NULL. This can happen when according to the given specification the locale file name is different for XPG and CEN syntax. */ - if (domain->filename == NULL) + if (domain_file->filename == NULL) return; /* Try to open the addressed file. */ - fd = open (domain->filename, O_RDONLY); + fd = open (domain_file->filename, O_RDONLY); if (fd == -1) return; @@ -160,6 +159,12 @@ _nl_load_domain (domain) return; } + domain_file->data + = (struct loaded_domain *) malloc (sizeof (struct loaded_domain *)); + if (domain->data == NULL) + return; + + domain = (struct loaded_domain *) domain_file->data; domain->data = (char *) data; domain->must_swap = data->magic != _MAGIC; @@ -185,11 +190,12 @@ _nl_load_domain (domain) else #endif free (data); - domain->data = NULL; + free (domain); + domain_file->data = NULL; return; } /* Show that one domain is changed. This might make some cached - translation invalid. */ + translations invalid. */ ++_nl_msg_cat_cntr; } diff --git a/intl/locale.alias b/intl/locale.alias new file mode 100644 index 0000000000..cf1f6eea83 --- /dev/null +++ b/intl/locale.alias @@ -0,0 +1,52 @@ +# Locale name alias data base +# Copyright (C) 1996 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) +# 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. + +# The format of this file is the same as for the corresponding file of +# the X Window System, which normally can be found in +# /usr/lib/X11/locale/locale.alias +# A single line contains two fields: an alias and a substitution value. +# All entries are case independent. + +# Note: This file is far from being complete. If you have a value for +# your own site which you think might be useful for others too, share it +# with the rest of us. Send it to bug-gnu-utils@prep.ai.mit.edu. + +czech cz_CZ.ISO-8859-2 +danish da_DK.ISO-8859-1 +dansk da_DK.ISO-8859-1 +deutsch de_DE.ISO-8859-1 +dutch nl_NL.ISO-8859-1 +finnish fi_FI.ISO-8859-1 +français fr_FR.ISO-8859-1 +french fr_FR.ISO-8859-1 +german de_DE.ISO-8859-1 +greek el_GR.ISO-8859-7 +hebrew iw_IL.ISO-8859-8 +hungarian hu_HU.ISO-8859-2 +icelandic is_IS.ISO-8859-1 +italian it_CH.ISO-8859-1 +japanese ja_JP.EUC +norwegian no_NO.ISO-8859-1 +polish pl_PL.ISO-8859-2 +portuguese pt_PT.ISO-8859-1 +rumanian ro_RO.ISO-8859-2 +russian ru_SU.ISO-8859-5 +slovak sk_SK.ISO-8859-2 +slovene sl_CS.ISO-8859-2 +spanish es_ES.ISO-8859-1 +swedish sv_SE.ISO-8859-1 +turkish tr_TR.ISO-8859-9 diff --git a/libio/stdio.h b/libio/stdio.h index 893e7bf3fe..e68b6ceeff 100644 --- a/libio/stdio.h +++ b/libio/stdio.h @@ -1,6 +1,6 @@ /* This is part of the iostream/stdio library, providing -*- C -*- I/O. Define ANSI C stdio on top of C++ iostreams. - Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -166,6 +166,9 @@ extern int snprintf __P ((char *, size_t, __const char *, ...)); extern int __snprintf __P ((char *, size_t, __const char *, ...)); extern int vsnprintf __P ((char *, size_t, __const char *, _G_va_list)); +extern int asprintf __P ((char **, const char *, ...)); +extern int vasprintf __P ((char **, const char *, _G_va_list)); + /* Open a stream that writes into a malloc'd buffer that is expanded as necessary. *BUFLOC and *SIZELOC are updated with the buffer's location and the number of characters written on fflush or fclose. */ 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]) diff --git a/string/Makefile b/string/Makefile index d90bf6f857..af371ed689 100644 --- a/string/Makefile +++ b/string/Makefile @@ -33,11 +33,11 @@ routines := strcat strchr strcmp strcoll strcpy strcspn strdup \ strcasecmp strncase \ memccpy memcpy wordcopy strsep \ swab strfry memfrob memmem \ - $(addprefix argz-,append count create \ + $(addprefix argz-,append count create ctsep next \ delete extract insert stringify) \ envz -tests := tester testcopy test-ffs +tests := tester testcopy test-ffs tst-strlen distribute := memcopy.h pagecopy.h diff --git a/string/argz-ctsep.c b/string/argz-ctsep.c new file mode 100644 index 0000000000..9560591cb3 --- /dev/null +++ b/string/argz-ctsep.c @@ -0,0 +1,60 @@ +/* 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 <argz.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + + +error_t +__argz_create_sep (const char *string, int delim, char **argz, size_t *len) +{ + size_t nlen = strlen (string) + 1; + + if (nlen != 0) + { + const char *rp; + char *wp; + + *argz = (char *) malloc (nlen); + if (*argz == NULL) + return ENOMEM; + + rp = string; + wp = *argz; + do + if (*rp == delim) + { + if (wp > *argz && wp[-1] != '\0') + *wp++ = '\0'; + else + --nlen; + } + else + *wp++ = *rp; + while (*rp++ != '\0'); + } + if (nlen == 0) + *argz = NULL; + *len = nlen; + + return 0; +} +weak_alias (__argz_create_sep, argz_create_sep) diff --git a/string/argz-next.c b/string/argz-next.c new file mode 100644 index 0000000000..6149c7ee51 --- /dev/null +++ b/string/argz-next.c @@ -0,0 +1,39 @@ +/* Iterate through the elements of an argz block. + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + 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) 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <argz.h> +#include <string.h> + +char * +__argz_next (char *argz, size_t argz_len, const char *entry) +{ + if (entry) + { + if (entry < argz + argz_len) + entry = strchr (entry, '\0') + 1; + + return entry >= argz + argz_len ? NULL : entry; + } + else + if (argz_len > 0) + return argz; + else + return NULL; +} +weak_alias (__argz_next, argz_next) diff --git a/string/argz.h b/string/argz.h index 9c03815915..733d06cca8 100644 --- a/string/argz.h +++ b/string/argz.h @@ -20,42 +20,59 @@ #ifndef __ARGZ_H__ #define __ARGZ_H__ 1 + +#include <features.h> + #include <errno.h> /* Define error_t. */ #include <string.h> /* Need size_t, and strchr is called below. */ + +__BEGIN_DECLS + /* Make a '\0' separated arg vector from a unix argv vector, returning it in ARGZ, and the total length in LEN. If a memory allocation error occurs, ENOMEM is returned, otherwise 0. The result can be destroyed using free. */ -error_t __argz_create (char **argv, char **argz, size_t *len); -error_t argz_create (char **argv, char **argz, size_t *len); +error_t __argz_create __P ((char **__argv, char **__argz, size_t *__len)); +error_t argz_create __P ((char **__argv, char **__argz, size_t *__len)); + +/* Make a '\0' separated arg vector from a SEP separated list in + STRING, returning it in ARGZ, and the total length in LEN. If a + memory allocation error occurs, ENOMEM is returned, otherwise 0. + The result can be destroyed using free. */ +error_t __argz_create_sep __P ((__const char *__string, int __sep, + char **__argz, size_t *__len)); +error_t argz_create_sep __P ((__const char *__string, int __sep, + char **__argz, size_t *__len)); /* Returns the number of strings in ARGZ. */ -size_t __argz_count (const char *argz, size_t len); -size_t argz_count (const char *argz, size_t len); +size_t __argz_count __P ((__const char *__argz, size_t __len)); +size_t argz_count __P ((__const char *__argz, size_t __len)); /* Puts pointers to each string in ARGZ into ARGV, which must be large enough to hold them all. */ -void __argz_extract (const char *argz, size_t len, char **argv); -void argz_extract (const char *argz, size_t len, char **argv); +void __argz_extract __P ((__const char *__argz, size_t __len, char **__argv)); +void argz_extract __P ((__const char *__argz, size_t __len, char **__argv)); /* Make '\0' separated arg vector ARGZ printable by converting all the '\0's except the last into the character SEP. */ -void __argz_stringify (char *argz, size_t len, int sep); -void argz_stringify (char *argz, size_t len, int sep); +void __argz_stringify __P ((char *__argz, size_t __len, int __sep)); +void argz_stringify __P ((char *__argz, size_t __len, int __sep)); /* Append BUF, of length BUF_LEN to the argz vector in ARGZ & ARGZ_LEN. */ -error_t __argz_append (char **argz, size_t *argz_len, - const char *buf, size_t buf_len); -error_t argz_append (char **argz, size_t *argz_len, - const char *buf, size_t buf_len); +error_t __argz_append __P ((char **__argz, size_t *__argz_len, + __const char *__buf, size_t __buf_len)); +error_t argz_append __P ((char **__argz, size_t *__argz_len, + __const char *__buf, size_t __buf_len)); /* Append STR to the argz vector in ARGZ & ARGZ_LEN. */ -error_t __argz_add (char **argz, size_t *argz_len, const char *str); -error_t argz_add (char **argz, size_t *argz_len, const char *str); +error_t __argz_add __P ((char **__argz, size_t *__argz_len, + __const char *__str)); +error_t argz_add __P ((char **__argz, size_t *__argz_len, + __const char *__str)); /* Delete ENTRY from ARGZ & ARGZ_LEN, if it appears there. */ -void __argz_delete (char **argz, size_t *argz_len, char *entry); -void argz_delete (char **argz, size_t *argz_len, char *entry); +void __argz_delete __P ((char **__argz, size_t *__argz_len, char *__entry)); +void argz_delete __P ((char **__argz, size_t *__argz_len, char *__entry)); /* Insert ENTRY into ARGZ & ARGZ_LEN before BEFORE, which should be an existing entry in ARGZ; if BEFORE is NULL, ENTRY is appended to the end. @@ -63,17 +80,17 @@ void argz_delete (char **argz, size_t *argz_len, char *entry); ARGZ, ENTRY) will insert ENTRY at the beginning of ARGZ. If BEFORE is not in ARGZ, EINVAL is returned, else if memory can't be allocated for the new ARGZ, ENOMEM is returned, else 0. */ -error_t __argz_insert (char **argz, size_t *argz_len, - char *before, const char *entry); -error_t argz_insert (char **argz, size_t *argz_len, - char *before, const char *entry); +error_t __argz_insert __P ((char **__argz, size_t *__argz_len, + char *__before, __const char *__entry)); +error_t argz_insert __P ((char **__argz, size_t *__argz_len, + char *__before, __const char *__entry)); /* Returns the next entry in ARGZ & ARGZ_LEN after ENTRY, or NULL if there are no more. If entry is NULL, then the first entry is returned. This behavior allows two convenient iteration styles: char *entry = 0; - while (entry = argz_next (argz, argz_len, entry)) + while ((entry = argz_next (argz, argz_len, entry))) ...; or @@ -82,19 +99,33 @@ error_t argz_insert (char **argz, size_t *argz_len, for (entry = argz; entry; entry = argz_next (argz, argz_len, entry)) ...; */ +extern char *__argz_next __P ((char *__argz, size_t __argz_len, + __const char *__entry)); +extern char *argz_next __P ((char *__argz, size_t __argz_len, + __const char *__entry)); + +#if defined (__OPTIMIZE__) && __GNUC__ >= 2 extern inline char * -argz_next (char *argz, size_t argz_len, const char *entry) +__argz_next (char *argz, size_t argz_len, const char *entry) { if (entry) - if (entry >= argz + argz_len) - return 0; - else - return strchr (entry, '\0') + 1; + { + if (entry < argz + argz_len) + entry = strchr (entry, '\0') + 1; + + return entry >= argz + argz_len ? NULL : entry; + } else if (argz_len > 0) return argz; else return 0; } +extern inline char * +argz_next (char *argz, size_t argz_len, const char *entry) +{ + return __argz_next (argz, argz_len, entry); +} +#endif /* optimizing GCC2 */ #endif /* __ARGZ_H__ */ diff --git a/string/envz.c b/string/envz.c index 4d0816e4e1..e751eccb8f 100644 --- a/string/envz.c +++ b/string/envz.c @@ -29,8 +29,8 @@ /* Returns a pointer to the entry in ENVZ for NAME, or 0 if there is none. If NAME contains the separator character, only the portion before it is used in the comparison. */ -char * -envz_entry (char *envz, unsigned envz_len, char *name) +const char * +envz_entry (const char *envz, size_t envz_len, const char *name) { while (envz_len) { @@ -57,8 +57,8 @@ envz_entry (char *envz, unsigned envz_len, char *name) /* Returns a pointer to the value portion of the entry in ENVZ for NAME, or 0 if there is none. */ -char * -envz_get (char *envz, unsigned envz_len, char *name) +const char * +envz_get (const char *envz, size_t envz_len, const char *name) { char *entry = envz_entry (envz, envz_len, name); if (entry) @@ -75,7 +75,7 @@ envz_get (char *envz, unsigned envz_len, char *name) /* Remove the entry for NAME from ENVZ & ENVZ_LEN, if any. */ void -envz_remove (char **envz, unsigned *envz_len, char *name) +envz_remove (char **envz, size_t *envz_len, char *name) { char *entry = envz_entry (*envz, *envz_len, name); if (entry) @@ -89,7 +89,7 @@ envz_remove (char **envz, unsigned *envz_len, char *name) because when merging with another envz, the null entry can override an entry in the other one. Null entries can be removed with envz_strip (). */ error_t -envz_add (char **envz, unsigned *envz_len, char *name, char *value) +envz_add (char **envz, unsigned *envz_len, const char *name, const char *value) { envz_remove (envz, envz_len, name); @@ -126,8 +126,8 @@ envz_add (char **envz, unsigned *envz_len, char *name, char *value) OVERRIDE is true, then values in ENVZ2 will supercede those with the same name in ENV, otherwise not. */ error_t -envz_merge (char **envz, unsigned *envz_len, char *envz2, unsigned envz2_len, - int override) +envz_merge (char **envz, unsigned *envz_len, const char *envz2, + size_t envz2_len, int override) { error_t err = 0; diff --git a/string/envz.h b/string/envz.h index c39c497e7e..dad2d281f4 100644 --- a/string/envz.h +++ b/string/envz.h @@ -28,11 +28,13 @@ #include <argz.h> /* Returns a pointer to the entry in ENVZ for NAME, or 0 if there is none. */ -char *envz_entry (const char *envz, size_t envz_len, const char *name); +const char *envz_entry __P ((__const char *__envz, size_t __envz_len, + __const char *__name)); /* Returns a pointer to the value portion of the entry in ENVZ for NAME, or 0 if there is none. */ -char *envz_get (const char *envz, size_t envz_len, const char *name); +const char *envz_get __P ((__const char *__envz, size_t __envz_len, + __const char *__name)); /* Adds an entry for NAME with value VALUE to ENVZ & ENVZ_LEN. If an entry with the same name already exists in ENVZ, it is removed. If VALUE is @@ -40,17 +42,17 @@ char *envz_get (const char *envz, size_t envz_len, const char *name); return NULL, although envz_entry will still return an entry; this is handy because when merging with another envz, the null entry can override an entry in the other one. Null entries can be removed with envz_strip (). */ -error_t envz_add (char **envz, size_t *envz_len, - const char *name, const char *value); +error_t envz_add __P ((char **__envz, size_t *__envz_len, + __const char *__name, __const char *__value)); /* Adds each entry in ENVZ2 to ENVZ & ENVZ_LEN, as if with envz_add(). If OVERRIDE is true, then values in ENVZ2 will supercede those with the same name in ENV, otherwise not. */ -error_t envz_merge (char **envz, size_t *envz_len, - const char *envz2, size_t envz2_len, - int override); +error_t envz_merge __P ((char **__envz, size_t *__envz_len, + __const char *__envz2, size_t __envz2_len, + int __override)); /* Remove null entries. */ -void envz_strip (char **envz, size_t *envz_len); +void envz_strip __P ((char **__envz, size_t *__envz_len)); #endif /* __ENVZ_H__ */ diff --git a/string/strcoll.c b/string/strcoll.c index dc1bb2aaaa..a4bbabc2ac 100644 --- a/string/strcoll.c +++ b/string/strcoll.c @@ -71,7 +71,7 @@ STRCOLL (s1, s2) { int s1ignore = 0; int s2ignore = 0; - u32_t w1, w2; + u_int32_t w1, w2; /* Here we have to check for IGNORE entries. If these are found we count them and go on witht he next value. */ diff --git a/string/tst-strlen.c b/string/tst-strlen.c new file mode 100644 index 0000000000..a58f8784db --- /dev/null +++ b/string/tst-strlen.c @@ -0,0 +1,32 @@ +#include <stdio.h> +#include <string.h> + +int +main() +{ + static const lens[16] = { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4 }; + char buf[24]; + int words; + + for (words = 0; words < 4; ++words) + { + int last; + memset (buf, 'a', words * 4); + + for (last = 0; last < 16; ++last) + { + buf[words * 4 + 0] = (last & 1) != 0 ? 'b' : '\0'; + buf[words * 4 + 1] = (last & 2) != 0 ? 'c' : '\0'; + buf[words * 4 + 2] = (last & 4) != 0 ? 'd' : '\0'; + buf[words * 4 + 3] = (last & 8) != 0 ? 'e' : '\0'; + buf[words * 4 + 4] = '\0'; + + if (strlen (buf) != words * 4 + lens[last]) + { + printf ("failed for words=%d and last=%d\n", words, last); + return 1; + } + } + } + return 0; +} diff --git a/sunrpc/svc_simple.c b/sunrpc/svc_simple.c index a18c8bce97..0a30c45b42 100644 --- a/sunrpc/svc_simple.c +++ b/sunrpc/svc_simple.c @@ -52,12 +52,12 @@ static struct proglst { } *proglst; static void universal(); static SVCXPRT *transp; -struct proglst *pl; registerrpc(prognum, versnum, procnum, progname, inproc, outproc) char *(*progname)(); xdrproc_t inproc, outproc; { + struct proglst *pl; if (procnum == NULLPROC) { (void) fprintf(stderr, diff --git a/sysdeps/i386/i586/strlen.S b/sysdeps/i386/i586/strlen.S index b807ed4b4f..15d01947d4 100644 --- a/sysdeps/i386/i586/strlen.S +++ b/sysdeps/i386/i586/strlen.S @@ -1,6 +1,6 @@ /* strlen -- Compute length og NUL terminated string. Highly optimized version for ix86, x>=5. -Copyright (C) 1995 Free Software Foundation, Inc. +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>. @@ -102,7 +102,6 @@ L1: jnc L3 /* previous addl caused overflow? */ xorl %ecx, %edx /* (word+magic)^word */ - subl $magic, %ecx /* undo previous addl to restore word */ andl $~magic, %edx /* any of the carry flags set? */ @@ -119,7 +118,6 @@ L1: jnc L3 /* previous addl caused overflow? */ xorl %ecx, %edx /* (word+magic)^word */ - subl $magic, %ecx /* undo previous addl to restore word */ andl $~magic, %edx /* any of the carry flags set? */ @@ -136,7 +134,6 @@ L1: jnc L3 /* previous addl caused overflow? */ xorl %ecx, %edx /* (word+magic)^word */ - subl $magic, %ecx /* undo previous addl to restore word */ andl $~magic, %edx /* any of the carry flags set? */ @@ -149,11 +146,10 @@ L1: subl %ecx, %edx /* first step to negate word */ addl $magic, %ecx /* add magic word */ - decl %edx /* wcomplete negation of ord */ + decl %edx /* complete negation of word */ jnc L3 /* previous addl caused overflow? */ xorl %ecx, %edx /* (word+magic)^word */ - subl $magic, %ecx /* undo previous addl to restore word */ andl $~magic, %edx /* any of the carry flags set? */ @@ -161,8 +157,9 @@ L1: L3: subl $4, %eax /* correct too early pointer increment */ - testb %cl, %cl /* lowest byte NUL? */ + subl $magic, %ecx + cmpb $0, %cl /* lowest byte NUL? */ jz L2 /* yes => return */ inc %eax /* increment pointer */ diff --git a/sysdeps/libm-ieee754/e_j0f.c b/sysdeps/libm-ieee754/e_j0f.c index b4e97a2c6b..eed171cc90 100644 --- a/sysdeps/libm-ieee754/e_j0f.c +++ b/sysdeps/libm-ieee754/e_j0f.c @@ -79,7 +79,7 @@ static float zero = 0.0; * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) */ - if(ix>0x80000000) z = (invsqrtpi*cc)/__sqrtf(x); + if(ix>0x48000000) z = (invsqrtpi*cc)/__sqrtf(x); else { u = pzerof(x); v = qzerof(x); z = invsqrtpi*(u*cc-v*ss)/__sqrtf(x); @@ -161,7 +161,7 @@ v04 = 4.4111031494e-10; /* 0x2ff280c2 */ if ((s*c)<zero) cc = z/ss; else ss = z/cc; } - if(ix>0x80000000) z = (invsqrtpi*ss)/__sqrtf(x); + if(ix>0x48000000) z = (invsqrtpi*ss)/__sqrtf(x); else { u = pzerof(x); v = qzerof(x); z = invsqrtpi*(u*ss+v*cc)/__sqrtf(x); diff --git a/sysdeps/libm-ieee754/e_j1f.c b/sysdeps/libm-ieee754/e_j1f.c index 06384bd68d..e6f14a16ac 100644 --- a/sysdeps/libm-ieee754/e_j1f.c +++ b/sysdeps/libm-ieee754/e_j1f.c @@ -80,7 +80,7 @@ static float zero = 0.0; * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x) * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x) */ - if(ix>0x80000000) z = (invsqrtpi*cc)/__sqrtf(y); + if(ix>0x48000000) z = (invsqrtpi*cc)/__sqrtf(y); else { u = ponef(y); v = qonef(y); z = invsqrtpi*(u*cc-v*ss)/__sqrtf(y); diff --git a/sysdeps/m68k/fpu/e_acos.c b/sysdeps/m68k/fpu/e_acos.c index 1a29222997..34dfc82cff 100644 --- a/sysdeps/m68k/fpu/e_acos.c +++ b/sysdeps/m68k/fpu/e_acos.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> #ifndef FUNC diff --git a/sysdeps/m68k/fpu/e_acosf.c b/sysdeps/m68k/fpu/e_acosf.c index 51968156f5..34da7ee163 100644 --- a/sysdeps/m68k/fpu/e_acosf.c +++ b/sysdeps/m68k/fpu/e_acosf.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> #ifndef FUNC diff --git a/sysdeps/m68k/fpu/e_fmod.c b/sysdeps/m68k/fpu/e_fmod.c index 310b1c41fa..578fa3ce53 100644 --- a/sysdeps/m68k/fpu/e_fmod.c +++ b/sysdeps/m68k/fpu/e_fmod.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> #ifndef FUNC diff --git a/sysdeps/m68k/fpu/e_fmodf.c b/sysdeps/m68k/fpu/e_fmodf.c index 1a74c3611b..b3c3eadddf 100644 --- a/sysdeps/m68k/fpu/e_fmodf.c +++ b/sysdeps/m68k/fpu/e_fmodf.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> #ifndef FUNC diff --git a/sysdeps/m68k/fpu/isinfl.c b/sysdeps/m68k/fpu/isinfl.c index 77fd759182..97b5983d0f 100644 --- a/sysdeps/m68k/fpu/isinfl.c +++ b/sysdeps/m68k/fpu/isinfl.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> int diff --git a/sysdeps/m68k/fpu/isnanl.c b/sysdeps/m68k/fpu/isnanl.c index 1e58ea4ebd..e5e3db2171 100644 --- a/sysdeps/m68k/fpu/isnanl.c +++ b/sysdeps/m68k/fpu/isnanl.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> int diff --git a/sysdeps/m68k/fpu/s_atan.c b/sysdeps/m68k/fpu/s_atan.c index f1cc9757b5..51916e12ff 100644 --- a/sysdeps/m68k/fpu/s_atan.c +++ b/sysdeps/m68k/fpu/s_atan.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> #ifndef FUNC diff --git a/sysdeps/m68k/fpu/s_atanf.c b/sysdeps/m68k/fpu/s_atanf.c index 5d1f337bee..d26f83875b 100644 --- a/sysdeps/m68k/fpu/s_atanf.c +++ b/sysdeps/m68k/fpu/s_atanf.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> #ifndef FUNC diff --git a/sysdeps/m68k/fpu/s_frexp.c b/sysdeps/m68k/fpu/s_frexp.c index b24af74956..45c054016d 100644 --- a/sysdeps/m68k/fpu/s_frexp.c +++ b/sysdeps/m68k/fpu/s_frexp.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> double diff --git a/sysdeps/m68k/fpu/s_frexpf.c b/sysdeps/m68k/fpu/s_frexpf.c index c7cd98a684..dd30f6c39c 100644 --- a/sysdeps/m68k/fpu/s_frexpf.c +++ b/sysdeps/m68k/fpu/s_frexpf.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> float diff --git a/sysdeps/m68k/fpu/s_ilogb.c b/sysdeps/m68k/fpu/s_ilogb.c index 2df00a656a..4119df968a 100644 --- a/sysdeps/m68k/fpu/s_ilogb.c +++ b/sysdeps/m68k/fpu/s_ilogb.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> int diff --git a/sysdeps/m68k/fpu/s_ilogbf.c b/sysdeps/m68k/fpu/s_ilogbf.c index 05f1546a96..8d9a027f22 100644 --- a/sysdeps/m68k/fpu/s_ilogbf.c +++ b/sysdeps/m68k/fpu/s_ilogbf.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> int diff --git a/sysdeps/m68k/fpu/s_isinf.c b/sysdeps/m68k/fpu/s_isinf.c index 96745337c9..eec07c7d3a 100644 --- a/sysdeps/m68k/fpu/s_isinf.c +++ b/sysdeps/m68k/fpu/s_isinf.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> #ifndef FUNC diff --git a/sysdeps/m68k/fpu/s_isinff.c b/sysdeps/m68k/fpu/s_isinff.c index d9101a9fd9..8f18db5b08 100644 --- a/sysdeps/m68k/fpu/s_isinff.c +++ b/sysdeps/m68k/fpu/s_isinff.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> #ifndef FUNC diff --git a/sysdeps/m68k/fpu/s_ldexp.c b/sysdeps/m68k/fpu/s_ldexp.c index ee7662e7d2..67513d4875 100644 --- a/sysdeps/m68k/fpu/s_ldexp.c +++ b/sysdeps/m68k/fpu/s_ldexp.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> #ifndef FUNC diff --git a/sysdeps/m68k/fpu/s_ldexpf.c b/sysdeps/m68k/fpu/s_ldexpf.c index a9741732a6..94abf25ac1 100644 --- a/sysdeps/m68k/fpu/s_ldexpf.c +++ b/sysdeps/m68k/fpu/s_ldexpf.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> #ifndef FUNC diff --git a/sysdeps/m68k/fpu/s_modf.c b/sysdeps/m68k/fpu/s_modf.c index 355df2fb19..ce70be8168 100644 --- a/sysdeps/m68k/fpu/s_modf.c +++ b/sysdeps/m68k/fpu/s_modf.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> double diff --git a/sysdeps/m68k/fpu/s_modff.c b/sysdeps/m68k/fpu/s_modff.c index f56bcb45ef..04b51d5be1 100644 --- a/sysdeps/m68k/fpu/s_modff.c +++ b/sysdeps/m68k/fpu/s_modff.c @@ -17,7 +17,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#define __NO_MATH_INLINES #include <math.h> float diff --git a/sysdeps/unix/sysv/linux/getpriority.c b/sysdeps/unix/sysv/linux/getpriority.c new file mode 100644 index 0000000000..6dd56cce8b --- /dev/null +++ b/sysdeps/unix/sysv/linux/getpriority.c @@ -0,0 +1,42 @@ +/* getpriority for Linux. +Copyright (C) 1996 Free Software Foundation, Inc. + +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 <errno.h> +#include <sys/resource.h> + +extern int __syscall_getpriority (int, int); + +/* The return value of __syscall_getpriority is biased by this value + to avoid returning negative values. */ +#define PZERO 20 + +/* Return the highest priority of any process specified by WHICH and WHO + (see above); if WHO is zero, the current process, process group, or user + (as specified by WHO) is used. A lower priority number means higher + priority. Priorities range from PRIO_MIN to PRIO_MAX. */ + +int +getpriority (enum __priority_which which, int who) +{ + int res; + + res = __syscall_getpriority ((int) which, who); + if (res >= 0) + res = PZERO - res; + return res; +} diff --git a/sysdeps/unix/sysv/linux/m68k/fpu_control.h b/sysdeps/unix/sysv/linux/m68k/fpu_control.h index 0b3623d9a3..97bde853bc 100644 --- a/sysdeps/unix/sysv/linux/m68k/fpu_control.h +++ b/sysdeps/unix/sysv/linux/m68k/fpu_control.h @@ -80,11 +80,9 @@ Cambridge, MA 02139, USA. */ /* Now two recommended fpucr */ -/* Linux default: - - extended precision - - rounding to nearest - - exceptions on overflow, zero divide and NaN */ -#define _FPU_DEFAULT 0x00005400 +/* The fdlibm code requires no interrupts for exceptions. Don't + change the rounding mode, it would break long double I/O! */ +#define _FPU_DEFAULT 0x00000000 /* IEEE: same as above, but exceptions. We must make it non-zero so that __setfpucw works. This bit will be ignored. */ diff --git a/sysdeps/unix/sysv/linux/sys/socket.h b/sysdeps/unix/sysv/linux/sys/socket.h index b3e8fe85e9..cd6c58bd32 100644 --- a/sysdeps/unix/sysv/linux/sys/socket.h +++ b/sysdeps/unix/sysv/linux/sys/socket.h @@ -1,2 +1 @@ #include <linux/socket.h> -#include <linux/socket.h> diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index 6deee5950f..d78a1f7e89 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -20,6 +20,7 @@ nanosleep - nanosleep 2 nanosleep personality init-first personality 1 __personality personality pipe - pipe 1 __pipe pipe reboot - reboot 3 reboot +s_getpriority getpriority getpriority 2 __syscall_getpriority s_ptrace ptrace ptrace 4 __syscall_ptrace s_sigsuspend sigsuspend sigsuspend 3 __syscall_sigsuspend sched_setp - sched_setparam 2 __sched_setparam sched_setparam diff --git a/wctype/test_wctype.c b/wctype/test_wctype.c index bf3de172df..bc2c7e9d18 100644 --- a/wctype/test_wctype.c +++ b/wctype/test_wctype.c @@ -48,7 +48,7 @@ main (int argc, char *argv[]) { #define TEST(test) \ do \ - if (is##test (ch) != iswctype ((wchar_t) ch, bit_##test)) \ + if ((is##test (ch) == 0) != (iswctype (ch, bit_##test)) == 0) \ { \ printf ("class `%s' test for character \\%o failed\n", \ #test, ch); \ |