Makefile.am (SUBDIRS): Move intl to be built before compat.
[enscript.git] / scripts / diffpp.in
1 #!@PERLPROG@
2 # -*- perl -*-
3 #
4 # Pretty-print diff outputs with GNU enscript.
5 # Copyright (c) 1996-1998 Markku Rossi
6 #
7 # Author: Markku Rossi <mtr@iki.fi>
8 #
9
10 #
11 # This file is part of GNU Enscript.
12 #
13 # Enscript is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
17 #
18 # Enscript is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 # GNU General Public License for more details.
22 #
23 # You should have received a copy of the GNU General Public License
24 # along with Enscript.  If not, see <http://www.gnu.org/licenses/>.
25 #
26
27 #
28 # Original idea by Trent Fisher <trent@informix.com>
29 # Thanks to:
30 #  - Tero Kivinen <kivinen@iki.fi> for the first prototype
31 #  - Tait Cyrus <tait.cyrus@mci.com> for fixes and cleanups
32 #
33
34 $file = shift(@ARGV);
35 $add_gray = ".80";
36 $del_gray = ".60";
37
38 $program = $0;
39 $program =~ s/.*\///g;
40
41 sub usage {
42     warn "Usage: $program ORIGINAL_FILE < DIFF\n\n";
43     warn "Program reads a diff file from its standard input and annotates
44 ORIGINAL_FILE to show the changes made to the file.  The easiest way to use
45 this program is to use it as an input filter for GNU enscript:
46
47   \$ enscript -G2re --filter='rcsdiff %s | diffpp %s' *.c *.h
48   \$ enscript -G2re --filter='diff %s~ %s | diffpp %s' *.c *.h
49
50 ";
51 }
52
53 if (!defined($file) || defined($ARGV[0])) {
54     &usage;
55     exit 1;
56 }
57
58 if ($file eq "--help") {
59     &usage;
60     exit 0;
61 }
62
63 if ($file eq "--version") {
64     warn "diffpp 1.0\n";
65     exit 0;
66 }
67
68 # Read in original file into internal array.
69 open(FP, $file) || die "$program: couldn't open file `$file' for input: $!\n";
70 @orig_file = <FP>;
71 close(FP);
72 $[ = 1;
73 $orig_line_num = 1;
74 $orig_num_lines = @orig_file;
75
76 # Now read in file of diffs into internal array.
77 @diffs = <STDIN>;
78 $diff_line_num = 1;
79 $diff_num_lines = @diffs;
80
81 while ($diff_line_num <= $diff_num_lines) {
82     $_ = $diffs[$diff_line_num];
83     if (/a/) {
84         do_add($_);
85     } elsif (/d/) {
86         do_delete($_);
87     } elsif (/c/) {
88         do_change($_);
89     }
90 }
91
92 while ($orig_line_num <= $orig_num_lines) {
93     print $orig_file[$orig_line_num++];
94 }
95
96 # Handle new/added lines
97 #
98 # Formats used:
99 #       #a#
100 #       #a#,#
101 sub do_add {
102     ($line) = @_;
103     if ($line =~ /(\d+)a(\d+),(\d+)/) {
104         $insert_at_line = $1;
105         $num_new_lines = $3 - $2 + 1;
106     } elsif ($line =~ /(\d+)a(\d+)/) {
107         $insert_at_line = $1;
108         $num_new_lines = 1;
109     }
110     &skip_to_line($insert_at_line);
111     printf("\000shade{$add_gray}");
112     &mark_to_line($num_new_lines, "+");
113     printf("\000shade{1.0}");
114 }
115
116 # Handle deleted/removed lines
117 #
118 # Formats used:
119 #       #d#
120 #       #,#d#
121 sub do_delete {
122     ($line) = @_;
123     if ($line =~ /(\d+),(\d+)d(\d+)/) {
124         $num_del_lines = $2 - $1 + 1;
125     } elsif ($line =~ /(\d+)d(\d+)/) {
126         $num_del_lines = 1;
127     }
128     $del_from = $1;
129     &skip_to_line($del_from - 1);
130     printf("\000shade{$del_gray}");
131     &mark_to_line($num_del_lines, "-");
132     printf("\000shade{1.0}");
133     $orig_line_num += $num_del_lines;
134 }
135
136 # Handle changed/modified lines
137 #
138 # Formats used:
139 #       #,#c#,#
140 #       #,#c#
141 #       #c#,#
142 #       #c#
143 sub do_change {
144     ($line) = @_;
145     if ($line =~ /(\d+),(\d+)c(\d+),(\d+)/) {
146         $num_old_lines = $2 - $1 + 1;
147         $num_new_lines = $4 - $3 + 1;
148         $change_at_line = $1;
149     } elsif ($line =~ /(\d+),(\d+)c(\d+)/) {
150         $num_old_lines = $2 - $1 + 1;
151         $num_new_lines = 1;
152         $change_at_line = $1;
153     } elsif ($line =~ /(\d+)c(\d+),(\d+)/) {
154         $num_old_lines = 1;
155         $num_new_lines = $3 - $2 + 1;
156         $change_at_line = $1;
157     } elsif ($line =~ /(\d+)c(\d+)/) {
158         $num_old_lines = 1;
159         $num_new_lines = 1;
160         $change_at_line = $1;
161     }
162     # Mark old lines
163     &skip_to_line($change_at_line - 1);
164     $orig_line_num += $num_old_lines;   # skip over changed lines
165     printf("\000shade{$del_gray}");
166     &mark_to_line($num_old_lines, "-");
167     printf("\000shade{1.0}");
168     # Mark new lines
169     printf("\000shade{$add_gray}");
170     &mark_to_line($num_new_lines, "+");
171     printf("\000shade{1.0}");
172 }
173
174 sub skip_to_line {
175     ($line) = @_;
176
177     while ($orig_line_num <= $line) {
178         print $orig_file[$orig_line_num];
179         $orig_line_num++;
180     }
181 }
182
183 sub mark_to_line {
184     ($num_lines, $marker) = @_;
185
186     $diff_line_num++;           # skip over diff command
187     while ($num_lines > 0) {
188         $diff_line = substr($diffs[$diff_line_num++],3);
189         print "\000ps{gsave -5 0 rmoveto ($marker) show grestore}";
190         print $diff_line;
191         $num_lines--;
192     }
193 }