#!/usr/bin/perl
# Filename:	colmath
# Author:	David Ljung Madison <DaveSource.com>
# See License:	http://MarginalHacks.com/License/
# Description:	Column math.  See usage.
use strict;

##################################################
# Setup the variables
##################################################
my $PROGNAME = $0; $PROGNAME =~ s|.*/||;
my ($BASENAME,$PROGNAME) = ($0 =~ m|(.*)/(.+)|) ? ($1?$1:'/',$2) : ('.',$0);


##################################################
# Usage
##################################################
sub fatal {
  foreach my $msg (@_) { print STDERR "[$PROGNAME] ERROR:  $msg\n"; }
  exit(-1);
}

sub usage {
  foreach my $msg (@_) { print STDERR "ERROR:  $msg\n"; }
  print STDERR "\n";
  print STDERR "Usage:\t$PROGNAME [-d] <file>\n";
  print STDERR "\tCut columns from files and do 'math' on the results\n";
  print STDERR "\t+<file> adds a file, -<file> subtracts, order is important!\n";
  print STDERR "\n";
  print STDERR "\t-d <char>\tDelimiter\n";
  print STDERR "\t-f <num>\tField to cut\n";
  print STDERR "\t-i\tIgnore case\n";
  print STDERR "\t-ignore <regex>\tIgnore these lines (regexp)\n";
  print STDERR "\n";
  print STDERR "\t-D\tSet debug mode\n";
  print STDERR "\n";
  exit -1;
}

sub parse_args {
  my %opt = (
		'delim' => "\t",
		'field' => 1,
  );

  while (my $arg=shift(@ARGV)) {
    if ($arg =~ /^-h$/) { usage(); }
    if ($arg =~ /^-i$/) { $opt{ic} = 1; next; }
    if ($arg =~ /^-d(=(.+))?$/) { $opt{delim} = $2 ? $2 : shift(@ARGV); next; }
    if ($arg =~ /^-f(=(.+))?$/) { $opt{field} = $2 ? $2 : shift(@ARGV); next; }
    if ($arg =~ /^-ignore(=(.+))?$/) { $opt{ignore} = $2 ? $2 : shift(@ARGV); next; }
    if ($arg =~ /^-D$/) { $MAIN::DEBUG=1; next; }
    if (-f $arg) { push(@{$opt{files}}, $arg); next; }
    if ($arg =~ /^[\+\-](.+)/ && -f $1) { push(@{$opt{files}}, $arg); next; }
    usage("Unknown option/file: [$arg]");
  }
  usage("No files defined") unless $opt{files} && @{$opt{files}};

  \%opt;
}

sub debug {
  return unless $MAIN::DEBUG;
  foreach my $msg (@_) { print STDERR "[$PROGNAME] $msg\n"; }
}

##################################################
# Code
##################################################
sub get_file {
  my ($opt,$file) = @_;

  # Add or subtract?
  my $add = 1;
  unless (-f $file) {
    $add = 0 if !($file =~ s/^\+//) && $file =~ s/^\-//;
  }

  open(FILE,$file) || usage("Couldn't open file: $file");

  my @fields;

  while(<FILE>) {
    next if $opt->{ignore} && /$opt->{ignore}/;
    chomp;
    my @cols = split($opt->{delim});
    my $col = $cols[$opt->{field}];
    push(@fields, $col) if $#cols+1>=$opt->{field};
  }
  close(FILE);
  ($add, @fields);
}

##################################################
# Main code
##################################################
sub main {
  my $opt = parse_args();

  my %final;
  foreach my $file ( @{$opt->{files}} ) {
    my ($add,@fields) = get_file($opt,$file);
    foreach my $field ( @fields ) {
      my $key = $opt->{ic} ? lc($field) : $field;
      $final{$key}=$field if $add;
      delete $final{$key} unless $add;
    }
  }

  foreach my $key ( sort keys %final ) {
    print "$final{$key}\n";
  }
}
main();
