#!/usr/bin/perl
use warnings;
use Getopt::Std;

$cmd = $0;
getopts("i:j:bd:hHvc", \%opts);
$prog_name = "Binary diff";
$prog_version = "v0.1.1";
$prog = $prog_name . " " . $prog_version;
$release_date = "2011-05-13";
$copy = "Copyright (C) Peter Ivanov <peter__AT__ivanov__DOT__eu>, 2003-2011";

if (length(%opts) == 1 || $opts{h}) {
  usage();
}
if ($opts{v}) {
  print "$prog\n";
  print "Released: $release_date\n";
  exit;
}
if ($opts{c}) {
  copyright();
}
my $infile1 = '';
my $infile2 = '';
my $div = 16;
my $big = 0;
my $binary = 0;
if ($opts{i}) {
  $infile1 = $opts{i};
}
if ($opts{j}) {
  $infile2 = $opts{j};
}
if ($opts{d}) {
  $div = $opts{d};
}
if ($opts{H}) {
  $big = 1;
}
if ($opts{b}) {
  $binary = 1;
}
if (!($infile1 && $infile2)) {
  die "Missing parameter!\n";
}
print "Input file 1: $infile1\n";
print "Input file 2: $infile2\n";
print "Division: $div\n";
print "\n";

print "Opening $infile1... ";
open (FH1, "<", $infile1) || die "Can't open $infile1.\n";
binmode (FH1);
print "Ok.\n";
print "Opening $infile2... ";
open (FH2, "<", $infile2) || die "Can't open $infile2.\n";
binmode (FH2);
print "Ok.\n";

sub printbuf ($$@) 
{
  # $fnlen: max length of filename
  my ($fnlen, $filename, @buf) = @_;
  my $bufhex = ''; # buffer in hex format
  my $buffmt = ''; # buffer in preformatted format
  my $buflen = @buf;
  for ($i = 0; $i < $buflen; $i++) {
    unless ($binary) {
      $formatStr = $big ? "%02X " : "%02x ";
    }
    else {
      $formatStr = "%08b ";
    }
    $bufhex .= sprintf ($formatStr, ord($buf[$i]));
    if (ord($buf[$i]) >= 32 && ord($buf[$i]) <= 127) {
      $buffmt .= $buf[$i];
    }
    else {
      $buffmt .= ".";
    }
  }
  printf ("%-" . $fnlen . "s | %s| %s\n", $filename, $bufhex, $buffmt);
}

$fnlen = length (@$infile1) > length (@$infile2) ? length ($infile1) : length ($infile2);
print "Comparing...\n";
$buf1 = '';
$buf2 = '';
$matches = 1;
$bufsize = $div;
while (!eof (FH1) || !eof (FH2)) {
  my $pr = 0;
  my $r1 = read (FH1, $buf1, $bufsize);
  if (!defined ($r1)) {
    die "Can't read!\n";
  }
  my $r2 = read (FH2, $buf2, $bufsize);
  if (!defined ($r2)) {
    die "Can't read!\n";
  }
  my @b1;
  @b1 = split (//, $buf1);
  my @b2;
  @b2 = split (//, $buf2);
  if ($r1 == $r2) {
    for ($i = 0; $i < $r1; $i++) {
      if ($b1[$i] ne $b2[$i]) {
        $matches = 0;
	$pr = 1;
      }
    }
  }
  else {
    $matches = 0;
    $pr = 1;
  }
  if ($pr) {
    if (!eof (FH1)) {
        $ofs = tell (FH1) - $r1;
    }
    else {
        $ofs = tell (FH2) - $r2;
    }
    my $s = $big ? "Offset: %i 0x%X\n" : "Offset: %i 0x%x\n";
    printf ($s, $ofs, $ofs);
    printbuf ($fnlen, $infile1, @b1);
    printbuf ($fnlen, $infile2, @b2);
  }
}
if ($matches) {
  print "Matches!\n";
}
else {
  print "Does not match!\n";
}

#print "Closing $infile1...";
close FH2;
#print "Ok.\n";
#print "Closing $infile2...";
close FH1;
#print "Ok.\n";
my $exitcode = $matches ? 1 : 0;
exit $exitcode;


##############################################################################
sub usage
{
  die<<"EOT";
$prog
$copy

This program comes with ABSOLUTELY NO WARRANTY; for details type `$cmd -c'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `$cmd -c' for details.

Usage: $cmd -i <infile1> -j <infile2> [-b] [-d <number> -h -v -c]
Options:
  -i: input file 1
  -j: input file 2
  -b: print in binary format
  -d: division number (default 16)
  -H: hex with big alphas 
  -h: prints help
  -v: prints version
  -c: prints copyright informations
EOT
}

sub copyright
{
die<<"EOT";
$prog
$copy

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

EOT
  exit;
}

# vim:ts=2:
