diff options
Diffstat (limited to 'toys/comm.c')
-rw-r--r-- | toys/comm.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/toys/comm.c b/toys/comm.c new file mode 100644 index 00000000..1cddf954 --- /dev/null +++ b/toys/comm.c @@ -0,0 +1,91 @@ +/* vi: set sw=4 ts=4: + * + * comm.c - select or reject lines common to two files + * + * Copyright 2012 Ilya Kuzmich <ikv@safe-mail.net> + * + * 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]); + } +} |