summary refs log tree commit diff
path: root/locale/programs/localedef.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1996-03-28 08:30:38 +0000
committerRoland McGrath <roland@gnu.org>1996-03-28 08:30:38 +0000
commit19bc17a90548ee427035994bbc4b14395723ff1f (patch)
treee7a17eda196c2610ca4be26c9e7985815162eafb /locale/programs/localedef.c
parent53f770e0f9d405ea8d1888254c6f7ce431b04c6e (diff)
downloadglibc-19bc17a90548ee427035994bbc4b14395723ff1f.tar.gz
glibc-19bc17a90548ee427035994bbc4b14395723ff1f.tar.xz
glibc-19bc17a90548ee427035994bbc4b14395723ff1f.zip
Thu Mar 28 03:25:10 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu>
	* intl/Makefile (copysrc): Add missing > in sed cmd.

Sat Mar 23 17:52:49 1996  Ulrich Drepper  <drepper@gnu.ai.mit.edu>

	* Makeconfig: Rename Makefile variable nlsdir to i18ndir and
	change value to $(datadir)/i18n.  `nls' is not an appropriate
	name.

	* Makefile (subdirs): Add new subdir wctype.

	* ctype/ctype-info.c: Add new global variable __ctype_names
	and initialize from _nl_C_LC_CTYPE.

	* ctype/ctype.h: In P1003.3b/D11 `alnum' is a separate character
        class.  Use bit 11.
	[_ISbit]: Protect definition of bitmasks because they are also
	used in wctype.h.

	* libio/genops.c (_IO_sputbackc, _IO_sungetc): Clear EOF flag
	after successfully pushing back a character.

	Fundamental changes in locale implementation.  Almost nothing
	from the old code is used anymore.
	* locale/charmap.c, locale/collate.c, locale/config.h,
 	locale/ctypedump.c, locale/hash.h, locale/keyword.gperf,
 	locale/keyword.h, locale/loadlocale.c, locale/locale-ctype.c,
 	locale/locale.c locale/localeconv.c, locale/localedef.c,
 	locale/localedef.h, locale/locfile-hash.c, locale/locfile-lex.c,
 	locale/locfile-parse.c, locale/messages.c, locale/monetary.c,
 	locale/numeric.c, locale/setlocale.c, locale/token.h,
 	locale/xmalloc.c: Removed.

	* locale/Makefile: Update for new locale implementation with
	program source code distributed in subdir.

	* locale/categories.def, locale/iso-4217.def: Updated file
        for new locale implementation.

	* locale/langinfo.h: Updated for new locale implementation.
	(ERA_D_T_FMT, ERA_T_FMT): New official values according to
	P1003.2b/D11.
	(_NL_COLLATE_NRULES, _NL_COLLATE_RULES, _NL_COLLATE_HASH_SIZE,
	_NL_COLLATE_HASH_LAYERS, _NL_COLLATE_TABLE_EB,
	_NL_COLLATE_TABLE_EL, _NL_COLLATE_UNDEFINED, _NL_COLLATE_EXTRA_EB,
	_NL_COLLATE_EXTRA_EL, _NL_CTYPE_NAMES_EB, _NL_CTYPE_NAMES_EL,
	_NL_CTYPE_HASH_SIZE, _NL_CTYPE_HASH_LAYERS, _NL_CTYPE_CLASS_NAMES,
	_NL_CTYPE_MAP_NAMES, _NL_CTYPE_WIDTH): New internal values for
	extended LC_CTYPE and LC_COLLATE implementation.

	* locale/simple-hash.c, locale/simple-hash.h, locale/xmalloc.c,
 	locale/xstrdup.c: Helper functions for locale related programs.

	* locale/C-collate.c, locale/C-ctype.c,
        locale/C-messages.c, locale/C-monetary.c,
        locale/C-numeric.c, locale/C-time.c,
        locale/lc-collate.c, locale/lc-ctype.c,
        locale/lc-messages.c, locale/lc-monetary.c,
        locale/lc-numeric.c, locale/lc-time.c: New implementation of locale
        functions, and new generated "C" locale data.

	* locale/loadlocale.c: Now handles word fields in locale binary
        automatically by changing the endianess if necessary.

	* locale/localeinfo.h (LIMAGIC): Changed magic number because
	of incompatible changes.
	(locale_data): Changed definition to allow word as a value type.
	(coll_sort_rule): Values for collation sorting mode.
	(_NL_CURRENT_WORD): New macro to access word value of locale entry.
	(__collate_table, __collate_extra): Declare new global variables
	for collation tables.

	* locale/programs/charmap-kw.gperf, locale/programs/charmap-kw.h,
        locale/programs/charmap.c, locale/programs/charset.c,
        locale/programs/charset.h, locale/programs/config.h,
        locale/programs/ctypedump.c, locale/programs/ld-collate.c,
        locale/programs/ld-ctype.c, locale/programs/ld-messages.c,
        locale/programs/ld-monetary.c, locale/programs/ld-numeric.c,
        locale/programs/ld-time.c, locale/programs/linereader.c,
        locale/programs/linereader.h, locale/programs/locale.c,
        locale/programs/localedef.c, locale/programs/locales.h,
        locale/programs/locfile-kw.gperf, locale/programs/locfile-kw.h,
        locale/programs/locfile-token.h, locale/programs/locfile.c,
        locale/programs/locfile.h, locale/programs/stringtrans.c,
        locale/programs/stringtrans.h: Implementation of locale related
        programs.

	* locale/weight.h: Functions to access collation tables.

	* posix/unistd.h: Define _POSIX2_LOCALEDEF.

	* stdio-common/printf_fp.c: Fix bug with printing certain numbers
	< 10^-1.  Reported by Bill Metzenthen.

	* stdio-common/tfformat.c: Add new test for above bug.

	* string/strcoll.c, string/strxfrm.c: Real implementation of
        string collation according to ISO C.

	* wctype/Makefile, wctype/cname-lookup.h, wctype/iswctype.c,
        wctype/test_wctype.c, wctype/towctrans.c, wctype/wcfuncs.c,
        wctype/wctrans.c, wctype/wctype.c, wctype/wctype.h: New files.
        Implementation of wide character classes and mapping.
Diffstat (limited to 'locale/programs/localedef.c')
-rw-r--r--locale/programs/localedef.c461
1 files changed, 461 insertions, 0 deletions
diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c
new file mode 100644
index 0000000000..a98bac4301
--- /dev/null
+++ b/locale/programs/localedef.c
@@ -0,0 +1,461 @@
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
+
+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 <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <libintl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include "error.h"
+#include "charset.h"
+#include "locfile.h"
+
+/* Undefine the following line in the production version.  */
+/* #define NDEBUG 1 */
+#include <assert.h>
+
+
+/* List of locale definition files which are used in `copy' instructions.  */
+struct copy_def_list_t
+{
+  struct copy_def_list_t *next;
+
+  const char *name;
+  int mask;
+
+  struct localedef_t *locale;
+
+  struct
+  {
+    void *data;
+    size_t len;
+  } binary[6];
+};
+
+
+/* List of copied locales.  */
+struct copy_def_list_t *copy_list;
+
+/* If this is defined be POSIX conform.  */
+int posix_conformance;
+
+/* Name of the running program.  */
+const char *program_name;
+
+/* If not zero give a lot more messages.  */
+int verbose;
+
+
+
+/* Long options.  */
+static const struct option long_options[] =
+{
+  { "charmap", required_argument, NULL, 'f' },
+  { "code-set-name", required_argument, NULL, 'u' },
+  { "help", no_argument, NULL, 'h' },
+  { "force", no_argument, NULL, 'c' },
+  { "inputfile", required_argument, NULL, 'i' },
+  { "posix", no_argument, &posix_conformance, 1 },
+  { "verbose", no_argument, &verbose, 1},
+  { "version", no_argument, NULL, 'V' },
+  { NULL, 0, NULL, 0 }
+};
+
+
+/* Prototypes for global functions.  */
+void *xmalloc (size_t __n);
+
+/* Prototypes for local functions.  */
+static void usage (int status) __attribute__ ((noreturn));
+static void error_print (void);
+static const char *construct_output_path (const char *path);
+
+
+int
+main (int argc, char *argv[])
+{
+  int optchar;
+  int do_help = 0;
+  int do_version = 0;
+  int force_output = 0;
+  const char *charmap_file = NULL;
+  const char *input_file = NULL;
+  const char *ucs_csn = NULL;
+  const char *output_path;
+  int cannot_write_why;
+  struct charset_t *charset;
+  struct localedef_t *localedef;
+  struct copy_def_list_t *act_add_locdef;
+
+  /* Set initial values for global varaibles.  */
+  copy_list = NULL;
+  posix_conformance = getenv ("POSIXLY_CORRECT") != NULL;
+  program_name = argv[0];
+  error_print_progname = error_print;
+  verbose = 0;
+
+  /* Set locale.  Do not set LC_ALL because the other categories must
+     not be affected (acccording to POSIX.2).  */
+  setlocale (LC_MESSAGES, "");
+  setlocale (LC_CTYPE, "");
+
+  /* Initialize the message catalog.  */
+#if 0
+  /* In the final version for glibc we can use the variable.  */
+  textdomain (_libc_intl_domainname);
+#else
+  textdomain ("SYS_libc");
+#endif
+
+  while ((optchar = getopt_long (argc, argv, "cf:hi:u:vV", long_options, NULL))
+         != EOF)
+    switch (optchar)
+      {
+      case '\0':		/* Long option.  */
+        break;
+
+      case 'c':
+	force_output = 1;
+	break;
+
+      case 'f':
+        charmap_file = optarg;
+        break;
+
+      case 'h':
+        do_help = 1;
+        break;
+
+      case 'i':
+	input_file = optarg;
+        break;
+
+      case 'u':
+	ucs_csn = optarg;
+	break;
+
+	case 'v':
+        verbose = 1;
+        break;
+
+      case 'V':
+        do_version = 1;
+        break;
+
+      default:
+        usage (4);	/* A value >3 is forced by POSIX.  */
+        break;
+      }
+
+  /* POSIX.2 requires to be verbose about missing characters in the
+     character map.  */
+  verbose |= posix_conformance;
+
+  /* Version information is requested.  */
+  if (do_version)
+    {
+      fprintf (stderr, "%s - GNU %s %s\n", program_name, PACKAGE, VERSION);
+      exit (0);
+    }
+
+  /* Help is requested.  */
+  if (do_help)
+    /* Possible violation: POSIX.2 4.35.8 defines the return value 0 as
+       "No errors occured and the locale(s) were successfully created."
+       But giving a other value than 0 does not make sense here.  It
+       is perhaps not that important because POSIX does not specify the
+       -h option for localedef.  */
+    usage (0);
+
+  if (argc - optind != 1)
+    /* We need exactly one non-option parameter.  */
+    usage (4);
+
+  /* The parameter describes the output path of the constructed files.
+     If the described files cannot be written return a NULL pointer.  */
+  output_path  = construct_output_path (argv[optind]);
+  cannot_write_why = errno;
+
+  /* Now that the parameters are processed we have to reset the local
+     ctype locale.  (P1003.2 4.35.5.2)  */
+  setlocale (LC_CTYPE, "POSIX");
+
+  /* Look whether the system really allows locale definitions.  POSIX
+     defines error code 3 for this situation so I think it must be
+     a fatal error (see P1003.2 4.35.8).  */
+  if (sysconf (_SC_2_LOCALEDEF) < 0)
+    error (3, 0, _("FATAL: system does not define `_POSIX2_LOCALEDEF'"));
+
+  /* Process charmap file.  */
+  charset = charmap_read (charmap_file);
+
+  /* Now read the locale file.  */
+  localedef = locfile_read (input_file, charset);
+  if (localedef->failed != 0)
+    error (4, errno, _("cannot open locale definition file `%s'"), input_file);
+
+  /* Perhaps we saw some `copy' instructions.  Process the given list.
+     We use a very simple algorithm: we look up the list from the
+     beginning every time.  */
+  do
+    {
+      int cat;
+
+      for (act_add_locdef = copy_list; act_add_locdef != NULL;
+	   act_add_locdef = act_add_locdef->next)
+	{
+	  for (cat = LC_COLLATE; cat <= LC_MESSAGES; ++cat)
+	    if ((act_add_locdef->mask & (1 << cat)) != 0)
+	      {
+		act_add_locdef->mask &= ~(1 << cat);
+		break;
+	      }
+	  if (cat <= LC_MESSAGES)
+	    break;
+	}
+
+      if (act_add_locdef != NULL)
+	{
+	  int avail = 0;
+
+	  if (act_add_locdef->locale == NULL)
+	    act_add_locdef->locale = locfile_read (act_add_locdef->name,
+						   charset);
+
+	  if (! act_add_locdef->locale->failed)
+	    {
+	      avail = act_add_locdef->locale->categories[cat].generic != NULL;
+	      if (avail)
+		localedef->categories[cat].generic
+		  = act_add_locdef->locale->categories[cat].generic;
+	    }
+
+	  if (! avail)
+	    {
+	      const char *locale_names[] = { "LC_COLLATE", "LC_CTYPE",
+					     "LC_MONETARY", "LC_NUMERIC",
+					     "LC_TIME", "LC_MESSAGES" };
+	      char *fname;
+	      int fd;
+	      struct stat st;
+
+	      asprintf (&fname, LOCALE_PATH "/%s/%s", act_add_locdef->name,
+			locale_names[cat]);
+	      fd = open (fname, O_RDONLY);
+	      if (fd == -1)
+		{
+		  free (fname);
+
+		  asprintf (&fname, LOCALE_PATH "/%s/%s/SYS_%s",
+			    act_add_locdef->name, locale_names[cat],
+			    locale_names[cat]);
+
+		  fd = open (fname, O_RDONLY);
+		  if (fd == -1)
+		    error (5, 0, _("\
+locale file `%s', used in `copy' statement, not found"),
+			   act_add_locdef->name);
+		}
+
+	      if (fstat (fd, &st) < 0)
+		error (5, errno, _("\
+cannot `stat' locale file `%s'"),
+		       fname);
+
+	      localedef->len[cat] = st.st_size;
+	      localedef->categories[cat].generic
+		= mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+
+	      if (localedef->categories[cat].generic == (void *) -1)
+		{
+		  size_t left = st.st_size;
+		  void *read_ptr;
+
+		  localedef->categories[cat].generic
+		    = xmalloc (st.st_size);
+		  read_ptr = localedef->categories[cat].generic;
+
+		  do
+		    {
+		      long int n;
+		      n = read (fd, read_ptr, left);
+		      if (n == 1)
+			error (5, errno, _("cannot read locale file `%s'"),
+			       fname);
+		      read_ptr += n;
+		      left -= n;
+		    }
+		  while (left > 0);
+		}
+
+	      close (fd);
+	      free (fname);
+
+	      localedef->binary |= 1 << cat;
+	    }
+	}
+    }
+  while (act_add_locdef != NULL);
+
+  /* Check the categories we processed in source form.  */
+  check_all_categories (localedef, charset);
+
+  /* We are now able to write the data files.  If warning were given we
+     do it only if it is explicitly requested (--force).  */
+  if (error_message_count == 0 || force_output != 0)
+    {
+      if (cannot_write_why != 0)
+	error (4, cannot_write_why, _("cannot write output files to `%s'"),
+	       output_path);
+      else
+	write_all_categories (localedef, output_path);
+    }
+  else
+    error (4, 0, _("no output file produced because warning were issued"));
+
+  /* This exit status is prescribed by POSIX.2 4.35.7.  */
+  exit (error_message_count != 0);
+}
+
+
+void
+def_to_process (const char *name, int category)
+{
+  struct copy_def_list_t *new, **rp;
+
+  for (rp = &copy_list; *rp != NULL; rp = &(*rp)->next)
+    if (strcmp (name, (*rp)->name) == 0)
+      break;
+
+  if (*rp == NULL)
+    {
+      size_t cnt;
+
+      *rp = (struct copy_def_list_t *) xmalloc (sizeof (**rp));
+
+      (*rp)->next = NULL;
+      (*rp)->name = name;
+      (*rp)->mask = 0;
+      (*rp)->locale = NULL;
+
+      for (cnt = 0; cnt < 6; ++cnt)
+	{
+	  (*rp)->binary[cnt].data = NULL;
+	  (*rp)->binary[cnt].len = 0;
+	}
+    }
+  new = *rp;
+
+  if ((new->mask & category) != 0)
+    /* We already have the information.  This cannot happen.  */
+    error (5, 0, _("\
+category data requested more than once: should not happen"));
+
+  new->mask |= category;
+}
+
+
+/* Display usage information and exit.  */
+static void
+usage (int status)
+{
+  if (status != 0)
+    fprintf (stderr, _("Try `%s --help' for more information.\n"),
+             program_name);
+  else
+    printf (_("\
+Usage: %s [OPTION]... name\n\
+Mandatory arguments to long options are mandatory for short options too.\n\
+  -c, --force               create output even if warning messages were issued\n\
+  -h, --help                display this help and exit\n\
+  -f, --charmap=FILE        symbolic character names defined in FILE\n\
+  -i, --inputfile=FILE      source definitions are found in FILE\n\
+  -u, --code-set-name=NAME  specify code set for mapping ISO 10646 elements\n\
+  -v, --verbose             print more messages\n\
+  -V, --version             output version information and exit\n\
+      --posix               be strictly POSIX conform\n\
+\n\
+System's directory for character maps: %s\n\
+                       locale files  : %s\n"),
+	    program_name, CHARMAP_PATH, LOCALE_PATH);
+
+  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.  */
+}
+
+
+/* The parameter to localedef describes the output path.  If it does
+   contain a '/' character it is a relativ path.  Otherwise it names the
+   locale this definition is for.  */
+static const char *
+construct_output_path (const char *path)
+{
+  char *result;
+
+  if (strchr (path, '/') == NULL)
+    {
+      /* This is a system path.  */
+      int path_max_len = pathconf (LOCALE_PATH, _PC_PATH_MAX) + 1;
+      result = (char *) xmalloc (path_max_len);
+
+      snprintf (result, path_max_len, "%s/%s", LOCALE_PATH, path);
+    }
+  else
+    {
+      char *t;
+      /* This is a user path.  */
+      result = xmalloc (strlen (path) + 2);
+      t = stpcpy (result, path);
+      *t = '\0';
+    }
+
+  errno = 0;
+
+  if (euidaccess (result, W_OK) == -1)
+    /* Perhaps the directory does not exist now.  Try to create it.  */
+    if (errno == ENOENT)
+      {
+	errno = 0;
+	mkdir (result, 0777);
+      }
+
+  strcat (result, "/");
+
+  return result;
+}