/* vi: set sw=4 ts=4: * * comm.c - select or reject lines common to two files * * Copyright 2012 Ilya Kuzmich * * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/comm.html USE_COMM(NEWTOY(comm, "123", TOYFLAG_USR|TOYFLAG_BIN)) config COMM bool "comm" default n help usage: comm [-123] FILE1 FILE2 Reads FILE1 and FILE2, which should be ordered, and produces three text columns as output: lines only in FILE1; lines only in FILE2; and lines in both files. Filename "-" is a synonym for stdin. -1 suppress the output column of lines unique to FILE1 -2 suppress the output column of lines unique to FILE2 -3 suppress the output column of lines duplicated in FILE1 and FILE2 */ #include "toys.h" #define FLAG_SUPPRESS_3 1 #define FLAG_SUPPRESS_2 2 #define FLAG_SUPPRESS_1 4 static void writeline(const char *line, int col) { if (col == 0 && toys.optflags & FLAG_SUPPRESS_1) return; else if (col == 1) { if (toys.optflags & FLAG_SUPPRESS_2) return; if (!(toys.optflags & FLAG_SUPPRESS_1)) putchar('\t'); } else if (col == 2) { if (toys.optflags & FLAG_SUPPRESS_3) return; if (!(toys.optflags & FLAG_SUPPRESS_1)) putchar('\t'); if (!(toys.optflags & FLAG_SUPPRESS_2)) putchar('\t'); } puts(line); } void comm_main(void) { int file[2]; char *line[2]; int i; if (toys.optc != 2) perror_exit("exactly 2 operands required"); if (toys.optflags == (FLAG_SUPPRESS_1 | FLAG_SUPPRESS_2 | FLAG_SUPPRESS_3)) return; for (i = 0; i < 2; i++) { file[i] = strcmp("-", toys.optargs[i]) ? xopen(toys.optargs[i], O_RDONLY) : 0; line[i] = get_line(file[i]); } while (line[0] && line[1]) { int order = strcmp(line[0], line[1]); if (order == 0) { writeline(line[0], 2); for (i = 0; i < 2; i++) { free(line[i]); line[i] = get_line(file[i]); } } else { i = order < 0 ? 0 : 1; writeline(line[i], i); free(line[i]); line[i] = get_line(file[i]); } } /* print rest of the longer file */ for (i = line[0] ? 0 : 1; line[i];) { writeline(line[i], i); free(line[i]); line[i] = get_line(file[i]); } if (CFG_TOYBOX_FREE) { for (i = 0; i < 2; i--) xclose(file[i]); } }