comm.c (1888B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <limits.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 7 #include "util.h" 8 9 #define CLAMP(x, l, h) MIN(h, MAX(l, x)) 10 11 static int show = 0x07; 12 13 static void 14 printline(int pos, char *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 printf("%s", line); 26 } 27 28 static char * 29 nextline(char *buf, int n, FILE *f, char *name) 30 { 31 buf = fgets(buf, n, f); 32 if (!buf && !feof(f)) 33 eprintf("%s: read error:", name); 34 if (buf && !strchr(buf, '\n')) 35 eprintf("%s: line too long\n", name); 36 return buf; 37 } 38 39 static void 40 finish(int pos, FILE *f, char *name) 41 { 42 char buf[LINE_MAX + 1]; 43 44 while (nextline(buf, sizeof(buf), f, name)) 45 printline(pos, buf); 46 exit(1); 47 } 48 49 static void 50 usage(void) 51 { 52 eprintf("usage: %s [-123] file1 file2\n", argv0); 53 } 54 55 int 56 main(int argc, char *argv[]) 57 { 58 int i, diff = 0; 59 FILE *fp[2]; 60 char lines[2][LINE_MAX + 1]; 61 62 ARGBEGIN { 63 case '1': 64 case '2': 65 case '3': 66 show &= 0x07 ^ (1 << (ARGC() - '1')); 67 break; 68 default: 69 usage(); 70 } ARGEND; 71 72 if (argc != 2) 73 usage(); 74 75 for (i = 0; i < LEN(fp); i++) { 76 if (argv[i][0] == '-' && !argv[i][1]) 77 argv[i] = "/dev/fd/0"; 78 if (!(fp[i] = fopen(argv[i], "r"))) 79 eprintf("fopen %s:", argv[i]); 80 } 81 82 for (;;) { 83 if (diff <= 0) { 84 lines[0][0] = '\0'; 85 if (!nextline(lines[0], sizeof(lines[0]), 86 fp[0], argv[0])) { 87 if (lines[1][0] != '\0') 88 printline(1, lines[1]); 89 finish(1, fp[1], argv[1]); 90 } 91 } 92 if (diff >= 0) { 93 lines[1][0] = '\0'; 94 if (!nextline(lines[1], sizeof(lines[1]), 95 fp[1], argv[1])) { 96 if (lines[0][0] != '\0') 97 printline(0, lines[0]); 98 finish(0, fp[0], argv[0]); 99 } 100 } 101 diff = strcmp(lines[0], lines[1]); 102 diff = CLAMP(diff, -1, 1); 103 printline((2-diff) % 3, lines[MAX(0, diff)]); 104 } 105 106 return 0; 107 }