]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
msgexec replaces msgsed.
authorBruno Haible <bruno@clisp.org>
Thu, 12 Jul 2001 12:23:01 +0000 (12:23 +0000)
committerBruno Haible <bruno@clisp.org>
Thu, 12 Jul 2001 12:23:01 +0000 (12:23 +0000)
man/ChangeLog
man/Makefile.am
man/msgexec.x [moved from man/msgsed.x with 55% similarity]
src/ChangeLog
src/Makefile.am
src/msgexec.c [moved from src/msgsed.c with 80% similarity]

index 2672fa549354e81f24433276b10c7268106f772c..4855cb8e23903b8fc361b856e02c69a91a2eb401 100644 (file)
@@ -1,3 +1,13 @@
+2001-07-12  Bruno Haible  <haible@clisp.cons.org>
+
+       * msgexec.x: New file.
+       * msgsed.x: Remove file.
+       * Makefile.am (man_aux): Replace msgsed.x with msgexec.x.
+       (man_MAN1): Replace msgsed.1 with msgexec.1.
+       (man_HTML): Replace msgsed.1.html with msgexec.1.html.
+       (msgexec.1.html): New rule.
+       (msgsed.1.html): Remove rule.
+
 2001-06-10  Bruno Haible  <haible@clisp.cons.org>
 
        * help2man: New file, from help2man-1.24.
index ba16c072e0059222caf86f09a0a23a295cb11993..105b14a159454e87086665e7a7d7043384eef6da 100644 (file)
@@ -28,13 +28,13 @@ AUTOMAKE_OPTIONS = 1.2 gnits
 
 man_aux  = gettext.x ngettext.x \
 msgcmp.x msgfmt.x msgmerge.x msgunfmt.x xgettext.x \
-msgcat.x msgcomm.x msgconv.x msgen.x msggrep.x msgsed.x
+msgcat.x msgcomm.x msgconv.x msgen.x msggrep.x msgexec.x
 
 # Likewise, plus additional manual pages for the libintl functions.
 
 man_MAN1 = gettext.1 ngettext.1 \
 msgcmp.1 msgfmt.1 msgmerge.1 msgunfmt.1 xgettext.1 \
-msgcat.1 msgcomm.1 msgconv.1 msgen.1 msggrep.1 msgsed.1
+msgcat.1 msgcomm.1 msgconv.1 msgen.1 msggrep.1 msgexec.1
 man_MAN3 = gettext.3 ngettext.3 \
 textdomain.3 bindtextdomain.3 bind_textdomain_codeset.3
 man_MAN3IN = gettext.3.in ngettext.3.in \
@@ -44,7 +44,7 @@ dgettext.3 dcgettext.3 dngettext.3 dcngettext.3
 
 man_HTML = gettext.1.html ngettext.1.html \
 msgcmp.1.html msgfmt.1.html msgmerge.1.html msgunfmt.1.html xgettext.1.html \
-msgcat.1.html msgcomm.1.html msgconv.1.html msgen.1.html msggrep.1.html msgsed.1.html \
+msgcat.1.html msgcomm.1.html msgconv.1.html msgen.1.html msggrep.1.html msgexec.1.html \
 gettext.3.html ngettext.3.html \
 textdomain.3.html bindtextdomain.3.html bind_textdomain_codeset.3.html
 
@@ -151,8 +151,8 @@ msgen.1.html: msgen.1
 msggrep.1.html: msggrep.1
        $(MAN2HTML) `if test -f msggrep.1; then echo .; else echo $(srcdir); fi`/msggrep.1 > t-$@
        mv t-$@ $@
-msgsed.1.html: msgsed.1
-       $(MAN2HTML) `if test -f msgsed.1; then echo .; else echo $(srcdir); fi`/msgsed.1 > t-$@
+msgexec.1.html: msgexec.1
+       $(MAN2HTML) `if test -f msgexec.1; then echo .; else echo $(srcdir); fi`/msgexec.1 > t-$@
        mv t-$@ $@
 gettext.3.html: gettext.3.in
        $(MAN2HTML) $(srcdir)/gettext.3.in > t-$@
similarity index 55%
rename from man/msgsed.x
rename to man/msgexec.x
index 7a7e4d3366855653e1a2dad759c6e9326ecbb378..2175e11cce6a5c94e94cf4e6416d7a904b62094a 100644 (file)
@@ -1,4 +1,4 @@
 [NAME]
-msgsed \- stream editing of message catalog
+msgexec \- edit translations of message catalog
 [DESCRIPTION]
 .\" Add any additional description here
index 5dd8a08c562377d1107c7ae06cdc9453b781553d..b01f5a553ec5ae388133445344fc6886f26cbca1 100644 (file)
@@ -1,3 +1,11 @@
+2001-07-12  Bruno Haible  <haible@clisp.cons.org>
+
+       * msgexec.c: New file.
+       * msgsed.c: Remove file.
+       * Makefile.am (bin_PROGRAMS): Replace msgsed with msgexec.
+       (msgexec_SOURCES, msgexec_LDADD): New variables.
+       (msgsed_SOURCES, msgsed_LDADD): Remove variables.
+
 2001-07-11  Bruno Haible  <haible@clisp.cons.org>
 
        * xgettext.c (test_whether_c_format): When encountering an
index 482fd477cbf3f35c55d10af8fa3f27836fa93d6a..9ac1b4e27c75d4986d57e3780a8ada3b3a3aeb69 100644 (file)
@@ -21,7 +21,7 @@ AUTOMAKE_OPTIONS = 1.2 gnits
 
 bin_PROGRAMS = gettext ngettext \
 msgcmp msgfmt msgmerge msgunfmt xgettext \
-msgcat msgcomm msgconv msgen msggrep msgsed
+msgcat msgcomm msgconv msgen msggrep msgexec
 
 noinst_HEADERS = pos.h message.h po-gram.h po-hash.h po-charset.h po-lex.h \
 po.h open-po.h read-po.h str-list.h write-po.h xget-lex.h dir-list.h \
@@ -65,7 +65,7 @@ po-charset.c po-lex.c po.c read-po.c str-list.c dir-list.c write-po.c
 msggrep_SOURCES = msggrep.c message.c open-po.c po-gram-gen.y po-hash-gen.y \
 po-charset.c po-lex.c po.c read-po.c str-list.c dir-list.c write-po.c \
 msgl-charset.c
-msgsed_SOURCES = msgsed.c message.c open-po.c po-gram-gen.y po-hash-gen.y \
+msgexec_SOURCES = msgexec.c message.c open-po.c po-gram-gen.y po-hash-gen.y \
 po-charset.c po-lex.c po.c read-po.c str-list.c dir-list.c write-po.c \
 msgl-charset.c
 
@@ -82,7 +82,7 @@ msgcomm_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@
 msgconv_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@
 msgen_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@
 msggrep_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@
-msgsed_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@
+msgexec_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@
 
 BUILT_SOURCES = po-gram-gen.c po-hash-gen.c po-gram-gen.h po-hash-gen.h
 
similarity index 80%
rename from src/msgsed.c
rename to src/msgexec.c
index 1d41c255fd965fbafe5ebe723df5bc39a4b495d6..5ddfe10616de9c70fbf5e90ffbb4df6c3d62ad1f 100644 (file)
@@ -1,4 +1,4 @@
-/* Edit translations using a script of editing commands.
+/* Edit translations using a subprocess.
    Copyright (C) 2001 Free Software Foundation, Inc.
    Written by Bruno Haible <haible@clisp.cons.org>, 2001.
 
 #define _(str) gettext (str)
 
 
-/* We use a child process running 'sed', and communicate through a
-   bidirectional pipe.  To avoid deadlocks, let the child process decide
-   when it wants to read or to write, and let the parent behave accordingly.
-   The parent uses select() to know whether it must write or read.  On
-   platforms without select(), we use non-blocking I/O.  (This means the
-   parent is busy looping while waiting for the child.  Not good.)  */
+/* We use a child process, and communicate through a bidirectional pipe.
+   To avoid deadlocks, let the child process decide when it wants to read
+   or to write, and let the parent behave accordingly.  The parent uses
+   select() to know whether it must write or read.  On platforms without
+   select(), we use non-blocking I/O.  (This means the parent is busy
+   looping while waiting for the child.  Not good.)  */
 
 /* On BeOS select() works only on sockets, not on normal file descriptors.  */
 #ifdef __BeOS__
 /* Force output of PO file even if empty.  */
 static int force_po;
 
-/* Arguments to be passed to the sed subprocess.  */
-static string_list_ty *sed_args;
+/* Name of the subprogram.  */
+static const char *sub_name;
 
-/* Pathname of the sed program.  */
-static const char *sed_path;
+/* Pathname of the subprogram.  */
+static const char *sub_path;
 
-/* Argument list for the sed program.  */
-static char **sed_argv;
+/* Argument list for the subprogram.  */
+static char **sub_argv;
+static int sub_argc;
 
 /* Long options.  */
 static const struct option long_options[] =
@@ -87,16 +88,13 @@ static const struct option long_options[] =
   { "add-location", no_argument, &line_comment, 1 },
   { "directory", required_argument, NULL, 'D' },
   { "escape", no_argument, NULL, 'E' },
-  { "expression", required_argument, NULL, 'e' },
-  { "file", required_argument, NULL, 'f' },
   { "force-po", no_argument, &force_po, 1 },
   { "help", no_argument, NULL, 'h' },
-  { "indent", no_argument, NULL, 'i' },
-  { "no-escape", no_argument, NULL, CHAR_MAX + 1 },
+  { "indent", no_argument, NULL, CHAR_MAX + 1 },
+  { "input", required_argument, NULL, 'i' },
+  { "no-escape", no_argument, NULL, CHAR_MAX + 2 },
   { "no-location", no_argument, &line_comment, 0 },
   { "output-file", required_argument, NULL, 'o' },
-  { "quiet", no_argument, NULL, 'n' },
-  { "silent", no_argument, NULL, 'n' },
   { "sort-by-file", no_argument, NULL, 'F' },
   { "sort-output", no_argument, NULL, 's' },
   { "strict", no_argument, NULL, 'S' },
@@ -155,10 +153,10 @@ main (argc, argv)
   do_version = false;
   output_file = NULL;
   input_file = NULL;
-  sed_args = string_list_alloc ();
 
-  while ((opt = getopt_long (argc, argv, "D:e:Ef:Fhino:sVw:",
-                            long_options, NULL))
+  /* The '+' in the options string causes option parsing to terminate when
+     the first non-option, i.e. the subprogram name, is encountered.  */
+  while ((opt = getopt_long (argc, argv, "+D:EFhio:sVw:", long_options, NULL))
         != EOF)
     switch (opt)
       {
@@ -169,20 +167,10 @@ main (argc, argv)
        dir_list_append (optarg);
        break;
 
-      case 'e':
-       string_list_append (sed_args, "-e");
-       string_list_append (sed_args, optarg);
-       break;
-
       case 'E':
        message_print_style_escape (true);
        break;
 
-      case 'f':
-       string_list_append (sed_args, "-f");
-       string_list_append (sed_args, optarg);
-       break;
-
       case 'F':
        sort_by_filepos = true;
        break;
@@ -192,11 +180,12 @@ main (argc, argv)
        break;
 
       case 'i':
-       message_print_style_indent ();
-       break;
-
-      case 'n':
-       string_list_append (sed_args, "-n");
+       if (input_file != NULL)
+         {
+           error (EXIT_SUCCESS, 0, _("at most one input file allowed"));
+           usage (EXIT_FAILURE);
+         }
+       input_file = optarg;
        break;
 
       case 'o':
@@ -226,6 +215,10 @@ main (argc, argv)
        break;
 
       case CHAR_MAX + 1:
+       message_print_style_indent ();
+       break;
+
+      case CHAR_MAX + 2:
        message_print_style_escape (false);
        break;
 
@@ -252,43 +245,65 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
   if (do_help)
     usage (EXIT_SUCCESS);
 
-  /* Test whether we have an .po file name as argument.  */
+  /* Test for the subprogram name.  */
   if (optind == argc)
-    input_file = "-";
-  else if (optind + 1 == argc)
-    input_file = argv[optind];
-  else
+    error (EXIT_FAILURE, 0, _("missing filter name"));
+  sub_name = argv[optind];
+
+  /* Build argument list for the program.  */
+  sub_argc = argc - optind;
+  sub_argv = (char **) xmalloc ((sub_argc + 1) * sizeof (char *));
+  for (i = 0; i < sub_argc; i++)
+    sub_argv[i] = argv[optind + i];
+  sub_argv[i] = NULL;
+
+  /* Extra checks for sed scripts.  */
+  if (strcmp (sub_name, "sed") == 0)
     {
-      error (EXIT_SUCCESS, 0, _("at most one input file allowed"));
-      usage (EXIT_FAILURE);
-    }
+      if (sub_argc == 1)
+       error (EXIT_FAILURE, 0,
+              _("at least one sed script must be specified"));
 
-  if (sed_args->nitems == 0)
-    error (EXIT_FAILURE, 0, _("at least one sed script must be specified"));
+      /* Replace GNU sed specific options with portable sed options.  */
+      for (i = 1; i < sub_argc; i++)
+       {
+         if (strcmp (sub_argv[i], "--expression") == 0)
+           sub_argv[i] = "-e";
+         else if (strcmp (sub_argv[i], "--file") == 0)
+           sub_argv[i] = "-f";
+         else if (strcmp (sub_argv[i], "--quiet") == 0
+                  || strcmp (sub_argv[i], "--silent") == 0)
+           sub_argv[i] = "-n";
+
+         if (strcmp (sub_argv[i], "-e") == 0
+             || strcmp (sub_argv[i], "-f") == 0)
+           i++;
+       }
+    }
 
   if (sort_by_msgid && sort_by_filepos)
     error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
           "--sort-output", "--sort-by-file");
 
+  /* By default, input comes from standard input.  */
+  if (input_file == NULL)
+    input_file = "-";
+
   /* Read input file.  */
   result = read_po_file (input_file);
 
   /* Warn if the current locale is not suitable for this PO file.  */
   compare_po_locale_charsets (result);
 
-  /* Attempt to locate the 'sed' program.
+  /* Attempt to locate the program.
      This is an optimization, to avoid that spawn/exec searches the PATH
      on every call.  */
-  sed_path = find_in_path ("sed");
+  sub_path = find_in_path (sub_name);
 
-  /* Build argument list for the 'sed' program.  */
-  sed_argv = (char **) xmalloc ((1 + sed_args->nitems + 1) * sizeof (char *));
-  sed_argv[0] = (char *) sed_path;
-  for (i = 1; i <= sed_args->nitems; i++)
-    sed_argv[i] = (char *) sed_args->item[i - 1];
-  sed_argv[i] = NULL;
+  /* Finish argument list for the program.  */
+  sub_argv[0] = (char *) sub_path;
 
-  /* Apply the sed script.  */
+  /* Apply the subprogram.  */
   result = process_msgdomain_list (result);
 
   /* Sort the results.  */
@@ -316,12 +331,12 @@ usage (status)
     {
       /* xgettext: no-wrap */
       printf (_("\
-Usage: %s [OPTION] [INPUTFILE]\n\
+Usage: %s [OPTION] FILTER [FILTER-OPTION]\n\
 "), program_name);
       printf ("\n");
       /* xgettext: no-wrap */
       printf (_("\
-Applies a sed script to all translations of a translation catalog.\n\
+Applies a filter to all translations of a translation catalog.\n\
 "));
       printf ("\n");
       /* xgettext: no-wrap */
@@ -332,7 +347,7 @@ Mandatory arguments to long options are mandatory for short options too.\n\
       /* xgettext: no-wrap */
       printf (_("\
 Input file location:\n\
-  INPUTFILE                   input PO file\n\
+  -i, --input=INPUTFILE       input PO file\n\
   -D, --directory=DIRECTORY   add DIRECTORY to list for input files search\n\
 If no input file is given or if it is -, standard input is read.\n\
 "));
@@ -347,7 +362,13 @@ or if it is -.\n\
       printf ("\n");
       /* xgettext: no-wrap */
       printf (_("\
-Sed options:\n\
+The FILTER can be any program that reads a translation from standard input\n\
+and writes a modified translation to standard output.\n\
+"));
+      printf ("\n");
+      /* xgettext: no-wrap */
+      printf (_("\
+Useful FILTER-OPTIONs when the FILTER is 'sed':\n\
   -e, --expression=SCRIPT     add SCRIPT to the commands to be executed\n\
   -f, --file=SCRIPTFILE       add the contents of SCRIPTFILE to the commands\n\
                                 to be executed\n\
@@ -360,7 +381,7 @@ Output details:\n\
       --no-escape             do not use C escapes in output (default)\n\
   -E, --escape                use C escapes in output, no extended chars\n\
       --force-po              write PO file even if empty\n\
-  -i, --indent                indented output style\n\
+      --indent                indented output style\n\
       --no-location           suppress '#: filename:line' lines\n\
       --add-location          preserve '#: filename:line' lines (default)\n\
       --strict                strict Uniforum output style\n\
@@ -475,7 +496,8 @@ nonintr_select (n, readfds, writefds, exceptfds, timeout)
 # endif
 #endif
 
-/* Process a string STR of size LEN bytes through sed, then remove NUL bytes.
+/* Process a string STR of size LEN bytes through the subprogram, then
+   remove NUL bytes.
    Store the freshly allocated result at *RESULTP and its length at *LENGTHP.
  */
 static void
@@ -492,8 +514,8 @@ process_string (str, len, resultp, lengthp)
   size_t length;
   int exitstatus;
 
-  /* Open a bidirectional pipe to a sed subprocess.  */
-  child = create_pipe_bidi ("sed", sed_path, sed_argv, fd);
+  /* Open a bidirectional pipe to a subprocess.  */
+  child = create_pipe_bidi (sub_name, sub_path, sub_argv, fd);
      
   /* Enable non-blocking I/O.  This permits the read() and write() calls
      to return -1/EAGAIN without blocking; this is important for polling
@@ -511,7 +533,7 @@ process_string (str, len, resultp, lengthp)
        || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0
        || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) < 0)
       error (EXIT_FAILURE, errno,
-            _("cannot set up nonblocking I/O to sed subprocess"));
+            _("cannot set up nonblocking I/O to %s subprocess"), sub_name);
   }
 
   allocated = len + (len >> 2) + 1;
@@ -539,7 +561,7 @@ process_string (str, len, resultp, lengthp)
       n = select (n, &readfds, (str != NULL ? &writefds : NULL), NULL, NULL);
       if (n < 0)
        error (EXIT_FAILURE, errno,
-              _("communication with sed subprocess failed"));
+              _("communication with %s subprocess failed"), sub_name);
       if (str != NULL && FD_ISSET (fd[1], &writefds))
        goto try_write;
       if (FD_ISSET (fd[0], &readfds))
@@ -559,7 +581,7 @@ process_string (str, len, resultp, lengthp)
              ssize_t nwritten = write (fd[1], str, len);
              if (nwritten < 0 && !IS_EAGAIN (errno))
                error (EXIT_FAILURE, errno,
-                      _("write to sed subprocess failed"));
+                      _("write to %s subprocess failed"), sub_name);
              if (nwritten > 0)
                {
                  str += nwritten;
@@ -589,7 +611,8 @@ process_string (str, len, resultp, lengthp)
       {
        ssize_t nread = read (fd[0], result + length, allocated - length);
        if (nread < 0 && !IS_EAGAIN (errno))
-         error (EXIT_FAILURE, errno, _("read from sed subprocess failed"));
+         error (EXIT_FAILURE, errno,
+                _("read from %s subprocess failed"), sub_name);
        if (nread > 0)
          length += nread;
        if (nread == 0 && str == NULL)
@@ -603,10 +626,10 @@ process_string (str, len, resultp, lengthp)
   close (fd[0]);
 
   /* Remove zombie process from process list.  */
-  exitstatus = wait_subprocess (child, "sed");
+  exitstatus = wait_subprocess (child, sub_name);
   if (exitstatus != 0)
-    error (EXIT_FAILURE, 0, _("sed subprocess terminated with exit code %d"),
-          exitstatus);
+    error (EXIT_FAILURE, 0, _("%s subprocess terminated with exit code %d"),
+          sub_name, exitstatus);
 
   /* Remove NUL bytes from result.  */
   {