|
| 1 | +#!/usr/bin/perl -w |
| 2 | + |
| 3 | +use strict; |
| 4 | + |
| 5 | +if(scalar(@ARGV)!=3) |
| 6 | +{ |
| 7 | + print STDERR "syntax: $0 <goto-diff> <old file-or-dir> <new file-or-dir>\n"; |
| 8 | + exit(1); |
| 9 | +} |
| 10 | +my ($diff, $old, $new)=@ARGV; |
| 11 | + |
| 12 | +open DIFF, "<$diff" or die $!; |
| 13 | + |
| 14 | +# goto-diff Input: |
| 15 | +#/** main **/ |
| 16 | +#D // 0 file data-dep.c line 3 function main |
| 17 | +# signed int cmd; |
| 18 | +#+ // 1 file data-dep.c line 4 function main |
| 19 | +# signed int other; |
| 20 | +#D // 2 file data-dep.c line 5 function main |
| 21 | +# signed int other2; |
| 22 | +#- // 2 file data-dep-before.c line 6 function main |
| 23 | +# IF !(other2 != 0) THEN GOTO 1 |
| 24 | +#+ // 4 file data-dep.c line 8 function main |
| 25 | +# other = 1; |
| 26 | +#+ // 5 file data-dep.c line 11 function main |
| 27 | +# 1: IF !(other2 != 0) THEN GOTO 2 |
| 28 | +#D // 6 file data-dep.c line 13 function main |
| 29 | +# cmd = cmd | 0x4; |
| 30 | +#+ // 7 file data-dep.c line 16 function main |
| 31 | +# 2: IF !(cmd == 2) THEN GOTO 3 |
| 32 | +#+ // 8 file data-dep.c line 18 function main |
| 33 | +# other = 3; |
| 34 | +# // 9 file data-dep.c line 21 function main |
| 35 | +# 3: return 0; |
| 36 | +# // 10 file data-dep.c line 21 function main |
| 37 | +# dead other2; |
| 38 | +#+ // 11 file data-dep.c line 21 function main |
| 39 | +# dead other; |
| 40 | +# // 12 file data-dep.c line 21 function main |
| 41 | +# dead cmd; |
| 42 | +# // 13 file data-dep.c line 21 function main |
| 43 | +# GOTO 4 |
| 44 | +# // 14 file data-dep.c line 22 function main |
| 45 | +# dead other2; |
| 46 | +#+ // 15 file data-dep.c line 22 function main |
| 47 | +# dead other; |
| 48 | +# // 16 file data-dep.c line 22 function main |
| 49 | +# dead cmd; |
| 50 | +# // 17 file data-dep.c line 22 function main |
| 51 | +# 4: END_FUNCTION |
| 52 | + |
| 53 | +my %edits=(); |
| 54 | + |
| 55 | +my %edit=(); |
| 56 | + |
| 57 | +while(<DIFF>) |
| 58 | +{ |
| 59 | + chomp; |
| 60 | + my $line=$_; |
| 61 | + |
| 62 | + if($line =~ /^\/\*\*/ || |
| 63 | + $line =~ /^\s+\/\/ \d+ file (.*) line (\d+) function \S+$/ || |
| 64 | + $line =~ /^\s+(\d+:\s+)?(dead |END_FUNCTION).*/) |
| 65 | + { |
| 66 | + %edit=(); |
| 67 | + } |
| 68 | + elsif($line =~ /^([\+CD\-cd])\s+\/\/ \d+ file (.*) line (\d+) function \S+$/) |
| 69 | + { |
| 70 | + %edit=( mod => $1, file => $2, line => $3 ); |
| 71 | + } |
| 72 | + else |
| 73 | + { |
| 74 | + if(defined($edit{mod})) |
| 75 | + { |
| 76 | + if($edit{mod} =~ /^[\+CD]$/) |
| 77 | + { |
| 78 | + if($edit{mod} eq '+' || |
| 79 | + !defined($edits{$edit{file}}{$edit{line}}) || |
| 80 | + $edits{$edit{file}}{$edit{line}} =~ /^[cd]$/) |
| 81 | + { |
| 82 | + $edits{$edit{file}}{$edit{line}}=$edit{mod}; |
| 83 | + } |
| 84 | + } |
| 85 | + elsif($edit{mod} =~ /^[\-cd]$/) |
| 86 | + { |
| 87 | + if(!defined($edits{$edit{file}}{$edit{line}}) || |
| 88 | + ($edit{mod} eq '-' && $edits{$edit{file}}{$edit{line}} =~ /^[cd]$/)) |
| 89 | + { |
| 90 | + $edits{$edit{file}}{$edit{line}}=$edit{mod}; |
| 91 | + } |
| 92 | + } |
| 93 | + else |
| 94 | + { |
| 95 | + die "Invalid modification $edit{mod}\n"; |
| 96 | + } |
| 97 | + |
| 98 | + %edit=(); |
| 99 | + } |
| 100 | + } |
| 101 | +} |
| 102 | + |
| 103 | +use File::Temp qw(tempdir); |
| 104 | +my $dir=tempdir(CLEANUP => 1); |
| 105 | + |
| 106 | +`cp -a $old $dir/`; |
| 107 | +`cp -a $new $dir/`; |
| 108 | + |
| 109 | +foreach my $f (keys(%edits)) |
| 110 | +{ |
| 111 | + my $f_edit="$dir/$f"; |
| 112 | + |
| 113 | + foreach my $l (keys(%{$edits{$f}})) |
| 114 | + { |
| 115 | + if($edits{$f}{$l} =~ /^[CDcd]$/) |
| 116 | + { |
| 117 | + `sed -i '${l}s/^/$edits{$f}{$l}#/' $f_edit`; |
| 118 | + } |
| 119 | + } |
| 120 | +} |
| 121 | + |
| 122 | +my @diff_to_clean=split('\n', `cd $dir && diff -urN $old $new`); |
| 123 | +my @clean_diff=(); |
| 124 | +my %rm_lines=(); |
| 125 | + |
| 126 | +foreach my $l (@diff_to_clean) |
| 127 | +{ |
| 128 | + my $push=1; |
| 129 | + |
| 130 | + if($l =~ /^-([cd])#(.*)/) |
| 131 | + { |
| 132 | + $rm_lines{$2}=1; |
| 133 | + push @clean_diff, "$1$2"; |
| 134 | + $push=0; |
| 135 | + } |
| 136 | + elsif($l =~ /^\+(.*)/) |
| 137 | + { |
| 138 | + foreach my $r (keys(%rm_lines)) |
| 139 | + { |
| 140 | + if($1 eq $r) |
| 141 | + { |
| 142 | + $push=0; |
| 143 | + delete $rm_lines{$r}; |
| 144 | + last; |
| 145 | + } |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | + push @clean_diff, $l if($push); |
| 150 | +} |
| 151 | + |
| 152 | +%rm_lines=(); |
| 153 | +@diff_to_clean=@clean_diff; |
| 154 | +@clean_diff=(); |
| 155 | + |
| 156 | +foreach my $l (reverse(@diff_to_clean)) |
| 157 | +{ |
| 158 | + my $unshift=1; |
| 159 | + |
| 160 | + if($l =~ /^\+([CD])#(.*)/) |
| 161 | + { |
| 162 | + $rm_lines{$2}=1; |
| 163 | + unshift @clean_diff, "$1$2"; |
| 164 | + $unshift=0; |
| 165 | + } |
| 166 | + elsif($l =~ /^-(.*)/) |
| 167 | + { |
| 168 | + foreach my $r (keys(%rm_lines)) |
| 169 | + { |
| 170 | + if($1 eq $r) |
| 171 | + { |
| 172 | + $unshift=0; |
| 173 | + delete $rm_lines{$r}; |
| 174 | + last; |
| 175 | + } |
| 176 | + } |
| 177 | + } |
| 178 | + |
| 179 | + unshift @clean_diff, $l if($unshift); |
| 180 | +} |
| 181 | + |
| 182 | +use Term::ANSIColor; |
| 183 | + |
| 184 | +foreach my $l (@clean_diff) |
| 185 | +{ |
| 186 | + if($l =~ /^(\s+|---|\+\+\+|@@)/) |
| 187 | + { |
| 188 | + print "$l\n"; |
| 189 | + } |
| 190 | + elsif($l =~ /^-/) |
| 191 | + { |
| 192 | + print colored("$l", 'red'), "\n"; |
| 193 | + } |
| 194 | + elsif($l =~ /^[cd]/) |
| 195 | + { |
| 196 | + print colored("$l", 'cyan'), "\n"; |
| 197 | + } |
| 198 | + elsif($l =~ /^\+/) |
| 199 | + { |
| 200 | + print colored("$l", 'green'), "\n"; |
| 201 | + } |
| 202 | + elsif($l =~ /^[CD]/) |
| 203 | + { |
| 204 | + print colored("$l", 'yellow'), "\n"; |
| 205 | + } |
| 206 | + else |
| 207 | + { |
| 208 | + die "Invalid diff output $l\n"; |
| 209 | + } |
| 210 | +} |
0 commit comments