Update.
[kopensolaris-gnu/glibc.git] / catgets / gencat.c
index 1616abf..d632f82 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
 
 # include <config.h>
 #endif
 
+#include <argp.h>
 #include <ctype.h>
 #include <endian.h>
 #include <errno.h>
 #include <error.h>
 #include <fcntl.h>
-#include <getopt.h>
 #include <locale.h>
 #include <libintl.h>
 #include <limits.h>
@@ -88,22 +88,56 @@ struct catalog
 /* If non-zero force creation of new file, not using existing one.  */
 static int force_new;
 
-/* Long options.  */
-static const struct option long_options[] =
+/* Name of output file.  */
+static const char *output_name;
+
+/* Name of generated C header file.  */
+static const char *header_name;
+
+/* Name and version of program.  */
+static void print_version (FILE *stream, struct argp_state *state);
+void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+
+#define OPT_NEW 1
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { "header", 'H', N_("NAME"), 0,
+    N_("Create C header file NAME containing symbol definitions") },
+  { "new", OPT_NEW, NULL, 0,
+    N_("Do not use existing catalog, force new output file") },
+  { "output", 'o', N_("NAME"), 0, N_("Write output to file NAME") },
+  { NULL, 0, NULL, 0, NULL }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("Generate message catalog.\
+\vIf INPUT-FILE is -, input is read from standard input.  If OUTPUT-FILE\n\
+is -, output is written to standard output.\n");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("\
+-o OUTPUT-FILE [INPUT-FILE]...\n[OUTPUT-FILE [INPUT-FILE]...]");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Function to print some extra text in the help message.  */
+static char *more_help (int key, const char *text, void *input);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
 {
-  { "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 }
+  options, parse_opt, args_doc, doc, NULL, more_help
 };
 
+
 /* Wrapper functions with error checking for standard functions.  */
 extern void *xmalloc (size_t n);
+extern void *xcalloc (size_t n, size_t s);
 
 /* 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);
@@ -119,11 +153,7 @@ 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;
+  int remaining;
 
   /* Set program name for messages.  */
   error_print_progname = error_print;
@@ -135,61 +165,21 @@ main (int argc, char *argv[])
   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)
-    {
-      printf ("gencat (GNU %s) %s\n", PACKAGE, VERSION);
-      printf (_("\
-Copyright (C) %s Free Software Foundation, Inc.\n\
-This is free software; see the source for copying conditions.  There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "1996, 1997");
-      printf (_("Written by %s.\n"), "Ulrich Drepper");
-
-      exit (EXIT_SUCCESS);
-    }
-
-  /* Help is requested.  */
-  if (do_help)
-    usage (EXIT_SUCCESS);
+  /* Parse and process arguments.  */
+  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
 
   /* Determine output file.  */
   if (output_name == NULL)
-    output_name = optind < argc ? argv[optind++] : "-";
+    output_name = remaining < argc ? argv[remaining++] : "-";
 
   /* Process all input files.  */
   setlocale (LC_CTYPE, "C");
-  if (optind < argc)
+  if (remaining < argc)
     do
-      result = read_input_file (result, argv[optind]);
-    while (++optind < argc);
+      result = read_input_file (result, argv[remaining]);
+    while (++remaining < argc);
   else
     result = read_input_file (NULL, "-");
 
@@ -201,32 +191,54 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
 }
 
 
-static void
-usage (int status)
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
 {
-  if (status != EXIT_SUCCESS)
-    fprintf (stderr, gettext ("Try `%s --help' for more information.\n"),
-             program_invocation_name);
-  else
+  switch (key)
     {
-      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);
-      fputs (gettext ("\
-Report bugs using the `glibcbug' script to <bugs@gnu.ai.mit.edu>.\n"),
-            stdout);
+    case 'H':
+      header_name = arg;
+      break;
+    case OPT_NEW:
+      force_new = 1;
+      break;
+    case 'o':
+      output_name = arg;
+      break;
+    default:
+      return ARGP_ERR_UNKNOWN;
     }
+  return 0;
+}
+
 
-  exit (status);
+static char *
+more_help (int key, const char *text, void *input)
+{
+  switch (key)
+    {
+    case ARGP_KEY_HELP_EXTRA:
+      /* We print some extra information.  */
+      return strdup (gettext ("\
+Report bugs using the `glibcbug' script to <bugs@gnu.org>.\n"));
+    default:
+      break;
+    }
+  return (char *) text;
+}
+
+/* Print the version information.  */
+static void
+print_version (FILE *stream, struct argp_state *state)
+{
+  fprintf (stream, "gencat (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, gettext ("\
+Copyright (C) %s Free Software Foundation, Inc.\n\
+This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
+"), "1996, 1997");
+  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
 }
 
 
@@ -264,16 +276,13 @@ read_input_file (struct catalog *current, const char *fname)
   /* 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);
+      current = (struct catalog *) xcalloc (1, sizeof (*current));
 
 #define obstack_chunk_alloc malloc
 #define obstack_chunk_free free
       obstack_init (&current->mem_pool);
+
+      current->current_set = find_set (current, NL_SETD);
     }
 
   buf = NULL;
@@ -321,7 +330,7 @@ read_input_file (struct catalog *current, const char *fname)
            /* This is a comment line.  Do nothing.  */;
          else if (strncmp (&this_line[1], "set", 3) == 0)
            {
-             int cnt = sizeof ("cnt");
+             int cnt = sizeof ("set");
              int set_number;
              const char *symbol = NULL;
              while (isspace (this_line[cnt]))
@@ -827,16 +836,18 @@ write_out (struct catalog *catalog, const char *output_name,
                 #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:%Zu */\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:%Zu */\n",
-                          set_run->symbol, message_run->symbol,
-                          message_run->number, message_run->fname,
-                          message_run->line);
+               {
+                 if (set_run->symbol == NULL)
+                   fprintf (fp, "#define AutomaticSet%d%s %#x\t/* %s:%Zu */\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:%Zu */\n",
+                            set_run->symbol, message_run->symbol,
+                            message_run->number, message_run->fname,
+                            message_run->line);
+               }
 
              message_run = message_run->next;
            }
@@ -866,10 +877,8 @@ find_set (struct catalog *current, int number)
       result = result->next;
 
   /* Prepare new message set.  */
-  result = (struct set_list *) xmalloc (sizeof (*result));
+  result = (struct set_list *) xcalloc (1, sizeof (*result));
   result->number = number;
-  result->deleted = 0;
-  result->messages = NULL;
   result->next = current->all_sets;
   current->all_sets = result;
 
@@ -977,16 +986,20 @@ read_old (struct catalog *catalog, const char *file_name)
 
   old_cat_obj.status = closed;
   old_cat_obj.cat_name = file_name;
+  old_cat_obj.nlspath = NULL;
+  __libc_lock_init (old_cat_obj.lock);
 
   /* Try to open catalog, but don't look through the NLSPATH.  */
-  __open_catalog (&old_cat_obj, 0);
+  __open_catalog (&old_cat_obj);
 
   if (old_cat_obj.status != mmapped && 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"));
+    {
+      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