toybox/toys/posix/comm.c
<<
>>
Prefs
   1/* comm.c - select or reject lines common to two files
   2 *
   3 * Copyright 2012 Ilya Kuzmich <ikv@safe-mail.net>
   4 *
   5 * See http://opengroup.org/onlinepubs/9699919799/utilities/comm.html
   6
   7// <# and ># take single digit, so 321 define flags
   8USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN))
   9
  10config COMM
  11  bool "comm"
  12  default y
  13  help
  14    usage: comm [-123] FILE1 FILE2
  15
  16    Read FILE1 and FILE2, which should be ordered, and produce three text
  17    columns as output: lines only in FILE1; lines only in FILE2; and lines
  18    in both files. Filename "-" is a synonym for stdin.
  19
  20    -1  Suppress the output column of lines unique to FILE1
  21    -2  Suppress the output column of lines unique to FILE2
  22    -3  Suppress the output column of lines duplicated in FILE1 and FILE2
  23*/
  24
  25#define FOR_comm
  26#include "toys.h"
  27
  28static void writeline(const char *line, int col)
  29{
  30  if (!col && FLAG(1)) return;
  31  else if (col == 1) {
  32    if (FLAG(2)) return;
  33    if (!FLAG(1)) putchar('\t');
  34  } else if (col == 2) {
  35    if (FLAG(3)) return;
  36    if (!FLAG(1)) putchar('\t');
  37    if (!FLAG(2)) putchar('\t');
  38  }
  39  puts(line);
  40}
  41
  42void comm_main(void)
  43{
  44  FILE *file[2];
  45  char *line[2];
  46  int i;
  47
  48  if (toys.optflags == 7) return;
  49
  50  for (i = 0; i < 2; i++) {
  51    file[i] = xfopen(toys.optargs[i], "r");
  52    line[i] = xgetline(file[i]);
  53  }
  54
  55  while (line[0] && line[1]) {
  56    int order = strcmp(line[0], line[1]);
  57
  58    if (order == 0) {
  59      writeline(line[0], 2);
  60      for (i = 0; i < 2; i++) {
  61        free(line[i]);
  62        line[i] = xgetline(file[i]);
  63      }
  64    } else {
  65      i = order < 0 ? 0 : 1;
  66      writeline(line[i], i);
  67      free(line[i]);
  68      line[i] = xgetline(file[i]);
  69    }
  70  }
  71
  72  // Print rest of the longer file.
  73  for (i = line[0] ? 0 : 1; line[i];) {
  74    writeline(line[i], i);
  75    free(line[i]);
  76    line[i] = xgetline(file[i]);
  77  }
  78
  79  if (CFG_TOYBOX_FREE) for (i = 0; i < 2; i++) fclose(file[i]);
  80}
  81