diff --git a/bin/pidiff b/bin/pidiff new file mode 100755 index 0000000..c7f5ba7 --- /dev/null +++ b/bin/pidiff @@ -0,0 +1,97 @@ +#!/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{$_}; +}