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