comm.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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. // <# and ># take single digit, so 321 define flags
  7. USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN))
  8. config COMM
  9. bool "comm"
  10. default y
  11. help
  12. usage: comm [-123] FILE1 FILE2
  13. Read FILE1 and FILE2, which should be ordered, and produce three text
  14. columns as output: lines only in FILE1; lines only in FILE2; and lines
  15. in both files. Filename "-" is a synonym for stdin.
  16. -1 Suppress the output column of lines unique to FILE1
  17. -2 Suppress the output column of lines unique to FILE2
  18. -3 Suppress the output column of lines duplicated in FILE1 and FILE2
  19. */
  20. #define FOR_comm
  21. #include "toys.h"
  22. static void writeline(const char *line, int col)
  23. {
  24. if (!col && FLAG(1)) return;
  25. else if (col == 1) {
  26. if (FLAG(2)) return;
  27. if (!FLAG(1)) putchar('\t');
  28. } else if (col == 2) {
  29. if (FLAG(3)) return;
  30. if (!FLAG(1)) putchar('\t');
  31. if (!FLAG(2)) putchar('\t');
  32. }
  33. puts(line);
  34. }
  35. void comm_main(void)
  36. {
  37. FILE *file[2];
  38. char *line[2];
  39. int i;
  40. if (toys.optflags == 7) return;
  41. for (i = 0; i < 2; i++) {
  42. file[i] = xfopen(toys.optargs[i], "r");
  43. line[i] = xgetline(file[i]);
  44. }
  45. while (line[0] && line[1]) {
  46. int order = strcmp(line[0], line[1]);
  47. if (order == 0) {
  48. writeline(line[0], 2);
  49. for (i = 0; i < 2; i++) {
  50. free(line[i]);
  51. line[i] = xgetline(file[i]);
  52. }
  53. } else {
  54. i = order < 0 ? 0 : 1;
  55. writeline(line[i], i);
  56. free(line[i]);
  57. line[i] = xgetline(file[i]);
  58. }
  59. }
  60. // Print rest of the longer file.
  61. for (i = line[0] ? 0 : 1; line[i];) {
  62. writeline(line[i], i);
  63. free(line[i]);
  64. line[i] = xgetline(file[i]);
  65. }
  66. if (CFG_TOYBOX_FREE) for (i = 0; i < 2; i++) fclose(file[i]);
  67. }