[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: rebased patches?
From: |
Jim Meyering |
Subject: |
Re: rebased patches? |
Date: |
Thu, 12 Jun 2008 21:40:48 +0200 |
Bo Borgerson <address@hidden> wrote:
> Jim Meyering wrote:
>> P.S. no need to send the tarball.
>> I like using repo.or.cz.
>>
>> Also, I think you made it so your new decl,
>>
>> /* Output columns will be delimited with this string, which may be set
>> on the command-line with --output-delimiter=STR. The default is a
>> single TAB character. */
>> static char *delimiter;
>>
>> has two empty lines after it.
>> Just one is better.
>
> Hi Jim,
>
> I've re-pushed the comm branch with the changes you suggested.
Hi Bo,
Thanks!
I've made some minor editing changes, e.g.,
[better to use an active voice than a passive one]
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index ff6bbb0..d05577d 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -4476,8 +4476,8 @@ Do not check that both input files are in sorted order.
Other options are:
@item address@hidden
-Columns will be delimited by @var{str} in output, rather than the default
-single TAB character.
+Print @var{str} between adjacent output columns,
+rather than the default of a single TAB character.
The delimiter @var{str} may not be empty.
and tweaked the log messages.
Also, I made some syntactic changes to fit with my policy
preferences (no ">" operators, and adjusted "const" placement):
Here are your two adjusted change sets, then mine at the end.
>From 98a96822d9dac92de719fa340fe326e1fe0427fe Mon Sep 17 00:00:00 2001
From: Bo Borgerson <address@hidden>
Date: Sun, 20 Apr 2008 21:24:16 -0400
Subject: [PATCH] comm: ensure that input files are sorted
* NEWS: List new behavior.
* doc/coreutils.texi (checkOrderOption) New macro for
describing `--check-order' and `--nocheck-order', used in
both join and comm.
* src/comm.c (main): Initialize new options.
(usage): Describe new options.
(compare_files): Keep an extra pair of buffers for the previous
line from each file to check the internal order.
(check_order): If an order-check is required, compare and handle
the result appropriately.
(copylinebuffer): Copy a linebuffer; used for copy before read.
* tests/misc/Makefile.am: List new test.
* tests/misc/comm: Tests for the comm program, including the
new order-checking functionality and attendant command-line options.
---
NEWS | 3 +
doc/coreutils.texi | 39 ++++++++----
src/comm.c | 168 +++++++++++++++++++++++++++++++++++++++++++++------
tests/Makefile.am | 1 +
tests/misc/comm | 124 ++++++++++++++++++++++++++++++++++++++
5 files changed, 303 insertions(+), 32 deletions(-)
create mode 100755 tests/misc/comm
diff --git a/NEWS b/NEWS
index 97f3162..ba39d2f 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,9 @@ GNU coreutils NEWS -*-
outline -*-
** New features
+ comm now verifies that the inputs are in sorted order. This check can
+ be turned off with the --nocheck-order option.
+
md5sum now accepts the new option, --quiet, to suppress the printing of
'OK' messages. sha1sum, sha224sum, sha384sum, and sha512sum accept it, too.
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index a626b45..3bedd73 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -4449,6 +4449,32 @@ status that does not depend on the result of the
comparison.
Upon normal completion @command{comm} produces an exit code of zero.
If there is an error it exits with nonzero status.
address@hidden checkOrderOption{cmd}
+If the @option{--check-order} option is given, unsorted inputs will
+cause a fatal error message. If the option @option{--nocheck-order}
+is given, unsorted inputs will never cause an error message. If
+neither of these options is given, wrongly sorted inputs are diagnosed
+only if an input file is found to contain unpairable lines. If an
+input file is diagnosed as being unsorted, the @command{\cmd\} command
+will exit with a nonzero status (and the output should not be used).
+
+Forcing @command{\cmd\} to process wrongly sorted input files
+containing unpairable lines by specifying @option{--nocheck-order} is
+not guaranteed to produce any particular output. The output will
+probably not correspond with whatever you hoped it would be.
address@hidden macro
address@hidden
+
address@hidden @samp
+
address@hidden --check-order
+Fail with an error message if either input file is wrongly ordered.
+
address@hidden --nocheck-order
+Do not check that both input files are in sorted order.
+
address@hidden table
+
@node tsort invocation
@section @command{tsort}: Topological sort
@@ -5290,18 +5316,7 @@ c c1 c2
b b1 b2
@end example
-If the @option{--check-order} option is given, unsorted inputs will
-cause a fatal error message. If the option @option{--nocheck-order}
-is given, unsorted inputs will never cause an error message. If
-neither of these options is given, wrongly sorted inputs are diagnosed
-only if an input file is found to contain unpairable lines. If an
-input file is diagnosed as being unsorted, the @command{join} command
-will exit with a nonzero status (and the output should not be used).
-
-Forcing @command{join} to process wrongly sorted input files
-containing unpairable lines by specifying @option{--nocheck-order} is
-not guaranteed to produce any particular output. The output will
-probably not correspond with whatever you hoped it would be.
address@hidden
The defaults are:
@itemize
diff --git a/src/comm.c b/src/comm.c
index a71d61a..01c0b8c 100644
--- a/src/comm.c
+++ b/src/comm.c
@@ -51,8 +51,31 @@ static bool only_file_2;
/* If true, print lines that are found in both files. */
static bool both;
+/* If nonzero, we have seen at least one unpairable line. */
+static bool seen_unpairable;
+
+/* If nonzero, we have warned about disorder in that file. */
+static bool issued_disorder_warning[2];
+
+/* If nonzero, check that the input is correctly ordered. */
+static enum
+ {
+ CHECK_ORDER_DEFAULT,
+ CHECK_ORDER_ENABLED,
+ CHECK_ORDER_DISABLED
+ } check_input_order;
+
+enum
+{
+ CHECK_ORDER_OPTION = CHAR_MAX + 1,
+ NOCHECK_ORDER_OPTION
+};
+
+
static struct option const long_options[] =
{
+ {"check-order", no_argument, NULL, CHECK_ORDER_OPTION},
+ {"nocheck-order", no_argument, NULL, NOCHECK_ORDER_OPTION},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
@@ -87,6 +110,12 @@ and column three contains lines common to both files.\n\
-2 suppress lines unique to FILE2\n\
-3 suppress lines that appear in both files\n\
"), stdout);
+ fputs (_("\
+\n\
+ --check-order check that the input is correctly sorted, even\n\
+ if all input lines are pairable\n\
+ --nocheck-order do not check that the input is correctly sorted\n\
+"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
emit_bug_reporting_address ();
@@ -132,6 +161,53 @@ writeline (const struct linebuffer *line, FILE *stream,
int class)
fwrite (line->buffer, sizeof (char), line->length, stream);
}
+/* Check that successive input lines PREV and CURRENT from input file
+ WHATFILE are presented in order.
+
+ If the user specified --nocheck-order, the check is not made.
+ If the user specified --check-order, the problem is fatal.
+ Otherwise (the default), the message is simply a warning.
+
+ A message is printed at most once per input file.
+
+ This funtion was copied (nearly) verbatim from `src/join.c'. */
+
+static void
+check_order (const struct linebuffer *prev,
+ const struct linebuffer *current,
+ int whatfile)
+{
+
+ if (check_input_order != CHECK_ORDER_DISABLED
+ && ((check_input_order == CHECK_ORDER_ENABLED) || seen_unpairable))
+ {
+ if (!issued_disorder_warning[whatfile - 1])
+ {
+ int order;
+
+ if (hard_LC_COLLATE)
+ order = xmemcoll (prev->buffer, prev->length - 1,
+ current->buffer, current->length - 1);
+ else
+ {
+ size_t len = min (prev->length, current->length) - 1;
+ order = memcmp (prev->buffer, current->buffer, len);
+ }
+
+ if (order > 0)
+ {
+ error ((check_input_order == CHECK_ORDER_ENABLED
+ ? EXIT_FAILURE : 0),
+ 0, _("file %d is not in sorted order"), whatfile);
+
+ /* If we get to here, the message was just a warning, but we
+ want only to issue it once. */
+ issued_disorder_warning[whatfile - 1] = true;
+ }
+ }
+ }
+}
+
/* Compare INFILES[0] and INFILES[1].
If either is "-", use the standard input for that file.
Assume that each input file is sorted;
@@ -140,28 +216,42 @@ writeline (const struct linebuffer *line, FILE *stream,
int class)
static void
compare_files (char **infiles)
{
- /* For each file, we have one linebuffer in lb1. */
- struct linebuffer lb1[2];
+ /* For each file, we have four linebuffers in lba. */
+ struct linebuffer lba[2][4];
/* thisline[i] points to the linebuffer holding the next available line
in file i, or is NULL if there are no lines left in that file. */
struct linebuffer *thisline[2];
+ /* all_line[i][alt[i][0]] also points to the linebuffer holding the
+ current line in file i. We keep two buffers of history around so we
+ can look two lines back when we get to the end of a file. */
+ struct linebuffer *all_line[2][4];
+
+ /* This is used to rotate through the buffers for each input file. */
+ int alt[2][3];
+
/* streams[i] holds the input stream for file i. */
FILE *streams[2];
- int i;
+ int i, j;
/* Initialize the storage. */
for (i = 0; i < 2; i++)
{
- initbuffer (&lb1[i]);
- thisline[i] = &lb1[i];
+ for (j = 0; j < 4; j++)
+ {
+ initbuffer (&lba[i][j]);
+ all_line[i][j] = &lba[i][j];
+ }
+ alt[i][0] = 0;
+ alt[i][1] = 0;
+ alt[i][2] = 0;
streams[i] = (STREQ (infiles[i], "-") ? stdin : fopen (infiles[i], "r"));
if (!streams[i])
error (EXIT_FAILURE, errno, "%s", infiles[i]);
- thisline[i] = readlinebuffer (thisline[i], streams[i]);
+ thisline[i] = readlinebuffer (all_line[i][alt[i][0]], streams[i]);
if (ferror (streams[i]))
error (EXIT_FAILURE, errno, "%s", infiles[i]);
}
@@ -169,6 +259,7 @@ compare_files (char **infiles)
while (thisline[0] || thisline[1])
{
int order;
+ bool fill_up[2] = { false, false };
/* Compare the next available lines of the two files. */
@@ -195,25 +286,47 @@ compare_files (char **infiles)
/* Output the line that is lesser. */
if (order == 0)
writeline (thisline[1], stdout, 3);
- else if (order > 0)
- writeline (thisline[1], stdout, 2);
else
- writeline (thisline[0], stdout, 1);
+ {
+ seen_unpairable = true;
+ if (order > 0)
+ writeline (thisline[1], stdout, 2);
+ else
+ writeline (thisline[0], stdout, 1);
+ }
/* Step the file the line came from.
If the files match, step both files. */
if (order >= 0)
- {
- thisline[1] = readlinebuffer (thisline[1], streams[1]);
- if (ferror (streams[1]))
- error (EXIT_FAILURE, errno, "%s", infiles[1]);
- }
+ fill_up[1] = true;
if (order <= 0)
- {
- thisline[0] = readlinebuffer (thisline[0], streams[0]);
- if (ferror (streams[0]))
- error (EXIT_FAILURE, errno, "%s", infiles[0]);
- }
+ fill_up[0] = true;
+
+ for (i = 0; i < 2; i++)
+ if (fill_up[i])
+ {
+ /* Rotate the buffers for this file. */
+ alt[i][2] = alt[i][1];
+ alt[i][1] = alt[i][0];
+ alt[i][0] = (alt[i][0] + 1) & 0x03;
+
+ thisline[i] = readlinebuffer (all_line[i][alt[i][0]], streams[i]);
+
+ if (thisline[i])
+ check_order (all_line[i][alt[i][1]], thisline[i], i + 1);
+
+ /* If this is the end of the file we may need to re-check
+ the order of the previous two lines, since we might have
+ discovered an unpairable match since we checked before. */
+ else if (all_line[i][alt[i][2]]->buffer)
+ check_order (all_line[i][alt[i][2]],
+ all_line[i][alt[i][1]], i + 1);
+
+ if (ferror (streams[i]))
+ error (EXIT_FAILURE, errno, "%s", infiles[i]);
+
+ fill_up[i] = false;
+ }
}
for (i = 0; i < 2; i++)
@@ -239,6 +352,10 @@ main (int argc, char **argv)
only_file_2 = true;
both = true;
+ seen_unpairable = false;
+ issued_disorder_warning[0] = issued_disorder_warning[1] = false;
+ check_input_order = CHECK_ORDER_DEFAULT;
+
while ((c = getopt_long (argc, argv, "123", long_options, NULL)) != -1)
switch (c)
{
@@ -254,6 +371,14 @@ main (int argc, char **argv)
both = false;
break;
+ case NOCHECK_ORDER_OPTION:
+ check_input_order = CHECK_ORDER_DISABLED;
+ break;
+
+ case CHECK_ORDER_OPTION:
+ check_input_order = CHECK_ORDER_ENABLED;
+ break;
+
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -279,5 +404,8 @@ main (int argc, char **argv)
compare_files (argv + optind);
- exit (EXIT_SUCCESS);
+ if (issued_disorder_warning[0] || issued_disorder_warning[1])
+ exit (EXIT_FAILURE);
+ else
+ exit (EXIT_SUCCESS);
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d33005a..f07837b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -146,6 +146,7 @@ TESTS = \
misc/base64 \
misc/basename \
misc/close-stdout \
+ misc/comm \
misc/csplit \
misc/date-sec \
misc/dircolors \
diff --git a/tests/misc/comm b/tests/misc/comm
new file mode 100755
index 0000000..39557d2
--- /dev/null
+++ b/tests/misc/comm
@@ -0,0 +1,124 @@
+#!/usr/bin/perl
+# -*- perl -*-
+# Test comm
+
+# Copyright (C) 2008 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
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program 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 General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+require 5.003;
+use strict;
+
+(my $program_name = $0) =~ s|.*/||;
+
+my $prog = 'comm';
+
+# Turn off localization of executable's ouput.
address@hidden(LANGUAGE LANG LC_ALL)} = ('C') x 3;
+
+my @inputs = ({IN=>{a=>"1\n3"}}, {IN=>{b=>"2\n3"}});
+
+my @Tests =
+ (
+ # basic operation
+ ['basic', @inputs, {OUT=>"1\n\t2\n\t\t3\n"} ],
+
+ # supress lines unique to file 1
+ ['opt-1', '-1', @inputs, {OUT=>"2\n\t3\n"} ],
+
+ # supress lines unique to file 2
+ ['opt-2', '-2', @inputs, {OUT=>"1\n\t3\n"} ],
+
+ # supress lines that appear in both files
+ ['opt-3', '-3', @inputs, {OUT=>"1\n\t2\n"} ],
+
+ # supress lines unique to file 1 and lines unique to file 2
+ ['opt-12', '-1', '-2', @inputs, {OUT=>"3\n"} ],
+
+ # supress lines unique to file 1 and those that appear in both files
+ ['opt-13', '-1', '-3', @inputs, {OUT=>"2\n"} ],
+
+ # supress lines unique to file 2 and those that appear in both files
+ ['opt-23', '-2', '-3', @inputs, {OUT=>"1\n"} ],
+
+ # supress all output (really?)
+ ['opt-123', '-1', '-2', '-3', @inputs, {OUT=>""} ],
+
+ # invalid missing command line argument (1)
+ ['missing-arg1', $inputs[0], {EXIT=>1},
+ {ERR => "$prog: missing operand after `a'\n"
+ . "Try `$prog --help' for more information.\n"}],
+
+ # invalid missing command line argument (both)
+ ['missing-arg2', {EXIT=>1},
+ {ERR => "$prog: missing operand\n"
+ . "Try `$prog --help' for more information.\n"}],
+
+ # invalid extra command line argument
+ ['extra-arg', @inputs, 'no-such', {EXIT=>1},
+ {ERR => "$prog: extra operand `no-such'\n"
+ . "Try `$prog --help' for more information.\n"}],
+
+ # out-of-order input
+ ['ooo', {IN=>{a=>"1\n3"}}, {IN=>{b=>"3\n2"}}, {EXIT=>1},
+ {OUT => "1\n\t\t3\n\t2\n"},
+ {ERR => "$prog: file 2 is not in sorted order\n"}],
+
+ # out-of-order input, fatal
+ ['ooo2', '--check-order', {IN=>{a=>"1\n3"}}, {IN=>{b=>"3\n2"}}, {EXIT=>1},
+ {OUT => "1\n\t\t3\n"},
+ {ERR => "$prog: file 2 is not in sorted order\n"}],
+
+ # out-of-order input, ignored
+ ['ooo3', '--nocheck-order', {IN=>{a=>"1\n3"}}, {IN=>{b=>"3\n2"}},
+ {OUT => "1\n\t\t3\n\t2\n"}],
+
+ # both inputs out-of-order
+ ['ooo4', {IN=>{a=>"3\n1\n0"}}, {IN=>{b=>"3\n2\n0"}}, {EXIT=>1},
+ {OUT => "\t\t3\n1\n0\n\t2\n\t0\n"},
+ {ERR => "$prog: file 1 is not in sorted order\n".
+ "$prog: file 2 is not in sorted order\n" }],
+
+ # both inputs out-of-order on last pair
+ ['ooo5', {IN=>{a=>"3\n1"}}, {IN=>{b=>"3\n2"}}, {EXIT=>1},
+ {OUT => "\t\t3\n1\n\t2\n"},
+ {ERR => "$prog: file 1 is not in sorted order\n".
+ "$prog: file 2 is not in sorted order\n" }],
+
+ # first input out-of-order extended
+ ['ooo5b', {IN=>{a=>"0\n3\n1"}}, {IN=>{b=>"2\n3"}}, {EXIT=>1},
+ {OUT => "0\n\t2\n\t\t3\n1\n"},
+ {ERR => "$prog: file 1 is not in sorted order\n"}],
+
+ # second input out-of-order extended
+ ['ooo5c', {IN=>{a=>"0\n3"}}, {IN=>{b=>"2\n3\n1"}}, {EXIT=>1},
+ {OUT => "0\n\t2\n\t\t3\n\t1\n"},
+ {ERR => "$prog: file 2 is not in sorted order\n"}],
+
+ # both inputs out-of-order, but fully pairable
+ ['ooo6', {IN=>{a=>"2\n1\n0"}}, {IN=>{b=>"2\n1\n0"}}, {EXIT=>0},
+ {OUT => "\t\t2\n\t\t1\n\t\t0\n"}],
+
+ # both inputs out-of-order, fully pairable, but forced to fail
+ ['ooo7', '--check-order', {IN=>{a=>"2\n1\n0"}}, {IN=>{b=>"2\n1\n0"}},
+ {EXIT=>1},
+ {OUT => "\t\t2\n"},
+ {ERR => "$prog: file 1 is not in sorted order\n"}],
+ );
+
+my $save_temps = $ENV{DEBUG};
+my $verbose = $ENV{VERBOSE};
+
+my $fail = run_tests ($program_name, $prog, address@hidden, $save_temps,
$verbose);
+exit $fail;
--
1.5.6.rc2.17.ge9e7
>From 81d0c8f367c89a52e41bbd89e7c45d2b1ac495f2 Mon Sep 17 00:00:00 2001
From: Bo Borgerson <address@hidden>
Date: Tue, 22 Apr 2008 23:47:42 -0400
Subject: [PATCH] comm: accept new option: --output-delimiter=STR
* src/comm.c (delimiter): New global.
(writeline): Use delimiter string instead of single TAB character.
(main): Initialize delimiter.
* tests/misc/comm: Add tests for comm output delimiter specification.
* doc/coreutils.texi: Document new option.
* NEWS: Advertise new option.
* TODO: Remove associated item.
---
NEWS | 3 +++
TODO | 5 -----
doc/coreutils.texi | 9 ++++++++-
src/comm.c | 41 ++++++++++++++++++++++++++++++++++-------
tests/misc/comm | 21 +++++++++++++++++++++
5 files changed, 66 insertions(+), 13 deletions(-)
diff --git a/NEWS b/NEWS
index ba39d2f..ce14695 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,9 @@ GNU coreutils NEWS -*-
outline -*-
comm now verifies that the inputs are in sorted order. This check can
be turned off with the --nocheck-order option.
+ comm accepts new option, --output-delimiter=STR, that allows specification
+ of an output delimiter other than the default single TAB.
+
md5sum now accepts the new option, --quiet, to suppress the printing of
'OK' messages. sha1sum, sha224sum, sha384sum, and sha512sum accept it, too.
diff --git a/TODO b/TODO
index a48a8e6..81add20 100644
--- a/TODO
+++ b/TODO
@@ -20,11 +20,6 @@ cp --recursive: use fts and *at functions to perform
directory traversals
become very long, and requires space and time that is quadratic in the
depth of the hierarchy. [Bo Borgerson is working on this]
-comm: add an option, --output-delimiter=STR
- Files to change: src/comm.c, ChangeLog, NEWS, doc/coreutils.texi,
- Add a new file, tests/misc/comm (use another file in that directory as
- a template), to exercise the new option. Suggestion from Dan Jacobson.
-
printf:
Now that gnulib supports *printf("%a"), import one of the
*printf-posix modules so that printf(1) will support %a even on
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 3bedd73..d05577d 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -4473,8 +4473,15 @@ Fail with an error message if either input file is
wrongly ordered.
@item --nocheck-order
Do not check that both input files are in sorted order.
address@hidden table
+Other options are:
+
address@hidden address@hidden
+Print @var{str} between adjacent output columns,
+rather than the default of a single TAB character.
+The delimiter @var{str} may not be empty.
+
address@hidden table
@node tsort invocation
@section @command{tsort}: Topological sort
diff --git a/src/comm.c b/src/comm.c
index 01c0b8c..9742fb3 100644
--- a/src/comm.c
+++ b/src/comm.c
@@ -65,10 +65,18 @@ static enum
CHECK_ORDER_DISABLED
} check_input_order;
+/* Output columns will be delimited with this string, which may be set
+ on the command-line with --output-delimiter=STR. The default is a
+ single TAB character. */
+static char const *delimiter;
+
+/* For long options that have no equivalent short option, use a
+ non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum
{
CHECK_ORDER_OPTION = CHAR_MAX + 1,
- NOCHECK_ORDER_OPTION
+ NOCHECK_ORDER_OPTION,
+ OUTPUT_DELIMITER_OPTION
};
@@ -76,6 +84,7 @@ static struct option const long_options[] =
{
{"check-order", no_argument, NULL, CHECK_ORDER_OPTION},
{"nocheck-order", no_argument, NULL, NOCHECK_ORDER_OPTION},
+ {"output-delimiter", required_argument, NULL, OUTPUT_DELIMITER_OPTION},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
@@ -116,6 +125,9 @@ and column three contains lines common to both files.\n\
if all input lines are pairable\n\
--nocheck-order do not check that the input is correctly sorted\n\
"), stdout);
+ fputs (_("\
+ --output-delimiter=STR separate columns with STR\n\
+"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
emit_bug_reporting_address ();
@@ -141,20 +153,20 @@ writeline (const struct linebuffer *line, FILE *stream,
int class)
case 2:
if (!only_file_2)
return;
- /* Print a TAB if we are printing lines from file 1. */
+ /* Print a delimiter if we are printing lines from file 1. */
if (only_file_1)
- putc ('\t', stream);
+ fputs (delimiter, stream);
break;
case 3:
if (!both)
return;
- /* Print a TAB if we are printing lines from file 1. */
+ /* Print a delimiter if we are printing lines from file 1. */
if (only_file_1)
- putc ('\t', stream);
- /* Print a TAB if we are printing lines from file 2. */
+ fputs (delimiter, stream);
+ /* Print a delimiter if we are printing lines from file 2. */
if (only_file_2)
- putc ('\t', stream);
+ fputs (delimiter, stream);
break;
}
@@ -379,6 +391,17 @@ main (int argc, char **argv)
check_input_order = CHECK_ORDER_ENABLED;
break;
+ case OUTPUT_DELIMITER_OPTION:
+ if (delimiter && !STREQ (delimiter, optarg))
+ error (EXIT_FAILURE, 0, _("multiple delimiters specified"));
+ delimiter = optarg;
+ if (!*delimiter)
+ {
+ error (EXIT_FAILURE, 0, _("empty %s not allowed"),
+ quote ("--output-delimiter"));
+ }
+ break;
+
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -402,6 +425,10 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
+ /* The default delimiter is a TAB. */
+ if (!delimiter)
+ delimiter = "\t";
+
compare_files (argv + optind);
if (issued_disorder_warning[0] || issued_disorder_warning[1])
diff --git a/tests/misc/comm b/tests/misc/comm
index 39557d2..81a8529 100755
--- a/tests/misc/comm
+++ b/tests/misc/comm
@@ -115,6 +115,27 @@ my @Tests =
{EXIT=>1},
{OUT => "\t\t2\n"},
{ERR => "$prog: file 1 is not in sorted order\n"}],
+
+ # alternate delimiter: ','
+ ['delim-comma', '--output-delimiter=,', @inputs,
+ {OUT=>"1\n,2\n,,3\n"} ],
+
+ # two-character alternate delimiter: '++'
+ ['delim-2char', '--output-delimiter=++', @inputs,
+ {OUT=>"1\n++2\n++++3\n"} ],
+
+ # invalid empty delimiter
+ ['delim-empty', '--output-delimiter=', @inputs, {EXIT=>1},
+ {ERR => "$prog: empty `--output-delimiter' not allowed\n"}],
+
+ # invalid dual delimiter
+ ['delim-dual', '--output-delimiter=,', '--output-delimiter=+',
+ @inputs, {EXIT=>1}, {ERR => "$prog: multiple delimiters specified\n"}],
+
+ # valid dual delimiter specification
+ ['delim-dual2', '--output-delimiter=,', '--output-delimiter=,', @inputs,
+ {OUT=>"1\n,2\n,,3\n"} ],
+
);
my $save_temps = $ENV{DEBUG};
--
1.5.6.rc2.17.ge9e7
>From 3808eccbbf7086f1289fe391fe861ec1966645d6 Mon Sep 17 00:00:00 2001
From: Jim Meyering <address@hidden>
Date: Thu, 12 Jun 2008 21:38:17 +0200
Subject: [PATCH] tweak to conform with syntax policy
Use "<" or "<=" rather than ">" or ">=".
Use "Type const *", rather than "const Type *".
---
src/comm.c | 16 ++++++++--------
1 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/comm.c b/src/comm.c
index 9742fb3..2bf8761 100644
--- a/src/comm.c
+++ b/src/comm.c
@@ -141,7 +141,7 @@ and column three contains lines common to both files.\n\
2 for a line only in file 2, 3 for a line in both. */
static void
-writeline (const struct linebuffer *line, FILE *stream, int class)
+writeline (struct linebuffer const *line, FILE *stream, int class)
{
switch (class)
{
@@ -185,8 +185,8 @@ writeline (const struct linebuffer *line, FILE *stream, int
class)
This funtion was copied (nearly) verbatim from `src/join.c'. */
static void
-check_order (const struct linebuffer *prev,
- const struct linebuffer *current,
+check_order (struct linebuffer const *prev,
+ struct linebuffer const *current,
int whatfile)
{
@@ -206,7 +206,7 @@ check_order (const struct linebuffer *prev,
order = memcmp (prev->buffer, current->buffer, len);
}
- if (order > 0)
+ if (0 < order)
{
error ((check_input_order == CHECK_ORDER_ENABLED
? EXIT_FAILURE : 0),
@@ -301,15 +301,15 @@ compare_files (char **infiles)
else
{
seen_unpairable = true;
- if (order > 0)
- writeline (thisline[1], stdout, 2);
- else
+ if (order <= 0)
writeline (thisline[0], stdout, 1);
+ else
+ writeline (thisline[1], stdout, 2);
}
/* Step the file the line came from.
If the files match, step both files. */
- if (order >= 0)
+ if (0 <= order)
fill_up[1] = true;
if (order <= 0)
fill_up[0] = true;
--
1.5.6.rc2.17.ge9e7