#!/usr/bin/perl
#
# pidiff - Position-independent diff filter
#
# Copyright 2012 by Werner Almesberger
#
# 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.
#


sub usage
{
	print STDERR <<'EOF'
usage: diff -u ... | $0 [-n] [-D]

  -n  print line numbers
  -D  print debug output
EOF
;
	exit(1);
}


while ($ARGV[0] =~ /^-/) {
	if ($ARGV[0] eq "-n") {
		$num = 1;
	} elsif ($ARGV[0] eq "-D") {
		$debug = 1;
	} else {
		&usage;
	}
	shift @ARGV;
}

$n = 0;
while (<>) {
	$n++;
	next unless /^[-+]/;
	if (/^-/) {
		push @{ $m{$'} }, $n;
	} else {
		push @{ $p{$'} }, $n;
	}
}
for $k (keys %p) {
	undef $bm, $mp;
	undef $bd;
	$em = $#{ $m{$k} };
	$ep = $#{ $p{$k} };
	$m = 0;
	$p = 0;
	while ($m <= $em && $p <= $ep) {
		$d = abs($m{$k}[$m]-$p{$k}[$p]);
		($bm, $bp, $bd) = ($m, $p, $d)
		    unless $d > $bd && defined $bd;
		if ($m{$k}[$m] <= $p{$k}[$p] && $m < $em) {
			$m++;
		} else {
			$p++;
		}
	}
# older variant, less efficient
#	for $m (0..$#{ $m{$k} }) {
#		for $p (0..$#{ $m{$k} }) {
#			$d = abs($m{$k}[$m]-$p{$k}[$p]);
#			($bm, $bp, $bd) = ($m, $p, $d)
#			    unless $d > $bd && defined $bd;
#		}
#	}
	next unless defined $bd;
	if ($debug) {
		chop($kk = $k);
		print STDERR
		    "$kk: del m at $bm ($m{$k}[$bm]) p at $bp ($p{$k}[$bp])\n";
	}
	splice(@{ $m{$k} }, $bm, 1);
	splice(@{ $p{$k} }, $bp, 1);
	redo;
}

for $k (keys %m) {
	for (@{ $m{$k} }) {
		$l{$_} = "-$k"; 
	}
}
for $k (keys %p) {
	for (@{ $p{$k} }) {
		$l{$_} = "+$k"; 
	}
}
for (sort { $a <=> $b } keys %l) {
	print "$_: " if $num;
	print $l{$_};
}
