mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-02-13 19:02:02 +02:00
* 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.
This commit is contained in:
13
ChangeLog
13
ChangeLog
@@ -1,3 +1,16 @@
|
||||
2006-06-25 Jim Meyering <jim@meyering.net>
|
||||
|
||||
* 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.
|
||||
|
||||
2006-06-24 Jim Meyering <jim@meyering.net>
|
||||
|
||||
* src/md5sum.c (DIGEST_BUFFER): Remove now-unused definitions.
|
||||
|
||||
8
NEWS
8
NEWS
@@ -140,6 +140,9 @@ GNU coreutils NEWS -*- outline -*-
|
||||
|
||||
sort now accepts the --random-sort (-R) option and `R' ordering option.
|
||||
|
||||
wc accepts a new option --files0-from=FILE, where FILE contains a
|
||||
list of NUL-terminated file names.
|
||||
|
||||
** Bug fixes
|
||||
|
||||
cat with any of the options, -A -v -e -E -T, when applied to a
|
||||
@@ -186,9 +189,12 @@ GNU coreutils NEWS -*- outline -*-
|
||||
tail -f once again works on a file with the append-only
|
||||
attribute (affects at least Linux ext2, ext3, xfs file systems)
|
||||
|
||||
* Major changes in release 5.97 (2006-06-24) [stable]
|
||||
* Major changes in release 5.96 (2006-05-22) [stable]
|
||||
* Major changes in release 5.95 (2006-05-12) [stable]
|
||||
* Major changes in release 5.94 (2006-02-13) [stable]
|
||||
|
||||
[see branch for details]
|
||||
[see the b5_9x branch for details]
|
||||
|
||||
* Major changes in release 5.93 (2005-11-06) [stable]
|
||||
|
||||
|
||||
80
src/wc.c
80
src/wc.c
@@ -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;
|
||||
|
||||
fstatus = get_input_fstatus (nfiles, argv + optind);
|
||||
/* 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));
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
@@ -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 \
|
||||
|
||||
49
tests/misc/wc-files0
Executable file
49
tests/misc/wc-files0
Executable file
@@ -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
|
||||
91
tests/misc/wc-files0-from
Executable file
91
tests/misc/wc-files0-from
Executable file
@@ -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.
|
||||
@ENV{qw(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, \@Tests, $save_temps, $verbose);
|
||||
exit $fail;
|
||||
EOF
|
||||
Reference in New Issue
Block a user