3 # This is a simple state machine.
5 # There is the state of the current file; its header is stored
6 # in $current_file to avoid outputting it when all hunks were
7 # culled. It is only printed before the first hunk, and then
8 # set to "" to avoid outputting it twice.
10 # There are the states of the current hunk, stored in
11 # * $current_hunk (possibly modified hunk)
12 # * $start_minus, $start_plus (from the original)
13 # * $plus, $minus, $space (the current count of the respective lines)
14 # a hunk is only printed (in flush_hunk) if any '+' or '-' lines
15 # are left after filtering.
17 # For $Log..$, there is the state $skip_logs, which is set to 1
18 # after seeing such a line, and set to 0 when the first line
19 # was seen which does not begin with '+'.
21 # A particularly nasty special case is when a single "*" was
22 # misattributed by the diff to be _inserted before_ a $Log, instead
23 # of _appended after_ a $Log.
24 # This is the purpose of the $before_log and $after_log variables:
25 # if not empty, the state machine expects the next line to begin
26 # with '+' or '-', respectively, and followed by a $Log. If this
27 # expectation is not met, the variable is output.
29 # The variable $plus_minus_adjust contains the number of lines which
30 # were skipped from the "+" side, so that the correct offset is shown.
33 # This function gets a hunk header.
35 # It initializes the state variables described above
40 ($start_minus, $dummy, $start_plus, $dummy) =
41 ($line =~ /^\@\@ -(\d+)(,\d+|) \+(\d+)(,\d+|) \@\@/);
42 $plus = $minus = $space = 0;
47 # we prefer /dev/null as original file name when a file is new
48 if ($start_minus eq 0) {
49 $current_file =~ s/\n--- .*\n/\n--- \/dev\
/null\n/;
50 } elsif ($start_plus eq 0) {
51 $current_file =~ s/\n\+\+\+ .*\n/\n+++ \/dev\
/null\n/;
55 # This function is called whenever there is possibly a hunk to print.
56 # Nothing is printed if no '+' or '-' lines are left.
57 # Otherwise, if the file header was not yet shown, it does so now.
60 if (($plus > 0 || $minus > 0) && $current_hunk ne '') {
61 if ($current_file ne "") {
67 print "\@\@ -$start_minus,$minus "
68 . "+" . ($start_plus - $start_plus_adjust)
75 # This adds a line to the current hunk and updates $space, $plus or $minus
79 $current_hunk .= $line;
82 } elsif ($line =~ /^\+/) {
84 } elsif ($line =~ /^-/) {
86 } elsif ($line =~ /^\\/) {
89 die "Unexpected line: $line";
93 # This function splits the current hunk into the part before the current
94 # line, and the part after the current line.
99 if ($start_minus == 0) {
100 # This patch adds a new file, just ignore that line
102 } elsif ($start_plus == 0) {
103 # This patch removes a file, so include the line nevertheless
111 } elsif ($line =~ /^\+/) {
113 $start_plus_adjust++;
115 init_hunk
"@@ -" . ($start_minus + $minus + $space)
116 . " +" . ($start_plus + $plus + $space)
120 $simple_keyword = "Id|Revision|Author|Date|Source|Header";
122 # This is the main loop
127 $start_plus_adjust = 0;
140 if (!/\+.*\$Log.*\$/) {
141 add_line
$before_log;
143 skip_line
$before_log;
149 if (!/-.*\$Log.*\$/) {
152 skip_line
$after_log;
167 } elsif (/^\+.*\$($simple_keyword).*\$/) {
169 } elsif (/^\@\@.*/) {
175 } elsif (/^-.*\$($simple_keyword).*\$/) {
178 } elsif (/^\+ *\*$/) {
180 } elsif (/^([- \+]).*\$Log.*\$/) {
189 # This loop just shows everything before the first diff, and then hands
190 # over to check_file whenever it sees a line beginning with "diff".