busybox/coreutils/comm.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * Mini comm implementation for busybox
   4 *
   5 * Copyright (C) 2005 by Robert Sullivan <cogito.ergo.cogito@gmail.com>
   6 *
   7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   8 */
   9
  10//usage:#define comm_trivial_usage
  11//usage:       "[-123] FILE1 FILE2"
  12//usage:#define comm_full_usage "\n\n"
  13//usage:       "Compare FILE1 with FILE2\n"
  14//usage:     "\n        -1      Suppress lines unique to FILE1"
  15//usage:     "\n        -2      Suppress lines unique to FILE2"
  16//usage:     "\n        -3      Suppress lines common to both files"
  17
  18#include "libbb.h"
  19
  20#define COMM_OPT_1 (1 << 0)
  21#define COMM_OPT_2 (1 << 1)
  22#define COMM_OPT_3 (1 << 2)
  23
  24/* writeline outputs the input given, appropriately aligned according to class */
  25static void writeline(char *line, int class)
  26{
  27        int flags = option_mask32;
  28        if (class == 0) {
  29                if (flags & COMM_OPT_1)
  30                        return;
  31        } else if (class == 1) {
  32                if (flags & COMM_OPT_2)
  33                        return;
  34                if (!(flags & COMM_OPT_1))
  35                        putchar('\t');
  36        } else /*if (class == 2)*/ {
  37                if (flags & COMM_OPT_3)
  38                        return;
  39                if (!(flags & COMM_OPT_1))
  40                        putchar('\t');
  41                if (!(flags & COMM_OPT_2))
  42                        putchar('\t');
  43        }
  44        puts(line);
  45}
  46
  47int comm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  48int comm_main(int argc UNUSED_PARAM, char **argv)
  49{
  50        char *thisline[2];
  51        FILE *stream[2];
  52        int i;
  53        int order;
  54
  55        opt_complementary = "=2";
  56        getopt32(argv, "123");
  57        argv += optind;
  58
  59        for (i = 0; i < 2; ++i) {
  60                stream[i] = xfopen_stdin(argv[i]);
  61        }
  62
  63        order = 0;
  64        thisline[1] = thisline[0] = NULL;
  65        while (1) {
  66                if (order <= 0) {
  67                        free(thisline[0]);
  68                        thisline[0] = xmalloc_fgetline(stream[0]);
  69                }
  70                if (order >= 0) {
  71                        free(thisline[1]);
  72                        thisline[1] = xmalloc_fgetline(stream[1]);
  73                }
  74
  75                i = !thisline[0] + (!thisline[1] << 1);
  76                if (i)
  77                        break;
  78                order = strcmp(thisline[0], thisline[1]);
  79
  80                if (order >= 0)
  81                        writeline(thisline[1], order ? 1 : 2);
  82                else
  83                        writeline(thisline[0], 0);
  84        }
  85
  86        /* EOF at least on one of the streams */
  87        i &= 1;
  88        if (thisline[i]) {
  89                /* stream[i] is not at EOF yet */
  90                /* we did not print thisline[i] yet */
  91                char *p = thisline[i];
  92                writeline(p, i);
  93                while (1) {
  94                        free(p);
  95                        p = xmalloc_fgetline(stream[i]);
  96                        if (!p)
  97                                break;
  98                        writeline(p, i);
  99                }
 100        }
 101
 102        if (ENABLE_FEATURE_CLEAN_UP) {
 103                fclose(stream[0]);
 104                fclose(stream[1]);
 105        }
 106
 107        return EXIT_SUCCESS;
 108}
 109