diff options
author | Roland McGrath <roland@gnu.org> | 1996-04-20 00:05:25 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1996-04-20 00:05:25 +0000 |
commit | a641835acd28fabf507c5a99d7805c694c2ec7e3 (patch) | |
tree | 5829796a450826b540dc763b8891b110bafd35b1 | |
parent | f24f4dc82d76bc2bed2d7e28877c5e9e469d4931 (diff) | |
download | glibc-a641835acd28fabf507c5a99d7805c694c2ec7e3.tar glibc-a641835acd28fabf507c5a99d7805c694c2ec7e3.tar.gz glibc-a641835acd28fabf507c5a99d7805c694c2ec7e3.tar.bz2 glibc-a641835acd28fabf507c5a99d7805c694c2ec7e3.zip |
Fri Apr 19 00:49:44 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>cvs/libc-960420
* stdlib/rpmatch.c (rpmatch: try): Take new arg NOMATCH, return value
for nonmatching nonerror (instead of !MATCH).
(rpmatch): Use it, so we return -1 when NOEXPR doesn't match either.
* resolv/getnetnamadr.c (getnetbyaddr): Use u_int32_t instead of
unsigned long for variable NET2.
* time/etcetera, time/europe, time/solar89: Updated from ADO's 96e.
Tue Apr 9 14:37:31 1996 Ulrich Drepper <drepper@cygnus.com>
* catgets/Makefile, catgets/catgets.c, catgets/catgetsinfo.h,
catgets/config.h, catgets/gencat.c, catgets/nl_types.h,
catgets/open_catalog.c: New files. Implementation of XPG4
compliant catgets() function and needed tools.
* Makefile (subdirs): Add catgets.
Thu Apr 18 23:36:11 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* math/Makefile (CPPFLAGS): Append -D__NO_MATH_INLINES.
Wed Apr 10 20:48:43 1996 Ulrich Drepper <drepper@cygnus.com>
* stdio-common/vfprintf.c: Correct some typos.
* sysdeps/libm-ieee754/w_gammaf.c, sysdeps/libm-ieee754/w_lgamma.c,
sysdeps/libm-ieee754/w_lgammaf.c: Reference signgam instead of
__signgam.
Thu Apr 18 21:07:27 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* Makerules (no-whole-archive): New variable.
(build-shlib): Use it.
* elf/Makefile (libdl.so): Use it.
* configure.in (libc_cv_ld_no_whole_archive): New check for
--no-whole-archive.
* config.make.in (have-no-whole-archive): New variable.
* stdio-common/printf_fp.c: Increase fudge factor for BIGNUM_SIZE calc
from 3 to 4.
* Make-dist: Include version.mk.
(version, release): Variables removed.
* Makeconfig (version.mk): New target.
Fri Apr 19 01:42:18 1996 Ulrich Drepper <drepper@cygnus.com>
* locale/Makefile (headers): Add langinfo.h.
(CPPFLAGS): Remove -Iliblib.
-rw-r--r-- | ChangeLog | 52 | ||||
-rw-r--r-- | Make-dist | 6 | ||||
-rw-r--r-- | Makeconfig | 7 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | Makerules | 9 | ||||
-rw-r--r-- | catgets/Makefile | 41 | ||||
-rw-r--r-- | catgets/catgets.c | 163 | ||||
-rw-r--r-- | catgets/catgetsinfo.h | 59 | ||||
-rw-r--r-- | catgets/config.h | 14 | ||||
-rw-r--r-- | catgets/gencat.c | 1030 | ||||
-rw-r--r-- | catgets/nl_types.h | 48 | ||||
-rw-r--r-- | catgets/open_catalog.c | 263 | ||||
-rw-r--r-- | config.make.in | 2 | ||||
-rw-r--r-- | configure.in | 13 | ||||
-rw-r--r-- | elf/Makefile | 4 | ||||
-rw-r--r-- | locale/Makefile | 4 | ||||
-rw-r--r-- | math/Makefile | 4 | ||||
-rw-r--r-- | posix/regex.c | 7 | ||||
-rw-r--r-- | resolv/getnetnamadr.c | 6 | ||||
-rw-r--r-- | stdio-common/printf_fp.c | 2 | ||||
-rw-r--r-- | stdio-common/vfprintf.c | 6 | ||||
-rw-r--r-- | stdlib/rpmatch.c | 8 | ||||
-rw-r--r-- | sysdeps/libm-ieee754/w_gammaf.c | 6 | ||||
-rw-r--r-- | sysdeps/libm-ieee754/w_lgamma.c | 6 | ||||
-rw-r--r-- | sysdeps/libm-ieee754/w_lgammaf.c | 6 | ||||
-rw-r--r-- | time/etcetera | 5 | ||||
-rw-r--r-- | time/europe | 9 | ||||
-rw-r--r-- | time/solar89 | 4 |
28 files changed, 1747 insertions, 39 deletions
@@ -1,3 +1,55 @@ +Fri Apr 19 00:49:44 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + + * stdlib/rpmatch.c (rpmatch: try): Take new arg NOMATCH, return value + for nonmatching nonerror (instead of !MATCH). + (rpmatch): Use it, so we return -1 when NOEXPR doesn't match either. + + * resolv/getnetnamadr.c (getnetbyaddr): Use u_int32_t instead of + unsigned long for variable NET2. + + * time/etcetera, time/europe, time/solar89: Updated from ADO's 96e. + +Tue Apr 9 14:37:31 1996 Ulrich Drepper <drepper@cygnus.com> + + * catgets/Makefile, catgets/catgets.c, catgets/catgetsinfo.h, + catgets/config.h, catgets/gencat.c, catgets/nl_types.h, + catgets/open_catalog.c: New files. Implementation of XPG4 + compliant catgets() function and needed tools. + * Makefile (subdirs): Add catgets. + +Thu Apr 18 23:36:11 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + + * math/Makefile (CPPFLAGS): Append -D__NO_MATH_INLINES. + +Wed Apr 10 20:48:43 1996 Ulrich Drepper <drepper@cygnus.com> + + * stdio-common/vfprintf.c: Correct some typos. + + * sysdeps/libm-ieee754/w_gammaf.c, sysdeps/libm-ieee754/w_lgamma.c, + sysdeps/libm-ieee754/w_lgammaf.c: Reference signgam instead of + __signgam. + +Thu Apr 18 21:07:27 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + + * Makerules (no-whole-archive): New variable. + (build-shlib): Use it. + * elf/Makefile (libdl.so): Use it. + * configure.in (libc_cv_ld_no_whole_archive): New check for + --no-whole-archive. + * config.make.in (have-no-whole-archive): New variable. + + * stdio-common/printf_fp.c: Increase fudge factor for BIGNUM_SIZE calc + from 3 to 4. + + * Make-dist: Include version.mk. + (version, release): Variables removed. + * Makeconfig (version.mk): New target. + +Fri Apr 19 01:42:18 1996 Ulrich Drepper <drepper@cygnus.com> + + * locale/Makefile (headers): Add langinfo.h. + (CPPFLAGS): Remove -Iliblib. + Mon Apr 15 16:49:04 1996 Roland McGrath <roland@whiz-bang.gnu.ai.mit.edu> * malloc/memalign.c, malloc/malloc.h [__DJGPP__ == 1]: Elide memalign @@ -105,11 +105,7 @@ foo:=$(shell echo '+tsrcs=$(+tsrcs)'>&2) foo:=$(shell echo foobie, dammit! >&2) ifndef tardir -rel+vers := $(shell sed -n -e 's/^.*RELEASE.*\"\([^"]*\)";$$/\1/p' \ - -e 's/^.*VERSION.*\"\([^"]*\)";$$/\1/p' \ - < $(..)version.h) -release := $(word 1,$(rel+vers)) -version := $(word 2,$(rel+vers)) +-include $(common-objpfx)version.mk export tardir := glibc-$(version) endif diff --git a/Makeconfig b/Makeconfig index 3273675d11..e0522ab815 100644 --- a/Makeconfig +++ b/Makeconfig @@ -468,6 +468,13 @@ cross-compiling := yes else cross-compiling := no endif + +# Figure out the version numbers from version.h. +$(common-objpfx)version.mk: $(..)version.h + sed -n -e 's/^.*RELEASE.*\"\([^"]*\)";$$/release=\1/p' \ + -e 's/^.*VERSION.*\"\([^"]*\)";$$/version=\1/p' \ + < $< > $@-new + mv -f $@-new $@ endif # Makeconfig not yet included @@ -51,7 +51,7 @@ sysdep-subdirs := $(subst $(\n), ,$(sysdep-subdirs)) endif # These are the subdirectories containing the library source. -subdirs = csu assert ctype db locale intl math setjmp signal stdlib \ +subdirs = csu assert ctype db locale intl catgets math setjmp signal stdlib \ stdio-common $(stdio) malloc string wcsmbs time dirent grp pwd\ posix io termios resource misc socket sysvipc gmon gnulib \ wctype $(wildcard crypt) manual $(sysdep-subdirs) elf @@ -569,12 +569,19 @@ ifeq (yes,$(build-shared)) # on other shared objects. lib%.so: lib%_pic.a; $(build-shlib) +ifeq ($(libc_cv_ld_no_whole_archive),yes) +no-whole-archive = -Wl,--no-whole-archive +else +no-whole-archive = +endif + define build-shlib $(LINK.o) -shared -o $@ $(sysdep-LDFLAGS) $(config-LDFLAGS) \ -Wl,-soname=lib$(libprefix)$(@F:lib%.so=%).so$($(@F)-version) \ $(LDFLAGS.so) $(LDFLAGS-$(@F:lib%.so=%).so) \ -Wl,-rpath-link=$(common-objdir) \ - -Wl,--whole-archive $^ $(LDLIBS-$(@F:lib%.so=%).so) + -Wl,--whole-archive $^ $(no-whole-archive) \ + $(LDLIBS-$(@F:lib%.so=%).so) endef # Don't try to use -lc when making libc.so itself. diff --git a/catgets/Makefile b/catgets/Makefile new file mode 100644 index 0000000000..4646dd5a3f --- /dev/null +++ b/catgets/Makefile @@ -0,0 +1,41 @@ +# Copyright (C) 1996 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# 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. + +# +# Makefile for catgets. +# +subdir := catgets + +headers = nl_types.h +distribute = catgetsinfo.h config.h +routines = catgets open_catalog +others = gencat +install-bin = gencat + +gencat-modules = xmalloc + +# To find xmalloc.c +vpath %.c ../locale/programs + + +include ../Rules + +$(objpfx)gencat: $(gencat-modules:%=$(objpfx)%.o) + +CPPFLAGS := -DNLSPATH='"$(localedir)/%L/%N:$(localedir)/%L/LC_MESSAGES/%N:"' \ + -DHAVE_CONFIG_H $(CPPFLAGS) diff --git a/catgets/catgets.c b/catgets/catgets.c new file mode 100644 index 0000000000..ca0fdd693c --- /dev/null +++ b/catgets/catgets.c @@ -0,0 +1,163 @@ +/* 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>. + +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 <alloca.h> +#include <nl_types.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> + +#include "catgetsinfo.h" + + +/* Open the catalog and return a descriptor for the catalog. */ +nl_catd +catopen (const char *cat_name, int flag) +{ + __nl_catd result; + const char *env_var; + + result = (__nl_catd) malloc (sizeof (__nl_catd)); + if (result == NULL) + /* We cannot get enough memory. */ + return (nl_catd) -1; + + result->status = closed; + + result->cat_name = strdup (cat_name); + if (result->cat_name == NULL) + { + free (result); + return (nl_catd) -1; + } + + if (strchr (cat_name, '/') == NULL) + { + if (flag == NL_CAT_LOCALE) + { + env_var = getenv ("LC_ALL"); + if (env_var == NULL) + { + env_var = getenv ("LC_MESSAGES"); + if (env_var == NULL) + { + env_var = getenv ("LANG"); + if (env_var == NULL) + env_var = "C"; + } + } + } + else + { + env_var = getenv ("LANG"); + if (env_var == NULL) + env_var = "C"; + } + + result->env_var = strdup (env_var); + if (result->env_var == NULL) + { + free ((void *) result->cat_name); + free ((void *) result); + return (nl_catd) -1; + } + + if (getenv ("NLSPATH") != NULL) + result->nlspath = strdup (getenv ("NLSPATH")); + else + result->nlspath = strdup (NLSPATH); + + if (result->nlspath == NULL) + { + free ((void *) result->cat_name); + free ((void *) result->env_var); + free ((void *) result); + return (nl_catd) -1; + } + } + else + { + result->env_var = NULL; + result->nlspath = NULL; + } + + return (nl_catd) result; +} + + +/* Return message from message catalog. */ +char * +catgets (nl_catd catalog_desc, int set, int message, const char *string) +{ + __nl_catd catalog; + size_t idx; + size_t cnt; + + /* Be generous if catalog which failed to be open is used. */ + if (catalog_desc == (nl_catd) -1 || ++set <= 0 || message < 0) + return (char *) string; + + catalog = (__nl_catd) catalog_desc; + + if (catalog->status == closed) + __open_catalog (catalog, 1); + + if (catalog->status == nonexisting) + return (char *) string; + + idx = ((set * message) % catalog->plane_size) * 3; + cnt = 0; + do + { + if (catalog->name_ptr[idx + 0] == (u_int32_t) set + && catalog->name_ptr[idx + 1] == (u_int32_t) message) + return (char *) &catalog->strings[catalog->name_ptr[idx + 2]]; + + idx += catalog->plane_size * 3; + } + while (++cnt < catalog->plane_depth); + + return (char *) string; +} + + +/* Return resources used for loaded message catalog. */ +int +catclose (nl_catd catalog_desc) +{ + __nl_catd catalog; + + catalog = (__nl_catd) catalog_desc; + + if (catalog->status == mmaped) + munmap ((void *) catalog->file_ptr, catalog->file_size); + else if (catalog->status == malloced) + free ((void *) catalog->file_ptr); + else if (catalog->status != closed && catalog->status != nonexisting) + return -1; + + if (catalog->nlspath) + free ((void *) catalog->nlspath); + if (catalog->env_var) + free ((void *) catalog->env_var); + free ((void *) catalog); + + return 0; +} diff --git a/catgets/catgetsinfo.h b/catgets/catgetsinfo.h new file mode 100644 index 0000000000..7e0a26f798 --- /dev/null +++ b/catgets/catgetsinfo.h @@ -0,0 +1,59 @@ +/* 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>. + +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 <sys/types.h> + + +struct catalog_obj +{ + u_int32_t magic; + u_int32_t plane_size; + u_int32_t plane_depth; + /* This is in fact two arrays in one: always a pair of name and + pointer into the data area. */ + u_int32_t name_ptr[0]; +}; + + +/* This structure will be filled after loading the catalog. */ +typedef struct catalog_info +{ + enum { closed, nonexisting, mmaped, malloced } status; + + const char *cat_name; + const char *env_var; + const char *nlspath; + + size_t plane_size; + size_t plane_depth; + u_int32_t *name_ptr; + const char *strings; + + struct catalog_obj *file_ptr; + size_t file_size; +} *__nl_catd; + + + +/* The magic number to signal we really have a catalog file. */ +#define CATGETS_MAGIC 0x960408de + + +/* Prototypes for helper functions. */ +void __open_catalog (__nl_catd __catalog, int __with_path); diff --git a/catgets/config.h b/catgets/config.h new file mode 100644 index 0000000000..ce7887b351 --- /dev/null +++ b/catgets/config.h @@ -0,0 +1,14 @@ +#ifndef _CG_CONFIG_H +#define _CG_CONFIG_H + +/* Use the internal textdomain used for libc messages. */ +#define PACKAGE _libc_intl_domainname +#ifndef VERSION +/* Get libc version number. */ +#include "../version.h" +#endif + + +#include_next <config.h> + +#endif diff --git a/catgets/gencat.c b/catgets/gencat.c new file mode 100644 index 0000000000..4b6eb43255 --- /dev/null +++ b/catgets/gencat.c @@ -0,0 +1,1030 @@ +/* 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>. + +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. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <ctype.h> +#include <endian.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <getopt.h> +#include <libintl.h> +#include <limits.h> +#include <nl_types.h> +#include <obstack.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "version.h" + +#include "catgetsinfo.h" + + +#define SWAPU32(w) \ + (((w) << 24) | (((w) & 0xff00) << 8) | (((w) >> 8) & 0xff00) | ((w) >> 24)) + +struct message_list +{ + int number; + const char *message; + + const char *fname; + size_t line; + const char *symbol; + + struct message_list *next; +}; + + +struct set_list +{ + int number; + int deleted; + struct message_list *messages; + int last_message; + + const char *fname; + size_t line; + const char *symbol; + + struct set_list *next; +}; + + +struct catalog +{ + struct set_list *all_sets; + struct set_list *current_set; + size_t total_messages; + char quote_char; + int last_set; + + struct obstack mem_pool; +}; + + +/* If non-zero force creation of new file, not using existing one. */ +static int force_new; + +/* Long options. */ +static const struct option long_options[] = +{ + { "header", required_argument, NULL, 'H' }, + { "help", no_argument, NULL, 'h' }, + { "new", no_argument, &force_new, 1 }, + { "output", required_argument, NULL, 'o' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } +}; + +/* Wrapper functions with error checking for standard functions. */ +extern void *xmalloc (size_t n); + +/* Prototypes for local functions. */ +static void usage (int status) __attribute__ ((noreturn)); +static void error_print (void); +static struct catalog *read_input_file (struct catalog *current, + const char *fname); +static void write_out (struct catalog *result, const char *output_name, + const char *header_name); +static struct set_list *find_set (struct catalog *current, int number); +static void normalize_line (const char *fname, size_t line, char *string, + char quote_char); +static void read_old (struct catalog *catalog, const char *file_name); + + +int +main (int argc, char *argv[]) +{ + struct catalog *result; + const char *output_name; + const char *header_name; + int do_help; + int do_version; + int opt; + + /* Set program name for messages. */ + error_print_progname = error_print; + + /* Set locale via LC_ALL. */ + setlocale (LC_ALL, ""); + + /* Set the text message domain. */ + textdomain (PACKAGE); + + /* Initialize local variables. */ + do_help = 0; + do_version = 0; + output_name = NULL; + header_name = NULL; + result = NULL; + + while ((opt = getopt_long (argc, argv, "hH:o:V", long_options, NULL)) != EOF) + switch (opt) + { + case '\0': /* Long option. */ + break; + case 'h': + do_help = 1; + break; + case 'H': + header_name = optarg; + break; + case 'o': + output_name = optarg; + break; + case 'V': + do_version = 1; + break; + default: + usage (EXIT_FAILURE); + } + + /* Version information is requested. */ + if (do_version) + { + fprintf (stderr, "%s - GNU %s %s\n", program_invocation_name, + PACKAGE, VERSION); + exit (EXIT_SUCCESS); + } + + /* Help is requested. */ + if (do_help) + usage (EXIT_SUCCESS); + + /* Determine output file. */ + if (output_name == NULL) + output_name = optind < argc ? argv[optind++] : "-"; + + /* Process all input files. */ + setlocale (LC_CTYPE, "C"); + if (optind < argc) + do + result = read_input_file (result, argv[optind]); + while (++optind < argc); + else + result = read_input_file (NULL, "-"); + + /* Write out the result. */ + if (result != NULL) + write_out (result, output_name, header_name); + + exit (EXIT_SUCCESS); +} + + +static void +usage (int status) +{ + if (status != EXIT_SUCCESS) + fprintf (stderr, gettext ("Try `%s --help' for more information.\n"), + program_invocation_name); + else + printf(gettext ("\ +Usage: %s [OPTION]... -o OUTPUT-FILE [INPUT-FILE]...\n\ + %s [OPTION]... [OUTPUT-FILE [INPUT-FILE]...]\n\ +Mandatory arguments to long options are mandatory for short options too.\n\ + -H, --header create C header file containing symbol definitions\n\ + -h, --help display this help and exit\n\ + --new do not use existing catalog, force new output file\n\ + -o, --output=NAME write output to file NAME\n\ + -V, --version output version information and exit\n\ +If INPUT-FILE is -, input is read from standard input. If OUTPUT-FILE\n\ +is -, output is written to standard output.\n"), + program_invocation_name, program_invocation_name); + + exit (status); +} + + +/* The address of this function will be assigned to the hook in the + error functions. */ +static void +error_print () +{ + /* We don't want the program name to be printed in messages. Emacs' + compile.el does not like this. */ +} + + +static struct catalog * +read_input_file (struct catalog *current, const char *fname) +{ + FILE *fp; + char *buf; + size_t len; + size_t line_number; + + if (strcmp (fname, "-") == 0 || strcmp (fname, "/dev/stdin") == 0) + { + fp = stdin; + fname = gettext ("*standard input*"); + } + else + fp = fopen (fname, "r"); + if (fp == NULL) + { + error (0, errno, gettext ("cannot open input file `%s'"), fname); + return current; + } + + /* If we haven't seen anything yet, allocate result structure. */ + if (current == NULL) + { + current = (struct catalog *) xmalloc (sizeof (*current)); + + current->all_sets = NULL; + current->total_messages = 0; + current->last_set = 0; + current->current_set = find_set (current, NL_SETD); + +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + obstack_init (¤t->mem_pool); + } + + buf = NULL; + len = 0; + line_number = 0; + while (!feof (fp)) + { + int continued; + int used; + size_t start_line = line_number + 1; + char *this_line; + + do + { + int act_len; + + act_len = getline (&buf, &len, fp); + if (act_len <= 0) + break; + ++line_number; + + /* It the line continued? */ + if (buf[act_len - 1] == '\n') + { + --act_len; + continued = buf[act_len - 1] == '\\'; + if (continued) + --act_len; + } + else + continued = 0; + + /* Append to currently selected line. */ + obstack_grow (¤t->mem_pool, buf, act_len); + } + while (continued); + + obstack_1grow (¤t->mem_pool, '\0'); + this_line = (char *) obstack_finish (¤t->mem_pool); + + used = 0; + if (this_line[0] == '$') + { + if (isspace (this_line[1])) + /* This is a comment line. Do nothing. */; + else if (strncmp (&this_line[1], "set", 3) == 0) + { + int cnt = sizeof ("cnt"); + size_t set_number; + const char *symbol = NULL; + while (isspace (this_line[cnt])) + ++cnt; + + if (isdigit (this_line[cnt])) + { + set_number = atol (&this_line[cnt]); + + /* If the given number for the character set is + higher than any we used for symbolic set names + avoid clashing by using only higher numbers for + the following symbolic definitions. */ + if (set_number > current->last_set) + current->last_set = set_number; + } + else + { + /* See whether it is a reasonable identifier. */ + int start = cnt; + while (isalnum (this_line[cnt]) || this_line[cnt] == '_') + ++cnt; + + if (cnt == start) + { + /* No correct character found. */ + error_at_line (0, 0, fname, start_line, + gettext ("illegal set number")); + set_number = 0; + } + else + { + /* We have found seomthing which looks like a + correct identifier. */ + struct set_list *runp; + + this_line[cnt] = '\0'; + used = 1; + symbol = &this_line[start]; + + /* Test whether the identifier was already used. */ + runp = current->all_sets; + while (runp != 0) + if (runp->symbol != NULL + && strcmp (runp->symbol, symbol) == 0) + break; + else + runp = runp->next; + + if (runp != NULL) + { + /* We cannot allow duplicate identifiers for + message sets. */ + error_at_line (0, 0, fname, start_line, + gettext ("duplicate set definition")); + error_at_line (0, 0, runp->fname, runp->line, + gettext ("\ +this is the first definition")); + set_number = 0; + } + else + /* Allocate next free message set for identifier. */ + set_number = ++current->last_set; + } + } + + if (set_number != 0) + { + /* We found a legal set number. */ + current->current_set = find_set (current, set_number); + if (symbol != NULL) + used = 1; + current->current_set->symbol = symbol; + current->current_set->fname = fname; + current->current_set->line = start_line; + } + } + else if (strncmp (&this_line[1], "delset", 6) == 0) + { + int cnt = sizeof ("delset"); + size_t set_number; + while (isspace (this_line[cnt])) + ++cnt; + + if (isdigit (this_line[cnt])) + { + size_t set_number = atol (&this_line[cnt]); + struct set_list *set; + + /* Mark the message set with the given number as + deleted. */ + set = find_set (current, set_number); + set->deleted = 1; + } + else + { + /* See whether it is a reasonable identifier. */ + int start = cnt; + while (isalnum (this_line[cnt]) || this_line[cnt] == '_') + ++cnt; + + if (cnt == start) + { + error_at_line (0, 0, fname, start_line, + gettext ("illegal set number")); + set_number = 0; + } + else + { + const char *symbol; + struct set_list *runp; + + this_line[cnt] = '\0'; + used = 1; + symbol = &this_line[start]; + + /* We have a symbolic set name. This name must + appear somewhere else in the catalogs read so + far. */ + set_number = 0; + for (runp = current->all_sets; runp != NULL; + runp = runp->next) + { + if (strcmp (runp->symbol, symbol) == 0) + { + runp->deleted = 1; + break; + } + } + if (runp == NULL) + /* Name does not exist before. */ + error_at_line (0, 0, fname, start_line, + gettext ("unknown set `%s'"), symbol); + } + } + } + else if (strncmp (&this_line[1], "quote", 5) == 0) + { + int cnt = sizeof ("quote"); + while (isspace (this_line[cnt])) + ++cnt; + /* Yes, the quote char can be '\0'; this means no quote + char. */ + current->quote_char = this_line[cnt]; + } + else + { + int cnt; + cnt = 2; + while (this_line[cnt] != '\0' && !isspace (this_line[cnt])) + ++cnt; + this_line[cnt] = '\0'; + error_at_line (0, 0, fname, start_line, + gettext ("unknown directive `%s': line ignored"), + &this_line[1]); + } + } + else if (isalnum (this_line[0]) || this_line[0] == '_') + { + const char *ident = this_line; + int message_number; + + do + ++this_line; + while (this_line[0] != '\0' && !isspace (this_line[0]));; + this_line[0] = '\0'; /* Terminate the identifier. */ + + do + ++this_line; + while (isspace (this_line[0])); + /* Now we found the beginning of the message itself. */ + + if (isdigit (ident[0])) + { + struct message_list *runp; + + message_number = atoi (ident); + + /* Find location to insert the new message. */ + runp = current->current_set->messages; + while (runp != NULL) + if (runp->number == message_number) + break; + else + runp = runp->next; + if (runp != NULL) + { + /* Oh, oh. There is already a message with this + number is the message set. */ + error_at_line (0, 0, fname, start_line, + gettext ("duplicated message number")); + error_at_line (0, 0, runp->fname, runp->line, + gettext ("this is the first definition")); + message_number = 0; + } + ident = NULL; /* We don't have a symbol. */ + + if (message_number != 0 + && message_number > current->current_set->last_message) + current->current_set->last_message = message_number; + } + else if (ident[0] != '\0') + { + struct message_list *runp; + runp = current->current_set->messages; + + /* Test whether the symbolic name was not used for + another message in this message set. */ + while (runp != NULL) + if (runp->symbol != NULL && strcmp (ident, runp->symbol) == 0) + break; + else + runp = runp->next; + if (runp != NULL) + { + /* The name is already used. */ + error_at_line (0, 0, fname, start_line, + gettext ("duplicated message identifier")); + error_at_line (0, 0, runp->fname, runp->line, + gettext ("this is the first definition")); + message_number = 0; + } + else + /* Give the message the next unused number. */ + message_number = ++current->current_set->last_message; + } + else + message_number = 0; + + if (message_number != 0) + { + struct message_list *newp; + + used = 1; /* Yes, we use the line. */ + + /* Strip quote characters, change escape sequences into + correct characters etc. */ + normalize_line (fname, start_line, this_line, + current->quote_char); + + newp = (struct message_list *) xmalloc (sizeof (*newp)); + newp->number = message_number; + newp->message = this_line; + /* Remember symbolic name; is NULL if no is given. */ + newp->symbol = ident; + /* Remember where we found the character. */ + newp->fname = fname; + newp->line = start_line; + + /* Find place to insert to message. We keep them in a + sorted single linked list. */ + if (current->current_set->messages == NULL + || current->current_set->messages->number > message_number) + { + newp->next = current->current_set->messages; + current->current_set->messages = newp; + } + else + { + struct message_list *runp; + runp = current->current_set->messages; + while (runp->next != NULL) + if (runp->next->number > message_number) + break; + else + runp = runp->next; + newp->next = runp->next; + runp->next = newp; + } + } + ++current->total_messages; + } + else + { + size_t cnt; + + cnt = 0; + /* See whether we have any non-white space character in this + line. */ + while (this_line[cnt] != '\0' && isspace (this_line[cnt])) + ++cnt; + + if (this_line[cnt] != '\0') + /* Yes, some unknown characters found. */ + error_at_line (0, 0, fname, start_line, + gettext ("malformed line ignored")); + } + + /* We can save the memory for the line if it was not used. */ + if (!used) + obstack_free (¤t->mem_pool, this_line); + } + + if (fp != stdin) + fclose (fp); + return current; +} + + +static void +write_out (struct catalog *catalog, const char *output_name, + const char *header_name) +{ + /* Computing the "optimal" size. */ + struct set_list *set_run; + size_t best_total, best_size, best_depth; + size_t act_size, act_depth; + struct catalog_obj obj; + struct obstack string_pool; + const char *strings; + size_t strings_size; + u_int32_t *array1, *array2; + size_t cnt; + int fd; + + /* If not otherwise told try to read file with existing + translations. */ + if (!force_new) + read_old (catalog, output_name); + + /* Initialize best_size with a very high value. */ + best_total = best_size = best_depth = UINT_MAX; + + /* We need some start size for testing. Let's start with + TOTAL_MESSAGES / 5, which theoretically provides a mean depth of + 5. */ + act_size = 1 + catalog->total_messages / 5; + + /* We determine the size of a hash table here. Because the message + numbers can be chosen arbitrary by the programmer we cannot use + the simple method of accessing the array using the message + number. The algorithm is based on the trivial hash function + NUMBER % TABLE_SIZE, where collisions are stored in a second + dimension up to TABLE_DEPTH. We here compute TABLE_SIZE so that + the needed space (= TABLE_SIZE * TABLE_DEPTH) is minimal. */ + while (act_size <= best_total) + { + size_t deep[act_size]; + + act_depth = 1; + memset (deep, '\0', act_size * sizeof (size_t)); + set_run = catalog->all_sets; + while (set_run != NULL) + { + struct message_list *message_run; + + message_run = set_run->messages; + while (message_run != NULL) + { + size_t idx = (message_run->number * set_run->number) % act_size; + + ++deep[idx]; + if (deep[idx] > act_depth) + { + act_depth = deep[idx]; + if (act_depth * act_size > best_total) + break; + } + message_run = message_run->next; + } + + if (act_depth * act_size <= best_total) + { + /* We have found a better solution. */ + best_total = act_depth * act_size; + best_size = act_size; + best_depth = act_depth; + } + set_run = set_run->next; + } + + ++act_size; + } + + /* let's be prepared for an empty message file. */ + if (best_size == UINT_MAX) + { + best_size = 1; + best_depth = 1; + } + + /* OK, now we have the size we will use. Fill in the header, build + the table and the second one with swapped byte order. */ + obj.magic = CATGETS_MAGIC; + obj.plane_size = best_size; + obj.plane_depth = best_depth; + + /* Allocate room for all needed arrays. */ + array1 = + (u_int32_t *) alloca (best_size * best_depth * sizeof (u_int32_t) * 3); + memset (array1, '\0', best_size * best_depth * sizeof (u_int32_t) * 3); + array2 + = (u_int32_t *) alloca (best_size * best_depth * sizeof (u_int32_t) * 3); + obstack_init (&string_pool); + + set_run = catalog->all_sets; + while (set_run != NULL) + { + struct message_list *message_run; + + message_run = set_run->messages; + while (message_run != NULL) + { + size_t idx = (((message_run->number * set_run->number) % best_size) + * 3); + /* Determine collision depth. */ + while (array1[idx] != 0) + idx += best_size * 3; + + /* Store set number, message number and pointer into string + space, relative to the first string. */ + array1[idx + 0] = set_run->number; + array1[idx + 1] = message_run->number; + array1[idx + 2] = obstack_object_size (&string_pool); + + /* Add current string to the continuous space containing all + strings. */ + obstack_grow0 (&string_pool, message_run->message, + strlen (message_run->message)); + + message_run = message_run->next; + } + + set_run = set_run->next; + } + strings_size = obstack_object_size (&string_pool); + strings = obstack_finish (&string_pool); + + /* Compute ARRAY2 by changing the byte order. */ + for (cnt = 0; cnt < best_size * best_depth * 3; ++cnt) + array2[cnt] = SWAPU32 (array1[cnt]); + + /* Now we can write out the whole data. */ + if (strcmp (output_name, "-") == 0 + || strcmp (output_name, "/dev/stdout") == 0) + fd = STDOUT_FILENO; + else + { + fd = creat (output_name, 0666); + if (fd < 0) + error (EXIT_FAILURE, errno, gettext ("cannot open output file `%s'"), + output_name); + } + + /* Write out header. */ + write (fd, &obj, sizeof (obj)); + + /* We always write out the little endian version of the index + arrays. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + write (fd, array1, best_size * best_depth * sizeof (u_int32_t) * 3); + write (fd, array2, best_size * best_depth * sizeof (u_int32_t) * 3); +#elif __BYTE_ORDER == __BIG_ENDIAN + write (fd, array2, best_size * best_depth * sizeof (u_int32_t) * 3); + write (fd, array1, best_size * best_depth * sizeof (u_int32_t) * 3); +#else +# error Cannot handle __BYTE_ORDER byte order +#endif + + /* Finally write the strings. */ + write (fd, strings, strings_size); + + if (fd != STDOUT_FILENO) + close (fd); + + /* If requested now write out the header file. */ + if (header_name != NULL) + { + int first = 1; + FILE *fp; + + /* Open output file. "-" or "/dev/stdout" means write to + standard output. */ + if (strcmp (header_name, "-") == 0 + || strcmp (header_name, "/dev/stdout") == 0) + fp = stdout; + else + { + fp = fopen (header_name, "w"); + if (fp == NULL) + error (EXIT_FAILURE, errno, + gettext ("cannot open output file `%s'"), header_name); + } + + /* Iterate over all sets and all messages. */ + set_run = catalog->all_sets; + while (set_run != NULL) + { + struct message_list *message_run; + + /* If the current message set has a symbolic name write this + out first. */ + if (set_run->symbol != NULL) + fprintf (fp, "%s#define %sSet %#x\t/* %s:%u */\n", + first ? "" : "\n", set_run->symbol, set_run->number - 1, + set_run->fname, set_run->line); + first = 0; + + message_run = set_run->messages; + while (message_run != NULL) + { + /* If the current message has a symbolic name write + #define out. But we have to take care for the set + not having a symbolic name. */ + if (message_run->symbol != NULL) + if (set_run->symbol == NULL) + fprintf (fp, "#define AutomaticSet%d%s %#x\t/* %s:%u */\n", + set_run->number, message_run->symbol, + message_run->number, message_run->fname, + message_run->line); + else + fprintf (fp, "#define %s%s %#x\t/* %s:%u */\n", + set_run->symbol, message_run->symbol, + message_run->number, message_run->fname, + message_run->line); + + message_run = message_run->next; + } + + set_run = set_run->next; + } + + if (fp != stdout) + fclose (fp); + } +} + + +static struct set_list * +find_set (struct catalog *current, int number) +{ + struct set_list *result = current->all_sets; + + /* We must avoid set number 0 because a set of this number signals + in the tables that the entry is not occupied. */ + ++number; + + while (result != NULL) + if (result->number == number) + return result; + else + result = result->next; + + /* Prepare new message set. */ + result = (struct set_list *) xmalloc (sizeof (*result)); + result->number = number; + result->deleted = 0; + result->messages = NULL; + result->next = current->all_sets; + current->all_sets = result; + + return result; +} + + +/* Normalize given string *in*place* by processing escape sequences + and quote characters. */ +static void +normalize_line (const char *fname, size_t line, char *string, char quote_char) +{ + int is_quoted; + char *rp = string; + char *wp = string; + + if (quote_char != '\0' && *rp == quote_char) + { + is_quoted = 1; + ++rp; + } + else + is_quoted = 0; + + while (*rp != '\0') + if (*rp == quote_char) + /* We simply end the string when we find the first time an + not-escaped quote character. */ + break; + else if (*rp == '\\') + { + ++rp; + if (quote_char != '\0' && *rp == quote_char) + /* This is an extension to XPG. */ + *wp++ = *rp++; + else + /* Recognize escape sequences. */ + switch (*rp) + { + case 'n': + *wp++ = '\n'; + ++rp; + break; + case 't': + *wp++ = '\t'; + ++rp; + break; + case 'v': + *wp++ = '\v'; + ++rp; + break; + case 'b': + *wp++ = '\b'; + ++rp; + break; + case 'r': + *wp++ = '\r'; + ++rp; + break; + case 'f': + *wp++ = '\f'; + ++rp; + break; + case '\\': + *wp++ = '\\'; + ++rp; + break; + case '0' ... '7': + { + int number = *rp++ - '0'; + while (number <= (255 / 8) && *rp >= '0' && *rp <= '7') + { + number *= 8; + number += *rp++ - '0'; + } + *wp++ = (char) number; + } + break; + default: + /* Simply ignore the backslash character. */ + break; + } + } + else + *wp++ = *rp++; + + /* If we saw a quote character at the beginning we expect another + one at the end. */ + if (is_quoted && *rp != quote_char) + error (0, 0, fname, line, gettext ("unterminated message")); + + /* Terminate string. */ + *wp = '\0'; + return; +} + + +static void +read_old (struct catalog *catalog, const char *file_name) +{ + struct catalog_info old_cat_obj; + struct set_list *set = NULL; + int last_set = -1; + size_t cnt; + + old_cat_obj.status = closed; + old_cat_obj.cat_name = file_name; + + /* Try to open catalog, but don't look through the NLSPATH. */ + __open_catalog (&old_cat_obj, 0); + + if (old_cat_obj.status != mmaped && old_cat_obj.status != malloced) + if (errno == ENOENT) + /* No problem, the catalog simply does not exist. */ + return; + else + error (EXIT_FAILURE, errno, gettext ("while opening old catalog file")); + + /* OK, we have the catalog loaded. Now read all messages and merge + them. When set and message number clash for any message the new + one is used. */ + for (cnt = 0; cnt < old_cat_obj.plane_size * old_cat_obj.plane_depth; ++cnt) + { + struct message_list *message, *last; + + if (old_cat_obj.name_ptr[cnt * 3 + 0] == 0) + /* No message in this slot. */ + continue; + + if (old_cat_obj.name_ptr[cnt * 3 + 0] - 1 != last_set) + { + last_set = old_cat_obj.name_ptr[cnt * 3 + 0] - 1; + set = find_set (catalog, old_cat_obj.name_ptr[cnt * 3 + 0] - 1); + } + + last = NULL; + message = set->messages; + while (message != NULL) + { + if (message->number >= old_cat_obj.name_ptr[cnt * 3 + 1]) + break; + last = message; + message = message->next; + } + + if (message == NULL + || message->number > old_cat_obj.name_ptr[cnt * 3 + 1]) + { + /* We have found a message which is not yet in the catalog. + Insert it at the right position. */ + struct message_list *newp; + + newp = (struct message_list *) xmalloc (sizeof(*newp)); + newp->number = old_cat_obj.name_ptr[cnt * 3 + 1]; + newp->message = + &old_cat_obj.strings[old_cat_obj.name_ptr[cnt * 3 + 2]]; + newp->fname = NULL; + newp->line = 0; + newp->symbol = NULL; + newp->next = message; + + if (last == NULL) + set->messages = newp; + else + last->next = newp; + + ++catalog->total_messages; + } + } +} diff --git a/catgets/nl_types.h b/catgets/nl_types.h new file mode 100644 index 0000000000..9f78d67468 --- /dev/null +++ b/catgets/nl_types.h @@ -0,0 +1,48 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +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. */ + +#ifndef _NL_TYPES_H +#define _NL_TYPES_H 1 +#include <features.h> + +/* The default message set used by the gencat program. */ +#define NL_SETD 1 + +/* Value for FLAG parameter of `catgets' to say we want XPG4 compliance. */ +#define NL_CAT_LOCALE 1 + +/* Message catalog descriptor type. */ +typedef void *nl_catd; + + +__BEGIN_DECLS + +/* Open message catalog for later use, returning descriptor. */ +extern nl_catd catopen __P ((__const char *__cat_name, int __flag)); + +/* Return translation with NUMBER in SET of CATALOG; if not found + return STRING. */ +extern char *catgets __P ((nl_catd __catalog, int __set, int __number, + __const char *__string)); + +/* Close message CATALOG. */ +extern int catclose __P ((nl_catd __catalog)); + +__END_DECLS + +#endif /* nl_types.h */ diff --git a/catgets/open_catalog.c b/catgets/open_catalog.c new file mode 100644 index 0000000000..9a8c7e643e --- /dev/null +++ b/catgets/open_catalog.c @@ -0,0 +1,263 @@ +/* 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>. + +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 <endian.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> + +#include "catgetsinfo.h" + + +#define SWAPU32(w) \ + (((w) << 24) | (((w) & 0xff00) << 8) | (((w) >> 8) & 0xff00) | ((w) >> 24)) + + +void +__open_catalog (__nl_catd catalog, int with_path) +{ + int fd; + struct stat st; + int swapping; + + if (strchr (catalog->cat_name, '/') != NULL || !with_path) + fd = open (catalog->cat_name, O_RDONLY); + else + { + const char *run_nlspath = catalog->nlspath; +#define ENOUGH(n) \ + if (bufact + (n) >=bufmax) \ + { \ + char *old_buf = buf; \ + bufmax += 256 + (n); \ + buf = (char *) alloca (bufmax); \ + memcpy (buf, old_buf, bufact); \ + } + + /* The RUN_NLSPATH variable contains a colon separated list of + descriptions where we expect to find catalogs. We have to + recognize certain % substitutions and stop when we found the + first existing file. */ + char *buf; + size_t bufact; + size_t bufmax; + + buf = NULL; + bufmax = 0; + + fd = -1; + while (*run_nlspath != '\0') + { + bufact = 0; + while (*run_nlspath != ':' && *run_nlspath != '\0') + if (*run_nlspath == '%') + { + const char *tmp; + + ++run_nlspath; /* We have seen the `%'. */ + switch (*run_nlspath++) + { + case 'N': + /* Use the catalog name. */ + ENOUGH (strlen (catalog->cat_name)); + bufact = stpcpy (&buf[bufact], catalog->cat_name) - buf; + break; + case 'L': + /* Use the current locale category value. */ + ENOUGH (strlen (catalog->env_var)); + bufact = stpcpy (&buf[bufact], catalog->env_var) - buf; + break; + case 'l': + /* Use language element of locale category value. */ + tmp = catalog->env_var; + do + { + ENOUGH (1); + buf[bufact++] = *tmp++; + } + while (*tmp != '\0' && *tmp != '_' && *tmp != '.'); + break; + case 't': + /* Use territory element of locale category value. */ + tmp = catalog->env_var; + do + ++tmp; + while (*tmp != '\0' && *tmp != '_' && *tmp != '.'); + if (*tmp == '_') + { + ++tmp; + do + { + ENOUGH (1); + buf[bufact++] = *tmp; + } + while (*tmp != '\0' && *tmp != '.'); + } + break; + case 'c': + /* Use code set element of locale category value. */ + tmp = catalog->env_var; + do + ++tmp; + while (*tmp != '\0' && *tmp != '.'); + if (*tmp == '.') + { + ++tmp; + do + { + ENOUGH (1); + buf[bufact++] = *tmp; + } + while (*tmp != '\0'); + } + break; + case '%': + ENOUGH (1); + buf[bufact++] = '%'; + break; + default: + /* Unknown variable: ignore this path element. */ + bufact = 0; + while (*run_nlspath != '\0' && *run_nlspath != ':') + ++run_nlspath; + break; + } + } + else + { + ENOUGH (1); + buf[bufact++] = *run_nlspath++; + } + ENOUGH (1); + buf[bufact] = '\0'; + + if (bufact != 0) + { + fd = open (buf, O_RDONLY); + if (fd >= 0) + break; + } + + ++run_nlspath; + } + } + + if (fd < 0 || fstat (fd, &st) < 0) + { + catalog->status = nonexisting; + return; + } + +#ifndef MAP_COPY + /* 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. */ +#define MAP_FILE 0 +#endif +#ifndef MAP_INHERIT + /* Some systems might lack this; they lose. */ +#define MAP_INHERIT 0 +#endif + catalog->file_size = st.st_size; + catalog->file_ptr = + (struct catalog_obj *) mmap (NULL, st.st_size, PROT_READ, + MAP_FILE|MAP_COPY|MAP_INHERIT, fd, 0); + if (catalog->file_ptr != (struct catalog_obj *) -1) + /* Tell the world we managed to mmap the file. */ + catalog->status = mmaped; + else + { + /* mmap failed perhaps because the system call is not + implemented. Try to load the file. */ + size_t todo; + catalog->file_ptr = malloc (st.st_size); + if (catalog->file_ptr == NULL) + { + catalog->status = nonexisting; + return; + } + todo = st.st_size; + /* Save read, handle partial reads. */ + do + { + size_t now = read (fd, (((char *) &catalog->file_ptr) + + (st.st_size - todo)), todo); + if (now == 0) + { + free ((void *) catalog->file_ptr); + catalog->status = nonexisting; + return; + } + todo -= now; + } + while (todo > 0); + catalog->status = malloced; + } + + /* We don't need the file anymore. */ + close (fd); + + /* Determine whether the file is a catalog file and if yes whether + it is written using the correct byte order. Else we have to swap + the values. */ + if (catalog->file_ptr->magic == CATGETS_MAGIC) + swapping = 0; + else if (catalog->file_ptr->magic == SWAPU32 (CATGETS_MAGIC)) + swapping = 1; + else + { + /* Illegal file. Free he resources and mark catalog as not + usable. */ + if (catalog->status == mmaped) + munmap ((void *) catalog->file_ptr, catalog->file_size); + else + free (catalog->file_ptr); + catalog->status = nonexisting; + return; + } + +#define SWAP(x) (swapping ? SWAPU32 (x) : (x)) + + /* Get dimensions of the used hashing table. */ + catalog->plane_size = SWAP (catalog->file_ptr->plane_size); + catalog->plane_depth = SWAP (catalog->file_ptr->plane_depth); + + /* The file contains two versions of the pointer tables. Pick the + right one for the local byte order. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + catalog->name_ptr = &catalog->file_ptr->name_ptr[0]; +#elif __BYTE_ORDER == __BIG_ENDIAN + catalog->name_ptr = &catalog->file_ptr->name_ptr[catalog->plane_size + * catalog->plane_depth + * 3]; +#else +# error Cannot handle __BYTE_ORDER byte order +#endif + + /* The rest of the file contains all the strings. They are + addressed relative to the position of the first string. */ + catalog->strings = + (const char *) &catalog->file_ptr->name_ptr[catalog->plane_size + * catalog->plane_depth * 3 * 2]; +} diff --git a/config.make.in b/config.make.in index 50571745d0..593d9ca908 100644 --- a/config.make.in +++ b/config.make.in @@ -17,6 +17,8 @@ config-defines = @DEFS@ elf = @elf@ have-initfini = @libc_cv_have_initfini@ +have-no-whole-archive = @libc_cv_ld_no_whole_archive@ + # Configuration options. gnu-as = @gnu_as@ gnu-ld = @gnu_ld@ diff --git a/configure.in b/configure.in index 734c5ad324..711635cc5d 100644 --- a/configure.in +++ b/configure.in @@ -469,6 +469,19 @@ elif test $libc_cv_asm_weakext_directive = yes; then AC_DEFINE(HAVE_ASM_WEAKEXT_DIRECTIVE) fi +AC_CACHE_CHECK(for ld --no-whole-archive, libc_cv_ld_no_whole_archive, [dnl +cat > conftest.c <<\EOF +main () { exit (0); } +EOF +if ${CC-cc} $CFLAGS -Wl,--no-whole-archive \ + -o conftest conftest.c 2>/dev/null; then + libc_cv_ld_no_whole_archive=yes +else + libc_cv_ld_no_whole_archive=no +fi +rm -f conftest*]) +AC_SUBST(libc_cv_ld_no_whole_archive)dnl + ### End of automated tests. ### Now run sysdeps configure fragments. diff --git a/elf/Makefile b/elf/Makefile index a77460d1de..dfb307b682 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -1,6 +1,6 @@ # Makefile for elf subdirectory of GNU C Library. -# Copyright (C) 1995 Free Software Foundation, Inc. +# Copyright (C) 1995, 1996 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -80,7 +80,7 @@ $(objpfx)libdl.so: $(objpfx)libdl_pic.a $(common-objpfx)libc.so $(objpfx)ld.so $(patsubst %/,cd %;,$(objpfx)) \ $(LINK.o) -shared -o $(@:$(objpfx)%=%) \ $(LDFLAGS.so) $(LDFLAGS-dl.so) \ - -Wl,--whole-archive $(^:$(objpfx)%=%) + -Wl,--whole-archive $(^:$(objpfx)%=%) $(no-whole-archive) $(slibdir)/$(rtld-installed-name): $(objpfx)ld.so; $(do-install-program) $(slibdir)/ld-linux.so.1: $(objpfx)ld-linux.so.1; $(do-install-program) diff --git a/locale/Makefile b/locale/Makefile index 0a30cd27d3..7399eda735 100644 --- a/locale/Makefile +++ b/locale/Makefile @@ -21,7 +21,7 @@ # subdir := locale -headers = locale.h +headers = locale.h langinfo.h distribute = localeinfo.h categories.def \ $(localedef-modules:=.c) $(locale-modules:=.c) \ $(lib-modules:=.c) config.h simple-hash.h iso-4217.def \ @@ -60,7 +60,7 @@ $(objpfx)localedef $(objpfx)locale: $(lib-modules:%=$(objpfx)%.o) CPPFLAGS := -DLOCALE_PATH='"$(localedir)"' \ -DCHARMAP_PATH='"$(i18ndir)/charmap"' \ -DLOCSRCDIR='"$(i18ndir)/locales"' -DHAVE_CONFIG_H \ - -Iliblib -Iprograms $(CPPFLAGS) + -Iprograms $(CPPFLAGS) CFLAGS-charmap.c = -Wno-write-strings CFLAGS-locfile.c = -Wno-write-strings diff --git a/math/Makefile b/math/Makefile index a2ceb06925..48652167ad 100644 --- a/math/Makefile +++ b/math/Makefile @@ -71,5 +71,9 @@ include ../Rules # the error return conventions for the math functions. CPPFLAGS-s_lib_version.c := -D_POSIX_MODE +# We don't want the fdlibm code to use the inline math functions, +# only the fdlibm code. +CPPFLAGS += -D__NO_MATH_INLINES + # The fdlibm code generates a lot of these warnings but is otherwise clean. override CFLAGS += -Wno-uninitialized -Wno-write-strings diff --git a/posix/regex.c b/posix/regex.c index ee066b5efa..dc831cecd1 100644 --- a/posix/regex.c +++ b/posix/regex.c @@ -1007,7 +1007,7 @@ static const char *re_error_msgid[] = #endif /* Roughly the maximum number of failure points on the stack. Would be - exactly that if always used MAX_FAILURE_SPACE each time we failed. + exactly that if always used MAX_FAILURE_ITEMS items each time we failed. This is a variable only so users of regex can assign to it; we never change it ourselves. */ #if defined (MATCH_MAY_ALLOCATE) @@ -1224,7 +1224,10 @@ typedef struct #endif /* We push at most this many items on the stack. */ -#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS) +/* We used to use (num_regs - 1), which is the number of registers + this regexp will save; but that was changed to 5 + to avoid stack overflow for a regexp with lots of parens. */ +#define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS) /* We actually push this many items. */ #define NUM_FAILURE_ITEMS \ diff --git a/resolv/getnetnamadr.c b/resolv/getnetnamadr.c index e5cc505d04..b2c911844e 100644 --- a/resolv/getnetnamadr.c +++ b/resolv/getnetnamadr.c @@ -154,7 +154,7 @@ static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1]; cp += n; return (NULL); } - cp += n; + cp += n; *ap++ = bp; bp += strlen(bp) + 1; net_entry.n_addrtype = @@ -189,7 +189,7 @@ static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1]; paux1 = pauxt; } in = ++st; - } + } net_entry.n_net = inet_network(paux2); break; } @@ -209,7 +209,7 @@ getnetbyaddr(net, net_type) int nn, anslen; querybuf buf; char qbuf[MAXDNAME]; - unsigned long net2; + u_int32_t net2; struct netent *net_entry; if (net_type != AF_INET) diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c index 009bdee0d5..4e6104a71b 100644 --- a/stdio-common/printf_fp.c +++ b/stdio-common/printf_fp.c @@ -337,7 +337,7 @@ __printf_fp (FILE *fp, would be really big it could lead to memory problems. */ { mp_size_t bignum_size = ((ABS (exponent) + BITS_PER_MP_LIMB - 1) - / BITS_PER_MP_LIMB + 3) * sizeof (mp_limb); + / BITS_PER_MP_LIMB + 4) * sizeof (mp_limb); frac = (mp_limb *) alloca (bignum_size); tmp = (mp_limb *) alloca (bignum_size); scale = (mp_limb *) alloca (bignum_size); diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 26b31a6ed2..04f9e0d5f1 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -895,7 +895,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) tmp = ++f; if (ISDIGIT (*tmp) && read_int (&tmp) && *tmp == L_('$')) - /* The width comes from an positional parameter. */ + /* The width comes from a positional parameter. */ goto do_positional; width = va_arg (ap, int); @@ -914,7 +914,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) LABEL (width): width = read_int (&f); if (*f == L_('$')) - /* Oh, oh. The argument comes from an positional parameter. */ + /* Oh, oh. The argument comes from a positional parameter. */ goto do_positional; JUMP (*f, step1_jumps); @@ -926,7 +926,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) tmp = ++f; if (ISDIGIT (*tmp) && read_int (&tmp) > 0 && *tmp == L_('$')) - /* The precision comes from an positional parameter. */ + /* The precision comes from a positional parameter. */ goto do_positional; prec = va_arg (ap, int); diff --git a/stdlib/rpmatch.c b/stdlib/rpmatch.c index 0dcaa6dc87..4774e2cf45 100644 --- a/stdlib/rpmatch.c +++ b/stdlib/rpmatch.c @@ -30,7 +30,7 @@ rpmatch (response) { /* Match against one of the response patterns, compiling the pattern first if necessary. */ - inline int try (const int tag, const int match, + inline int try (const int tag, const int match, const int nomatch, const char **lastp, regex_t *re) { const char *pattern = nl_langinfo (tag); @@ -50,13 +50,13 @@ rpmatch (response) } /* Try the pattern. */ - return regexec (re, response, 0, NULL, 0) == 0 ? match : !match; + return regexec (re, response, 0, NULL, 0) == 0 ? match : nomatch; } /* We cache the response patterns and compiled regexps here. */ static const char *yesexpr, *noexpr; static regex_t yesre, nore; - return (try (YESEXPR, 1, &yesexpr, &yesre) ?: - try (NOEXPR, 0, &noexpr, &nore)); + return (try (YESEXPR, 1, 0, &yesexpr, &yesre) ?: + try (NOEXPR, 0, -1, &noexpr, &nore)); } diff --git a/sysdeps/libm-ieee754/w_gammaf.c b/sysdeps/libm-ieee754/w_gammaf.c index d0058df9ef..c2d21daf47 100644 --- a/sysdeps/libm-ieee754/w_gammaf.c +++ b/sysdeps/libm-ieee754/w_gammaf.c @@ -20,7 +20,7 @@ static char rcsid[] = "$NetBSD: w_gammaf.c,v 1.4 1995/11/20 22:06:48 jtc Exp $"; #include "math.h" #include "math_private.h" -extern int __signgam; +extern int signgam; #ifdef __STDC__ float __gammaf(float x) @@ -30,10 +30,10 @@ extern int __signgam; #endif { #ifdef _IEEE_LIBM - return __ieee754_lgammaf_r(x,&__signgam); + return __ieee754_lgammaf_r(x,&signgam); #else float y; - y = __ieee754_lgammaf_r(x,&__signgam); + y = __ieee754_lgammaf_r(x,&signgam); if(_LIB_VERSION == _IEEE_) return y; if(!__finitef(y)&&__finitef(x)) { if(__floorf(x)==x&&x<=(float)0.0) diff --git a/sysdeps/libm-ieee754/w_lgamma.c b/sysdeps/libm-ieee754/w_lgamma.c index 9868f05782..2563d28f8d 100644 --- a/sysdeps/libm-ieee754/w_lgamma.c +++ b/sysdeps/libm-ieee754/w_lgamma.c @@ -23,7 +23,7 @@ static char rcsid[] = "$NetBSD: w_lgamma.c,v 1.6 1995/05/10 20:49:24 jtc Exp $"; #include "math.h" #include "math_private.h" -extern int __signgam; +extern int signgam; #ifdef __STDC__ double __lgamma(double x) @@ -33,10 +33,10 @@ extern int __signgam; #endif { #ifdef _IEEE_LIBM - return __ieee754_lgamma_r(x,&__signgam); + return __ieee754_lgamma_r(x,&signgam); #else double y; - y = __ieee754_lgamma_r(x,&__signgam); + y = __ieee754_lgamma_r(x,&signgam); if(_LIB_VERSION == _IEEE_) return y; if(!__finite(y)&&__finite(x)) { if(__floor(x)==x&&x<=0.0) diff --git a/sysdeps/libm-ieee754/w_lgammaf.c b/sysdeps/libm-ieee754/w_lgammaf.c index 351b7acd33..1fd15a3110 100644 --- a/sysdeps/libm-ieee754/w_lgammaf.c +++ b/sysdeps/libm-ieee754/w_lgammaf.c @@ -20,7 +20,7 @@ static char rcsid[] = "$NetBSD: w_lgammaf.c,v 1.3 1995/05/10 20:49:30 jtc Exp $" #include "math.h" #include "math_private.h" -extern int __signgam; +extern int signgam; #ifdef __STDC__ float __lgammaf(float x) @@ -30,10 +30,10 @@ extern int __signgam; #endif { #ifdef _IEEE_LIBM - return __ieee754_lgammaf_r(x,&__signgam); + return __ieee754_lgammaf_r(x,&signgam); #else float y; - y = __ieee754_lgammaf_r(x,&__signgam); + y = __ieee754_lgammaf_r(x,&signgam); if(_LIB_VERSION == _IEEE_) return y; if(!__finitef(y)&&__finitef(x)) { if(__floorf(x)==x&&x<=(float)0.0) diff --git a/time/etcetera b/time/etcetera index ed619aecfa..73ad68ee0a 100644 --- a/time/etcetera +++ b/time/etcetera @@ -1,4 +1,4 @@ -# @(#)etcetera 7.4 +# @(#)etcetera 7.5 # All of these are set up just so people can "zic -l" to a timezone # that's right for their area, even if it doesn't have a name or DST rules @@ -27,7 +27,8 @@ Link Etc/GMT Etc/GMT0 # zic -l GMT-12 # so we moved the names into the Etc subdirectory. -Zone Etc/GMT-13 13 - GMT-13 # 12 hours ahead of GMT, plus DST +Zone Etc/GMT-14 14 - GMT-14 # 14 hours ahead of GMT +Zone Etc/GMT-13 13 - GMT-13 Zone Etc/GMT-12 12 - GMT-12 Zone Etc/GMT-11 11 - GMT-11 Zone Etc/GMT-10 10 - GMT-10 diff --git a/time/europe b/time/europe index 85c05eef11..04273d277c 100644 --- a/time/europe +++ b/time/europe @@ -1,4 +1,4 @@ -# @(#)europe 7.31 +# @(#)europe 7.33 # This data is by no means authoritative; if you think you know better, # go ahead and edit the file (and please send any changes to @@ -1644,7 +1644,12 @@ Zone Europe/Lisbon -0:36:32 - LMT 1884 # From Rui Pedro Salgueiro <rps@inescca.inescc.pt> (November 12, 1992): # Portugal has recently (September, 27) changed timezone # (from WET to MET or CET) to harmonize with EEC. - 1:00 EC MET%s + 1:00 EC MET%s 1996 Mar 31 1:00u +# Martin Bruckmann <martin@ua.pt> (1996-02-29) reports via Peter Ilieve +# that Portugal is reverting to 0:00 by not moving its clocks this spring. +# The new Prime Minister was fed up with getting up in the dark in the winter. + 0:00 1:00 "WET DST" 1996 Oct 27 1:00u + 0:00 EC WET%s # We don't know what happened to Madeira or the Azores, # so we'll just use Shanks for now. # Zone NAME GMTOFF RULES FORMAT [UNTIL] diff --git a/time/solar89 b/time/solar89 index 5a720a8dfd..a6d3d718d3 100644 --- a/time/solar89 +++ b/time/solar89 @@ -1,4 +1,4 @@ -# @(#)solar89 7.3 +# @(#)solar89 7.4 # Apparent noon times below are for Riyadh; they're a bit off for other places. # Times were computed using a formula provided by the U. S. Naval Observatory: @@ -390,4 +390,4 @@ Zone Asia/Riyadh89 3:07:04 - ?? 1989 3:07:04 sol89 ?? 1990 3:07:04 - ?? # For backward compatibility... -Link Asia/Riyadh88 Mideast/Riyadh88 +Link Asia/Riyadh89 Mideast/Riyadh89 |