#!/usr/bin/perl
#------------------------------------------------------------------------------
# $Id: hdiff,v 1.4 2002/06/09 02:18:18 peters Exp $
#
# NAME: hdiff
#
# PURPOSE: HTML diff. Produces a colourised HTML diff output which is
# much easier to read than standard diff output.
#
# SOURCE: www.ginini.com/software/hdiff
#
# hdiff is derived from cvs2html from www.sslug.dk/cvs2html
#
# MODS: Thanks to Gordon McKinney to support recursion (-r) and
# multiple file files per diff run. Also fixed blank context
# lines removing the background fill.
#
#------------------------------------------------------------------------------
use Getopt::Std;
#
# You must use a version of diff that has unified output. GNU diff has this
# option, so you can leave the default setting as is on Linux based systems.
# For most other Unix systems, grab a copy of GNU diff from
# ftp://ftp.gnu.org/gnu/diffutils
#
$diff = 'diff';
#
# Colors and font to show the diff type of code changes
#
$diffcolorEmpty = '#CCCCCC'; # color of 'empty' lines
$diffcolorAdd = '#FF9999'; # Removed line(s) (left) ( - )
$diffcolorChange = '#99FF99'; # Changed line(s) ( both )
$diffcolorRemove = '#CCCCFF'; # Added line(s) ( - ) (right)
$diffcolorDarkChange = '#99CC99'; # lines, which are empty in change
#-----------------------------------------------------------------------------
# END OF CONFIGURABLE OPTIONS
#-----------------------------------------------------------------------------
$Version = "1.9.9";
#
# Process options
#
use vars qw($opt_s $opt_r);
getopts('h:f:t:rl:s') or Usage();
Usage() unless ( scalar @ARGV == 2 );
$File1 = $ARGV[0];
$File2 = $ARGV[1];
if ($opt_t) {
$Title = "$opt_t";
}
else {
$Title = "hdiff output";
}
die "$File1 not found\n" if ( ( !-f $File1 ) && ( !-d $File1 ) );
die "$File2 not found\n" if ( ( !-f $File2 ) && ( !-d $File2 ) );
HtmlHeader();
human_readable_diff( $File1, $File2 );
HtmlFooter();
exit 0;
#--------------------------------------------------------------------------
sub htmlify {
my ( $string, $pr ) = @_;
# Special Characters; RFC 1866
$string =~ s/&/&/g;
$string =~ s/\"/"/g;
$string =~ s/</g;
$string =~ s/>/>/g;
# get URL's as link ..
$string =~ s§(http|ftp)(://[-a-zA-Z0-9%.~:/]+)([?&]([-a-zA-Z0-9%.~:_]+)=([-a-zA-Z0-9%.~:_])+)*§$1$2$3§;
# get e-mails as link
$string =~ s§([-a-zA-Z0-9.]+@([-a-zA-Z0-9]+\.)+[A-Za-z]{2,4})§$1§;
# get #PR as link ..
if ( $pr && defined $prcgi ) {
$string =~ s!\b((pr[:#]?\s*#?)|((bin|conf|docs|gnu|i386|kern|misc|ports)\/))(\d+)\b!$&!ig;
}
return $string;
}
#------------------------------------------------------------------------------
sub spacedHtmlText {
my ( $string, $pr ) = @_;
# Cut trailing spaces
s/\s+$//;
# Expand tabs
$string =~ s/\t+/' ' x (length($&) * $tabstop - length($`) % $tabstop)/e
if ( defined $tabstop );
# replace and (§ is to protect us from htmlify)
# gzip can make excellent use of this repeating pattern :-)
$string =~ s/§/§%/g; #protect our & substitute
$string =~ s/ /§nbsp;§nbsp;§nbsp;§nbsp;§nbsp;§nbsp;§nbsp;§nbsp;/g;
$string =~ s/ /§nbsp;/g;
$string = htmlify($string);
# unescape
$string =~ s/§([^%])/&$1/g;
$string =~ s/§%/§/g;
return $string;
}
#------------------------------------------------------------------------------
sub flush_diff_rows {
my $j;
my ( $leftColRef, $rightColRef, $leftRow, $rightRow ) = @_;
if ( $state eq "PreChangeRemove" ) { # we just got remove-lines before
for ( $j = 0 ; $j < $leftRow ; $j++ ) {
print "
@$leftColRef[$j]
";
print "
\n";
}
}
elsif ( $state eq "PreChange" ) { # state eq "PreChange"
# we got removes with subsequent adds
for ( $j = 0 ; $j < $leftRow || $j < $rightRow ; $j++ ) { # dump out both cols
print "
";
if ( $j < $leftRow ) { print "
@$leftColRef[$j]
"; }
else { print "
"; }
if ( $j < $rightRow ) { print "
@$rightColRef[$j]
"; }
else { print "
"; }
print "
\n";
}
}
}
#------------------------------------------------------------------------------
sub HtmlHeader {
if ($opt_h) {
open HEADER, $opt_h or die "Can not open $opt_h $!\n";
print ;
close (HEADER);
}
else {
print qq(\n\n);
print qq($Title\n);
print qq(\n);
print qq(\n);
print qq(
$Title
\n);
}
}
#------------------------------------------------------------------------------
sub HtmlFooter {
print <