master xplshn/aruu / cmd / posix / comm.c
  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}