Fri Apr 19 00:49:44 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> cvs/libc-960420
authorRoland McGrath <roland@gnu.org>
Sat, 20 Apr 1996 00:05:25 +0000 (00:05 +0000)
committerRoland McGrath <roland@gnu.org>
Sat, 20 Apr 1996 00:05:25 +0000 (00:05 +0000)
* 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.

28 files changed:
ChangeLog
Make-dist
Makeconfig
Makefile
Makerules
catgets/Makefile [new file with mode: 0644]
catgets/catgets.c [new file with mode: 0644]
catgets/catgetsinfo.h [new file with mode: 0644]
catgets/config.h [new file with mode: 0644]
catgets/gencat.c [new file with mode: 0644]
catgets/nl_types.h [new file with mode: 0644]
catgets/open_catalog.c [new file with mode: 0644]
config.make.in
configure.in
elf/Makefile
locale/Makefile
math/Makefile
posix/regex.c
resolv/getnetnamadr.c
stdio-common/printf_fp.c
stdio-common/vfprintf.c
stdlib/rpmatch.c
sysdeps/libm-ieee754/w_gammaf.c
sysdeps/libm-ieee754/w_lgamma.c
sysdeps/libm-ieee754/w_lgammaf.c
time/etcetera
time/europe
time/solar89

index 6ba5054..3966fcd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index 9ec795e..d388142 100644 (file)
--- a/Make-dist
+++ b/Make-dist
@@ -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
 
index 3273675..e0522ab 100644 (file)
@@ -468,6 +468,13 @@ cross-compiling := yes
 else
 cross-compiling := no
 endif
+\f
+# 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
index 30e0204..68ad32d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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
index cb22d03..a163378 100644 (file)
--- a/Makerules
+++ b/Makerules
@@ -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 (file)
index 0000000..4646dd5
--- /dev/null
@@ -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 (file)
index 0000000..ca0fdd6
--- /dev/null
@@ -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 (file)
index 0000000..7e0a26f
--- /dev/null
@@ -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 (file)
index 0000000..ce7887b
--- /dev/null
@@ -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 (file)
index 0000000..4b6eb43
--- /dev/null
@@ -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 (&current->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 (&current->mem_pool, buf, act_len);
+       }
+      while (continued);
+
+      obstack_1grow (&current->mem_pool, '\0');
+      this_line = (char *) obstack_finish (&current->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 (&current->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 (file)
index 0000000..9f78d67
--- /dev/null
@@ -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 (file)
index 0000000..9a8c7e6
--- /dev/null
@@ -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];
+}
index 5057174..593d9ca 100644 (file)
@@ -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@
index 734c5ad..711635c 100644 (file)
@@ -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.
 
index a77460d..dfb307b 100644 (file)
@@ -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)
index 0a30cd2..7399eda 100644 (file)
@@ -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
index a2ceb06..4865216 100644 (file)
@@ -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
index ee066b5..dc831ce 100644 (file)
@@ -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                              \
index e5cc505..b2c9118 100644 (file)
@@ -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)
index 009bdee..4e6104a 100644 (file)
@@ -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);
index 26b31a6..04f9e0d 100644 (file)
@@ -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);
index 0dcaa6d..4774e2c 100644 (file)
@@ -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));
 }
index d0058df..c2d21da 100644 (file)
@@ -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)
index 9868f05..2563d28 100644 (file)
@@ -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)
index 351b7ac..1fd15a3 100644 (file)
@@ -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)
index ed619ae..73ad68e 100644 (file)
@@ -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
index 85c05ee..04273d2 100644 (file)
@@ -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]
index 5a720a8..a6d3d71 100644 (file)
@@ -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