commit a4587b84f82a61fdcb22766163aa0a6c19dc8a84
parent 76ea3fdd52d306faffb8b40842c73639fbbfc957
Author: FRIGN <dev@frign.de>
Date:   Wed, 11 Mar 2015 13:39:08 +0100
Audit comm(1)
1) Use the LIMIT()-macro in util.h instead of defining our own.
2) Drop nextline() and finish(), not needed anymore. Use
   fputs in printline instead of printf.
   --> BUGFIX: Finish exited with status 1, but actually should
               exit with status 0 if ferror(f) == 0.
3) Don't use /dev/fd/0 and use idiomatic <stdin> and fp = stdin
   instead.
4) Refactor loop to use getline() instead of some handrolled
   nextline-function.
   --> BUGFIX: Line-length was limited to LINE_MAX before, now
               it's factually unlimited.
5) Combine diff >= 0 and diff <= 0 into one loop with a beginning
   continue-condition (diff && i == (diff < 0)).
6) BUGFIX: If diff == 0, don't print one buffer after EOFing on the
           other.
Diffstat:
| M | comm.c | | | 79 | ++++++++++++++++++++++++++++--------------------------------------------------- | 
1 file changed, 28 insertions(+), 51 deletions(-)
diff --git a/comm.c b/comm.c
@@ -5,8 +5,6 @@
 
 #include "util.h"
 
-#define CLAMP(x, l, h) MIN(h, MAX(l, x))
-
 static int show = 0x07;
 
 static void
@@ -21,28 +19,7 @@ printline(int pos, char *line)
 		if (show & (0x1 << i))
 			putchar('\t');
 	}
-	printf("%s", line);
-}
-
-static char *
-nextline(char *buf, int n, FILE *f, char *name)
-{
-	buf = fgets(buf, n, f);
-	if (!buf && !feof(f))
-		eprintf("%s: read error:", name);
-	if (buf && !strchr(buf, '\n'))
-		eprintf("%s: line too long\n", name);
-	return buf;
-}
-
-static void
-finish(int pos, FILE *f, char *name)
-{
-	char buf[LINE_MAX + 1];
-
-	while (nextline(buf, sizeof(buf), f, name))
-		printline(pos, buf);
-	exit(1);
+	fputs(line, stdout);
 }
 
 static void
@@ -54,9 +31,10 @@ usage(void)
 int
 main(int argc, char *argv[])
 {
-	int i, diff = 0;
 	FILE *fp[2];
-	char lines[2][LINE_MAX + 1];
+	size_t linelen[2] = { 0, 0 };
+	int i, diff = 0;
+	char *line[2] = { NULL, NULL };
 
 	ARGBEGIN {
 	case '1':
@@ -71,36 +49,35 @@ main(int argc, char *argv[])
 	if (argc != 2)
 		usage();
 
-	for (i = 0; i < LEN(fp); i++) {
-		if (argv[i][0] == '-' && !argv[i][1])
-			argv[i] = "/dev/fd/0";
-		if (!(fp[i] = fopen(argv[i], "r")))
+	for (i = 0; i < 2; i++) {
+		if (argv[i][0] == '-' && !argv[i][1]) {
+			argv[i] = "<stdin>";
+			fp[i] = stdin;
+		} else if (!(fp[i] = fopen(argv[i], "r"))) {
 			eprintf("fopen %s:", argv[i]);
+		}
 	}
 
 	for (;;) {
-		if (diff <= 0) {
-			lines[0][0] = '\0';
-			if (!nextline(lines[0], sizeof(lines[0]),
-				     fp[0], argv[0])) {
-				if (lines[1][0] != '\0')
-					printline(1, lines[1]);
-				finish(1, fp[1], argv[1]);
-			}
-		}
-		if (diff >= 0) {
-			lines[1][0] = '\0';
-			if (!nextline(lines[1], sizeof(lines[1]),
-				     fp[1], argv[1])) {
-				if (lines[0][0] != '\0')
-					printline(0, lines[0]);
-				finish(0, fp[0], argv[0]);
-			}
+		for (i = 0; i < 2; i++) {
+			if (diff && i == (diff < 0))
+				continue;
+			if (getline(&line[i], &linelen[i], fp[i]) >= 0)
+				continue;
+			if (ferror(fp[i]))
+				eprintf("getline %s:", argv[i]);
+			if (diff && strlen(line[!i]))
+				printline(!i, line[!i]);
+			while (getline(&line[!i], &linelen[!i], fp[!i]) >= 0)
+				printline(!i, line[!i]);
+			if (ferror(fp[!i]))
+				eprintf("getline %s:", argv[!i]);
+			goto end;
 		}
-		diff = strcmp(lines[0], lines[1]);
-		diff = CLAMP(diff, -1, 1);
-		printline((2-diff) % 3, lines[MAX(0, diff)]);
+		diff = strcmp(line[0], line[1]);
+		LIMIT(diff, -1, 1);
+		printline((2-diff) % 3, line[MAX(0, diff)]);
 	}
-
+end:
 	return 0;
 }