1/* See LICENSE file for copyright and license details. */
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7#include "text.h"
8#include "util.h"
9
10static int show = 0x07;
11
12static void
13printline(int pos, struct line *line)
14{
15 int i;
16
17 if (!(show & (0x1 << pos)))
18 return;
19
20 for (i = 0; i < pos; i++) {
21 if (show & (0x1 << i))
22 putchar('\t');
23 }
24 fwrite(line->data, 1, line->len, stdout);
25}
26
27static void
28usage(void)
29{
30 eprintf("usage: %s [-123] file1 file2\n", argv0);
31}
32
33// ?man comm: compare two sorted files
34// ?man arguments: file1 file2
35// ?man compare two sorted files line by line
36int
37main(int argc, char *argv[])
38{
39 FILE *fp[2];
40 static struct line line[2];
41 size_t linecap[2] = {0, 0};
42 ssize_t len;
43 int ret = 0, i, diff = 0, seenline = 0;
44
45 ARGBEGIN
46 {
47 // ?man -1: specify option flag
48 case '1':
49 // ?man -2: specify option flag
50 case '2':
51 // ?man -3: specify option flag
52 case '3':
53 show &= 0x07 ^ (1 << (ARGC() - '1'));
54 break;
55 default:
56 usage();
57 }
58 ARGEND
59
60 if (argc != 2)
61 usage();
62
63 for (i = 0; i < 2; i++) {
64 if (!strcmp(argv[i], "-")) {
65 argv[i] = "<stdin>";
66 fp[i] = stdin;
67 } else if (!(fp[i] = fopen(argv[i], "r"))) {
68 eprintf("fopen %s:", argv[i]);
69 }
70 }
71
72 for (;;) {
73 for (i = 0; i < 2; i++) {
74 if (diff && i == (diff < 0))
75 continue;
76 if ((len = getline(&(line[i].data), &linecap[i], fp[i])) > 0) {
77 line[i].len = len;
78 seenline = 1;
79 continue;
80 }
81 if (ferror(fp[i]))
82 eprintf("getline %s:", argv[i]);
83 if ((diff || seenline) && line[!i].data[0])
84 printline(!i, &line[!i]);
85 while ((len = getline(&(line[!i].data), &linecap[!i], fp[!i])) > 0) {
86 line[!i].len = len;
87 printline(!i, &line[!i]);
88 }
89 if (ferror(fp[!i]))
90 eprintf("getline %s:", argv[!i]);
91 goto end;
92 }
93 diff = linecmp(&line[0], &line[1]);
94 LIMIT(diff, -1, 1);
95 seenline = 0;
96 printline((2 - diff) % 3, &line[MAX(0, diff)]);
97 }
98end:
99 ret |= fshut(fp[0], argv[0]);
100 ret |= (fp[0] != fp[1]) && fshut(fp[1], argv[1]);
101 ret |= fshut(stdout, "<stdout>");
102
103 return ret;
104}