#!/usr/bin/perl

=begin metadata

Name: comm
Description: select or reject lines common to two files
Author: Mark-Jason Dominus, mjd-perl-comm@plover.comm
License: public domain

=end metadata

=cut


#
# comm
#
# 1999 M-J. Dominus (mjd-perl-comm@plover.com)
# Public domain.
#

use strict;

use File::Basename qw(basename);
use Getopt::Std qw(getopts);

use constant EX_SUCCESS => 0;
use constant EX_FAILURE => 1;

my $Program = basename($0);

my %opt;
getopts('123', \%opt) or usage();
usage() if (@ARGV != 2);
my @COL = (undef, !$opt{'1'}, !$opt{'2'}, !$opt{'3'});

my ($f1, $f2);
if ($ARGV[0] eq '-') {
  if ($ARGV[1] eq '-') {
    warn "$Program: only one file argument may be stdin\n";
    exit EX_FAILURE;
  }
  $f1 = *STDIN;
} else {
  if (-d $ARGV[0]) {
    warn "$Program: '$ARGV[0]' is a directory\n";
    exit EX_FAILURE;
  }
  unless (open $f1, '<', $ARGV[0]) {
    warn "$Program: Couldn't open file '$ARGV[0]': $!\n";
    exit EX_FAILURE;
  }
}
if ($ARGV[1] eq '-') {
  $f2 = *STDIN;
} else {
  if (-d $ARGV[1]) {
    warn "$Program: '$ARGV[1]' is a directory\n";
    exit EX_FAILURE;
  }
  unless (open $f2, '<', $ARGV[1]) {
    warn "$Program: Couldn't open file '$ARGV[1]': $!\n";
    exit EX_FAILURE;
  }
}

my $r1 = <$f1>;
my $r2 = <$f2>;

while (defined $r1 && defined $r2) {
  if ($r1 eq $r2) {
    print "\t\t", $r1 if $COL[3];
    $r1 = <$f1>;
    $r2 = <$f2>;
  } elsif ($r1 gt $r2) {
    print "\t", $r2 if $COL[2];
    $r2 = <$f2>;
  } else {
    print $r1 if $COL[1];
    $r1 = <$f1>;
  }
}

print $r1 if defined $r1 && $COL[1];
print "\t", $r2 if defined $r2 && $COL[2];
if ($COL[1]) { print while <$f1> }
if ($COL[2]) { print "\t", $_ while <$f2> }

close $f1;
close $f2;
exit EX_SUCCESS;

sub usage {
  warn "usage: $Program [-123] file1 file2\n";
  exit EX_FAILURE;
}

__END__

=encoding utf8

=head1 NAME

comm - select or reject lines common to two files