bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

FYI: wc accepts a new option --files0-from=FILE, ...


From: Jim Meyering
Subject: FYI: wc accepts a new option --files0-from=FILE, ...
Date: Sun, 25 Jun 2006 20:28:35 +0200

I've just checked in this change:

2006-06-25  Jim Meyering  <address@hidden>

        * NEWS: wc accepts a new option --files0-from=FILE, where FILE
        contains a list of NUL-separated file names.

        * src/wc.c: Include "readtokens.h".
        (usage): Describe the new option, and adjust the `Usage':
        with this option, no FILE may be specified on the command line.
        (main): Handle the new option.
        * tests/misc/wc-files0: New tests, for the above.
        * tests/misc/wc-files0-from: Likewise.
        * tests/misc/Makefile.am (TESTS): Add wc-files0.

Index: src/wc.c
===================================================================
RCS file: /fetish/cu/src/wc.c,v
retrieving revision 1.108
retrieving revision 1.109
diff -u -p -u -r1.108 -r1.109
--- src/wc.c    13 Aug 2005 22:47:48 -0000      1.108
+++ src/wc.c    25 Jun 2006 18:26:09 -0000      1.109
@@ -1,5 +1,5 @@
 /* wc - print the number of lines, words, and bytes in files
-   Copyright (C) 85, 91, 1995-2005 Free Software Foundation, Inc.
+   Copyright (C) 85, 91, 1995-2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -48,6 +48,8 @@
 
 #include "error.h"
 #include "inttostr.h"
+#include "quote.h"
+#include "readtokens0.h"
 #include "safe-read.h"
 
 #ifndef HAVE_DECL_WCWIDTH
@@ -103,6 +105,12 @@ struct fstatus
   struct stat st;
 };
 
+/* For long options that have no equivalent short option, use a
+   non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
+enum
+{
+  FILES0_FROM_OPTION = CHAR_MAX + 1
+};
 
 static struct option const longopts[] =
 {
@@ -110,6 +118,7 @@ static struct option const longopts[] =
   {"chars", no_argument, NULL, 'm'},
   {"lines", no_argument, NULL, 'l'},
   {"words", no_argument, NULL, 'w'},
+  {"files0-from", required_argument, NULL, FILES0_FROM_OPTION},
   {"max-line-length", no_argument, NULL, 'L'},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
@@ -126,8 +135,9 @@ usage (int status)
     {
       printf (_("\
 Usage: %s [OPTION]... [FILE]...\n\
+  or:  %s [OPTION]... --files0-from=F\n\
 "),
-             program_name);
+             program_name, program_name);
       fputs (_("\
 Print newline, word, and byte counts for each FILE, and a total line if\n\
 more than one FILE is specified.  With no FILE, or when FILE is -,\n\
@@ -137,6 +147,8 @@ read standard input.\n\
   -l, --lines            print the newline counts\n\
 "), stdout);
       fputs (_("\
+      --files0-from=F    read input from the files specified by\n\
+                           NUL-terminated names in file F\n\
   -L, --max-line-length  print the length of the longest line\n\
   -w, --words            print the word counts\n\
 "), stdout);
@@ -593,7 +605,10 @@ main (int argc, char **argv)
   bool ok;
   int optc;
   int nfiles;
+  char **files;
+  char *files_from = NULL;
   struct fstatus *fstatus;
+  struct Tokens tok;
 
   initialize_main (&argc, &argv);
   program_name = argv[0];
@@ -630,6 +645,10 @@ main (int argc, char **argv)
        print_linelength = true;
        break;
 
+      case FILES0_FROM_OPTION:
+       files_from = optarg;
+       break;
+
       case_GETOPT_HELP_CHAR;
 
       case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -642,15 +661,64 @@ main (int argc, char **argv)
         | print_linelength))
     print_lines = print_words = print_bytes = true;
 
-  nfiles = argc - optind;
-  nfiles += (nfiles == 0);
+  if (files_from)
+    {
+      FILE *stream;
+
+      /* When using --files0-from=F, you may not specify any files
+        on the command-line.  */
+      if (optind < argc)
+       {
+         error (0, 0, _("extra operand %s"), quote (argv[optind]));
+         fprintf (stderr, "%s\n",
+                  _("File operands cannot be combined with --files0-from."));
+         usage (EXIT_FAILURE);
+       }
+
+      if (STREQ (files_from, "-"))
+       stream = stdin;
+      else
+       {
+         stream = fopen (files_from, "r");
+         if (stream == NULL)
+           error (EXIT_FAILURE, errno, _("cannot open %s for reading"),
+                  quote (files_from));
+       }
 
-  fstatus = get_input_fstatus (nfiles, argv + optind);
+      readtokens0_init (&tok);
+
+      if (! readtokens0 (stream, &tok) || fclose (stream) != 0)
+       error (EXIT_FAILURE, 0, _("cannot read file names from %s"),
+              quote (files_from));
+
+      files = tok.tok;
+      nfiles = tok.n_tok;
+    }
+  else
+    {
+      static char *stdin_only[2];
+      files = (optind < argc ? argv + optind : stdin_only);
+      nfiles = (optind < argc ? argc - optind : 1);
+      stdin_only[0] = NULL;
+    }
+
+  fstatus = get_input_fstatus (nfiles, files);
   number_width = compute_number_width (nfiles, fstatus);
 
   ok = true;
   for (i = 0; i < nfiles; i++)
-    ok &= wc_file (argv[optind + i], &fstatus[i]);
+    {
+      if (files_from && STREQ (files_from, "-") && STREQ (files[i], "-"))
+       {
+         ok = false;
+         error (0, 0,
+                _("when reading file names from stdin, "
+                  "no file name of %s allowed"),
+                quote ("-"));
+         continue;
+       }
+      ok &= wc_file (files[i], &fstatus[i]);
+    }
 
   if (1 < nfiles)
     write_counts (total_lines, total_words, total_chars, total_bytes,
Index: tests/misc/wc-files0-from
===================================================================
RCS file: tests/misc/wc-files0-from
diff -N tests/misc/wc-files0-from
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/misc/wc-files0-from   25 Jun 2006 18:26:10 -0000      1.1
@@ -0,0 +1,91 @@
+#!/bin/sh
+# -*- perl -*-
+# Exercise wc's --files0-from option.
+# This file bears a striking resemblance to tests/du/files0-from.
+
+: ${PERL=perl}
+: ${srcdir=.}
+
+. $srcdir/../envvar-check
+
+$PERL -e 1 > /dev/null 2>&1 || {
+  echo 1>&2 "$0: configure didn't find a usable version of Perl," \
+    "so can't run this test"
+  exit 77
+}
+
+exec $PERL -w -I$srcdir/.. -MCoreutils -- - <<\EOF
+#/
+require 5.003;
+use strict;
+
+(my $program_name = $0) =~ s|.*/||;
+
+$ENV{PROG} = 'wc';
+my $ME = $ENV{PROG};
+
+# Turn off localization of executable's ouput.
address@hidden(LANGUAGE LANG LC_ALL)} = ('C') x 3;
+
+my @Tests =
+  (
+   # invalid extra command line argument
+   ['f-extra-arg', '--files0-from=- no-such', {IN=>"a"}, {EXIT=>1},
+    {ERR => "$ME: extra operand `no-such'\n"
+       . "File operands cannot be combined with --files0-from.\n"
+       . "Try `$ME --help' for more information.\n"}
+    ],
+
+   # missing input file
+   ['missing', '--files0-from=missing', {EXIT=>1},
+    {ERR => "$ME: cannot open `missing' for reading: "
+     . "No such file or directory\n"}],
+
+   # empty input
+   ['empty', '--files0-from=-'],
+
+   # empty input, from non-regular file
+   ['empty-nonreg', '--files0-from=/dev/null'],
+
+   # one NUL
+   ['nul-1', '--files0-from=-', '<', {IN=>"\0"}, {EXIT=>1},
+    {ERR => "$ME: : No such file or directory\n"}],
+
+   # two NULs
+   ['nul-2', '--files0-from=-', '<', {IN=>"\0\0"}, {EXIT=>1},
+    {OUT=>"0 0 0 total\n"},
+    {ERR => "$ME: : No such file or directory\n"
+          . "$ME: : No such file or directory\n"}],
+
+   # one file name, no NUL
+   ['1', '--files0-from=-', '<',
+    {IN=>{f=>"g"}}, {AUX=>{g=>''}}, {OUT=>"0 0 0 g\n"} ],
+
+   # one file name, with NUL
+   ['1a', '--files0-from=-', '<',
+    {IN=>{f=>"g\0"}}, {AUX=>{g=>''}}, {OUT=>"0 0 0 g\n"} ],
+
+   # two file names, no final NUL
+   ['2', '--files0-from=-', '<',
+    {IN=>{f=>"g\0g"}}, {AUX=>{g=>''}},
+     {OUT=>"0 0 0 g\n0 0 0 g\n0 0 0 total\n"} ],
+
+   # two file names, with final NUL
+   ['2a', '--files0-from=-', '<',
+    {IN=>{f=>"g\0g\0"}}, {AUX=>{g=>''}},
+     {OUT=>"0 0 0 g\n0 0 0 g\n0 0 0 total\n"} ],
+
+   # Ensure that wc processes FILEs following a zero-length name.
+   ['zero-len', '--files0-from=-', '<',
+    {IN=>{f=>"\0g\0"}}, {AUX=>{g=>''}},
+    {OUT=>"0 0 0 g\n0 0 0 total\n"},
+    {ERR => "$ME: : No such file or directory\n"}, {EXIT=>1} ],
+  );
+
+my $save_temps = $ENV{DEBUG};
+my $verbose = $ENV{VERBOSE};
+
+my $prog = $ENV{PROG} || die "$0: \$PROG not specified in environment\n";
+my $fail = run_tests ($program_name, $prog, address@hidden, $save_temps, 
$verbose);
+exit $fail;
+EOF
Index: tests/misc/wc-files0
===================================================================
RCS file: tests/misc/wc-files0
diff -N tests/misc/wc-files0
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/misc/wc-files0        25 Jun 2006 18:26:10 -0000      1.1
@@ -0,0 +1,49 @@
+#!/bin/sh
+# Show that wc's new --files0-from option works.
+
+if test "$VERBOSE" = yes; then
+  set -x
+  wc --version
+fi
+
+. $srcdir/../lang-default
+
+pwd=`pwd`
+t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
+trap 'status=$?; cd $pwd; chmod -R u+rwx $t0; rm -rf $t0 && exit $status' 0
+trap '(exit $?); exit $?' 1 2 13 15
+
+framework_failure=0
+mkdir -p $tmp || framework_failure=1
+cd $tmp || framework_failure=1
+
+echo 2 > 2b || framework_failure=1
+echo 2 words > 2w || framework_failure=1
+printf '2b\n2w\n' |tr '\n' '\0' > names || framework_failure=1
+
+if test $framework_failure = 1; then
+  echo "$0: failure in testing framework" 1>&2
+  (exit 1); exit 1
+fi
+
+fail=0
+
+wc --files0-from=names > out || fail=1
+cat <<\EOF > exp || fail=1
+ 1  1  2 2b
+ 1  2  8 2w
+ 2  3 10 total
+EOF
+
+cmp out exp || fail=1
+test $fail = 1 && diff out exp 2> /dev/null
+
+if test "$fail" = ''; then
+  # Repeat the above test, but read the file name list from stdin.
+  rm -f out
+  wc --files0-from=- < names > out || fail=1
+  cmp out exp || fail=1
+  test $fail = 1 && diff out exp 2> /dev/null
+fi
+
+(exit $fail); exit $fail
Index: tests/misc/Makefile.am
===================================================================
RCS file: /fetish/cu/tests/misc/Makefile.am,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -p -u -r1.39 -r1.40
--- tests/misc/Makefile.am      8 Jun 2006 20:13:46 -0000       1.39
+++ tests/misc/Makefile.am      25 Jun 2006 18:26:10 -0000      1.40
@@ -18,6 +18,8 @@ TESTS_ENVIRONMENT = \
 # will execute the test script rather than the standard utility.
 
 TESTS = \
+  wc-files0-from \
+  wc-files0 \
   cat-proc \
   base64 \
   basename \




reply via email to

[Prev in Thread] Current Thread [Next in Thread]