mirror of
https://https.git.savannah.gnu.org/git/diffutils.git
synced 2026-01-27 01:44:20 +00:00
cmp: improve EOF diagnostic
This improves on yesterday's change, following up on a remark by Jim Meyering (Bug#22816#21). * doc/diffutils.texi (Invoking cmp, cmp Options): Follow POSIX more closely in the documentation of the information appended to the EOF diagnostic. * src/cmp.c (cmp): Be more specific about the shorter file's length and fix some off-by-1 issues in reporting line counts. * tests/cmp: Adjust to match new behavior. Don't assume internal details about stdio buffering.
This commit is contained in:
parent
98b6fc2f32
commit
ac05c6d549
@ -3511,15 +3511,16 @@ reports the location of the first difference to standard output:
|
||||
|
||||
@noindent
|
||||
If one file is a prefix of the other, @command{cmp} reports the
|
||||
shorter file's length to standard error (@acronym{POSIX} allows but
|
||||
does not require the shorter file's name to be followed by a blank and
|
||||
additional information):
|
||||
shorter file's name to standard error, followed by a blank and extra
|
||||
information about the shorter file:
|
||||
|
||||
@example
|
||||
cmp: EOF on @var{shorter-file} after byte @var{byte-number}, line @var{line-number}
|
||||
cmp: EOF on @var{shorter-file} @var{extra-info}
|
||||
@end example
|
||||
|
||||
The message formats can differ outside the @acronym{POSIX} locale.
|
||||
@acronym{POSIX} allows but does not require the EOF diagnostic's file
|
||||
name to be followed by a blank and additional information.
|
||||
|
||||
An exit status of 0 means no differences were found, 1 means some
|
||||
differences were found, and 2 means trouble.
|
||||
@ -3566,8 +3567,7 @@ instead of the default standard output.
|
||||
Each output line contains a differing byte's number relative to the
|
||||
start of the input, followed by the differing byte values.
|
||||
Byte numbers start at 1.
|
||||
Also, if one file is shorter than the other, output the @acronym{EOF}
|
||||
message with just a byte number.
|
||||
Also, output the @acronym{EOF} message if one file is shorter than the other.
|
||||
|
||||
@item -n @var{count}
|
||||
@itemx --bytes=@var{count}
|
||||
|
||||
60
src/cmp.c
60
src/cmp.c
@ -378,6 +378,7 @@ main (int argc, char **argv)
|
||||
static int
|
||||
cmp (void)
|
||||
{
|
||||
bool at_line_start = true;
|
||||
off_t line_number = 1; /* Line number (1...) of difference. */
|
||||
off_t byte_number = 1; /* Byte number (1...) of difference. */
|
||||
uintmax_t remaining = bytes; /* Remaining number of bytes to compare. */
|
||||
@ -463,8 +464,11 @@ cmp (void)
|
||||
}
|
||||
|
||||
byte_number += first_diff;
|
||||
if (comparison_type == type_first_diff)
|
||||
line_number += count_newlines (buf0, first_diff);
|
||||
if (comparison_type == type_first_diff && first_diff != 0)
|
||||
{
|
||||
line_number += count_newlines (buf0, first_diff);
|
||||
at_line_start = buf0[first_diff - 1] == '\n';
|
||||
}
|
||||
|
||||
if (first_diff < smaller)
|
||||
{
|
||||
@ -478,9 +482,9 @@ cmp (void)
|
||||
char const *line_num = offtostr (line_number, line_buf);
|
||||
if (!opt_print_bytes)
|
||||
{
|
||||
/* See POSIX 1003.1-2001 for this format. This
|
||||
message is used only in the POSIX locale, so it
|
||||
need not be translated. */
|
||||
/* See POSIX for this format. This message is
|
||||
used only in the POSIX locale, so it need not
|
||||
be translated. */
|
||||
static char const char_message[] =
|
||||
"%s %s differ: char %s, line %s\n";
|
||||
|
||||
@ -510,7 +514,7 @@ cmp (void)
|
||||
printf (_("%s %s differ: byte %s, line %s is %3o %s %3o %s\n"),
|
||||
file[0], file[1], byte_num, line_num,
|
||||
c0, s0, c1, s1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Fall through. */
|
||||
case type_status:
|
||||
@ -527,7 +531,7 @@ cmp (void)
|
||||
char const *byte_num = offtostr (byte_number, byte_buf);
|
||||
if (!opt_print_bytes)
|
||||
{
|
||||
/* See POSIX 1003.1-2001 for this format. */
|
||||
/* See POSIX for this format. */
|
||||
printf ("%*s %3o %3o\n",
|
||||
offset_width, byte_num, c0, c1);
|
||||
}
|
||||
@ -559,23 +563,35 @@ cmp (void)
|
||||
if (differing <= 0 && comparison_type != type_status)
|
||||
{
|
||||
char const *shorter_file = file[read1 < read0];
|
||||
char byte_buf[INT_BUFSIZE_BOUND (off_t)];
|
||||
char const *byte_num = offtostr (byte_number - 1, byte_buf);
|
||||
|
||||
/* See POSIX 1003.1-2001 for the constraints on these
|
||||
format strings. */
|
||||
if (comparison_type == type_first_diff)
|
||||
{
|
||||
char line_buf[INT_BUFSIZE_BOUND (off_t)];
|
||||
char const *line_num = offtostr (line_number - 1, line_buf);
|
||||
fprintf (stderr,
|
||||
_("cmp: EOF on %s after byte %s, line %s\n"),
|
||||
shorter_file, byte_num, line_num);
|
||||
}
|
||||
/* POSIX says that each of these format strings must be
|
||||
"cmp: EOF on %s", optionally followed by a blank and
|
||||
extra text sans newline, then terminated by "\n". */
|
||||
if (byte_number == 1)
|
||||
fprintf (stderr, _("cmp: EOF on %s which is empty\n"),
|
||||
shorter_file);
|
||||
else
|
||||
fprintf (stderr,
|
||||
_("cmp: EOF on %s after byte %s\n"),
|
||||
shorter_file, byte_num);
|
||||
{
|
||||
char byte_buf[INT_BUFSIZE_BOUND (off_t)];
|
||||
char const *byte_num = offtostr (byte_number - 1, byte_buf);
|
||||
|
||||
if (comparison_type == type_first_diff)
|
||||
{
|
||||
char line_buf[INT_BUFSIZE_BOUND (off_t)];
|
||||
char const *line_num
|
||||
= offtostr (line_number - at_line_start, line_buf);
|
||||
fprintf (stderr,
|
||||
(at_line_start
|
||||
? _("cmp: EOF on %s after byte %s, line %s\n")
|
||||
: _("cmp: EOF on %s after byte %s,"
|
||||
" in line %s\n")),
|
||||
shorter_file, byte_num, line_num);
|
||||
}
|
||||
else
|
||||
fprintf (stderr,
|
||||
_("cmp: EOF on %s after byte %s\n"),
|
||||
shorter_file, byte_num);
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
|
||||
66
tests/cmp
66
tests/cmp
@ -27,7 +27,7 @@ cmp a b
|
||||
a b differ: char 1, line 1
|
||||
1
|
||||
cmp a c
|
||||
cmp: EOF on c after byte 0, line 0
|
||||
cmp: EOF on c which is empty
|
||||
1
|
||||
cmp a d
|
||||
cmp: d: No such file or directory
|
||||
@ -38,16 +38,16 @@ b a differ: char 1, line 1
|
||||
cmp b b
|
||||
0
|
||||
cmp b c
|
||||
cmp: EOF on c after byte 0, line 0
|
||||
cmp: EOF on c which is empty
|
||||
1
|
||||
cmp b d
|
||||
cmp: d: No such file or directory
|
||||
2
|
||||
cmp c a
|
||||
cmp: EOF on c after byte 0, line 0
|
||||
cmp: EOF on c which is empty
|
||||
1
|
||||
cmp c b
|
||||
cmp: EOF on c after byte 0, line 0
|
||||
cmp: EOF on c which is empty
|
||||
1
|
||||
cmp c c
|
||||
0
|
||||
@ -72,7 +72,7 @@ cmp -l a b
|
||||
1 141 142
|
||||
1
|
||||
cmp -l a c
|
||||
cmp: EOF on c after byte 0
|
||||
cmp: EOF on c which is empty
|
||||
1
|
||||
cmp -l a d
|
||||
cmp: d: No such file or directory
|
||||
@ -83,16 +83,16 @@ cmp -l b a
|
||||
cmp -l b b
|
||||
0
|
||||
cmp -l b c
|
||||
cmp: EOF on c after byte 0
|
||||
cmp: EOF on c which is empty
|
||||
1
|
||||
cmp -l b d
|
||||
cmp: d: No such file or directory
|
||||
2
|
||||
cmp -l c a
|
||||
cmp: EOF on c after byte 0
|
||||
cmp: EOF on c which is empty
|
||||
1
|
||||
cmp -l c b
|
||||
cmp: EOF on c after byte 0
|
||||
cmp: EOF on c which is empty
|
||||
1
|
||||
cmp -l c c
|
||||
0
|
||||
@ -154,12 +154,58 @@ for option in '' -l -s; do
|
||||
for i in a b c d; do
|
||||
for j in a b c d; do
|
||||
echo cmp $option $i $j
|
||||
cmp $option $i $j 2>&1
|
||||
echo $?
|
||||
cmp $option $i $j >stdout 2>stderr
|
||||
status=$?
|
||||
cat stderr stdout
|
||||
echo $status
|
||||
done
|
||||
done
|
||||
done >out
|
||||
|
||||
compare exp out || fail=1
|
||||
|
||||
cat <<'EOF' > exp1 || fail=1
|
||||
cmp a0 a1
|
||||
cmp: EOF on a0 which is empty
|
||||
1
|
||||
cmp a1 a2
|
||||
cmp: EOF on a1 after byte 2, line 1
|
||||
1
|
||||
cmp a2 a3
|
||||
cmp: EOF on a2 after byte 5, in line 2
|
||||
1
|
||||
cmp -l a0 a1
|
||||
cmp: EOF on a0 which is empty
|
||||
1
|
||||
cmp -l a1 a2
|
||||
cmp: EOF on a1 after byte 2
|
||||
1
|
||||
cmp -l a2 a3
|
||||
cmp: EOF on a2 after byte 5
|
||||
1
|
||||
cmp -s a0 a1
|
||||
1
|
||||
cmp -s a1 a2
|
||||
1
|
||||
cmp -s a2 a3
|
||||
1
|
||||
EOF
|
||||
|
||||
printf '' >a0
|
||||
printf '1\n' >a1
|
||||
printf '1\nfoo' >a2
|
||||
printf '1\nfoolery\n' >a3
|
||||
|
||||
for option in '' -l -s; do
|
||||
for files in 'a0 a1' 'a1 a2' 'a2 a3'; do
|
||||
echo cmp $option $files
|
||||
cmp $option $files >stdout 2>stderr
|
||||
status=$?
|
||||
cat stderr stdout
|
||||
echo $status
|
||||
done
|
||||
done >out1
|
||||
|
||||
compare exp1 out1 || fail=1
|
||||
|
||||
Exit $fail
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user