commit 79e45395e5fc8a2933df1fd3dccb570df6890929
parent d5d686e9f625d3f02dbd267929328d75259d96d1
Author: FRIGN <dev@frign.de>
Date: Sat, 7 Feb 2015 21:05:33 +0100
Refactor cmp(1) code and manpage
The algorithm had some areas which had potential for improvement.
This should make cmp(1) faster.
There have been changes to behaviour as well:
1) If argv[0] and argv[1] are the same, cmp(1) returns Same.
2) POSIX specifies the format of the difference-message to be:
"%s %s differ: char %d, line %d\n", file1, file2,
<byte number>, <line number>
However, as cmp(1) operates on bytes, not characters, I changed
it to
"%s %s differ: byte %d, line %d\n", file1, file2,
<byte number>, <line number>
This is one example where the standard just keeps the old format
for backwards-compatibility. As this is harmful, this change
makes sense in the sense of consistentcy (and because we take
the difference of char and byte very seriously in sbase, as
opposed to GNU coreutils).
The manpage has been annotated, reflecting the second change, and
sections shortened where possible.
Thus I marked cmp(1) as finished in README.
Diffstat:
M | README | | | 2 | +- |
M | cmp.1 | | | 27 | +++++++++++++++++++-------- |
M | cmp.c | | | 62 | ++++++++++++++++++++++++++++---------------------------------- |
3 files changed, 48 insertions(+), 43 deletions(-)
diff --git a/README b/README
@@ -17,7 +17,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support,
= chown no -h, -H, -L, -P
=* chroot non-posix none
=* cksum yes none
- cmp yes none
+=* cmp yes none
#* cols non-posix none
=* comm yes none
= cp no -H, (-i), -L
diff --git a/cmp.1 b/cmp.1
@@ -1,4 +1,4 @@
-.Dd November 21, 2014
+.Dd February 7, 2015
.Dt CMP 1
.Os sbase
.Sh NAME
@@ -10,23 +10,32 @@
.Ar file1 file2
.Sh DESCRIPTION
.Nm
-compares two files byte by byte. If the files differ,
+compares
+.Ar file1
+and
+.Ar file2
+byte by byte. If they differ,
.Nm
-prints the byte and
-line number at which the difference occurred.
+writes the first differing byte- and line-number to stdout.
.Sh OPTIONS
.Bl -tag -width Ds
.It Fl l
-Print the byte number, and the differing bytes (in octal), for each difference.
+Print byte-number and bytes (in octal) for each difference.
.It Fl s
-Print nothing, only returns status.
+Print nothing and only return status.
.El
.Sh EXIT STATUS
.Bl -tag -width Ds
.It 0
-The files are identical.
+.Ar file1
+and
+.Ar file2
+are identical.
.It 1
-The files are different.
+.Ar file1
+and
+.Ar file2
+are different.
.It > 1
An error occurred.
.El
@@ -39,3 +48,5 @@ The
utility is compliant with the
.St -p1003.1-2008
specification.
+.Pp
+The "char" in the default result format has been replaced with "byte".
diff --git a/cmp.c b/cmp.c
@@ -1,6 +1,7 @@
/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include "util.h"
@@ -16,12 +17,9 @@ usage(void)
int
main(int argc, char *argv[])
{
- int lflag = 0;
- int sflag = 0;
- int same = 1;
- int b[2], i;
- long line = 1, n = 1;
FILE *fp[2];
+ size_t i, line = 1, n = 1;
+ int lflag = 0, sflag = 0, same = 1, b[2];
ARGBEGIN {
case 'l':
@@ -37,45 +35,41 @@ main(int argc, char *argv[])
if (argc != 2 || (lflag && sflag))
usage();
- if (argv[0][0] == '-' && !argv[0][1])
- argv[0] = "/dev/fd/0";
- fp[0] = fopen(argv[0], "r");
- if (!fp[0]) {
- if (!sflag)
- weprintf("fopen %s:", argv[0]);
- exit(Error);
- }
+ if (!strcmp(argv[0], argv[1]))
+ return Same;
- if (argv[1][0] == '-' && !argv[1][1])
- argv[1] = "/dev/fd/0";
- fp[1] = fopen(argv[1], "r");
- if (!fp[1]) {
- if (!sflag)
- weprintf("fopen %s:", argv[1]);
- exit(Error);
+ for (i = 0; i < 2; i++) {
+ if (argv[i][0] == '-' && !argv[i][1])
+ argv[i] = "/dev/fd/0";
+ fp[i] = fopen(argv[i], "r");
+ if (!fp[i]) {
+ if (!sflag)
+ weprintf("fopen %s:", argv[i]);
+ exit(Error);
+ }
}
for (n = 1; ; n++) {
b[0] = getc(fp[0]);
b[1] = getc(fp[1]);
- if (b[0] == EOF && b[1] == EOF)
- break;
- if (b[0] == '\n' && b[1] == '\n')
- line++;
- if (b[0] == b[1])
+
+ if (b[0] == b[1]) {
+ if (b[0] == EOF)
+ break;
+ else if (b[0] == '\n')
+ line++;
continue;
- for (i = 0; i < 2; i++) {
- if (b[i] == EOF) {
- if (!sflag)
- fprintf(stderr, "cmp: EOF on %s\n",
- !argv[i] ? "<stdin>" : argv[i]);
- exit(Diff);
- }
+ }
+ if (b[0] == EOF || b[1] == EOF) {
+ if (!sflag)
+ fprintf(stderr, "cmp: EOF on %s\n",
+ argv[(b[0] == EOF) ? 0 : 1]);
+ exit(Diff);
}
if (!lflag) {
if (!sflag)
- printf("%s %s differ: char %ld, line %ld\n",
- argv[0], !argv[1] ? "<stdin>" : argv[1], n, line);
+ printf("%s %s differ: byte %ld, line %ld\n",
+ argv[0], argv[1], n, line);
exit(Diff);
} else {
printf("%ld %o %o\n", n, b[0], b[1]);