##
package Letter_B;
use strict;
use warnings;
our @ISA = qw( Letter );
sub new {
my $class = shift;
my %_hash = ( my_type => $class, letter => q{B}, );
bless \%_hash, $class;
}
1;
####
package Letter;
use strict;
use warnings;
sub new {
my $class = shift;
my %_hash;
if ( scalar @_ and $_[0] eq q{A} ) {
require Letter_A;
my $s = Letter_A->new();
return bless $s, $class;
}
if ( scalar @_ and $_[0] eq q{B} ) {
require Letter_B;
my $s = Letter_B->new();
return bless $s, $class;
}
# } else {
%_hash = ( my_type => $class, letter => q{}, );
bless \%_hash, $class;
# }
}
sub identify {
my $self = shift;
print q{I am a '} . $self->{my_type} . q{'} . qq{\n};
}
1;
####
#!/usr/bin/perl
use strict;
use warnings;
use lib q{.};
use Data::Dumper;
use Letter;
my $s = Letter->new(q{B});
$s->identify;
print Data::Dumper->Dump( [ \$s ], [qw( *s )] ), qq{\n};
####
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
$| = 1;
my @filename;
my %color = ( same => q{#000000}, file1 => q{#FF0000}, file2 => q{#0000FF}, );
my $outfile = $0 . q{.html};
if ( scalar( grep( /^-/, @ARGV ) ) ) {
my @local_color;
GetOptions(
'filename:s' => \@filename,
'outputfile:s' => \$outfile,
'color:s' => \@local_color,
'help' => \&help,
);
@filename = split( /,/, join( ',', @filename ) );
while ( scalar @filename > 2 ) {
pop @filename;
}
@local_color = split( /,/, join( ',', @local_color ) );
if ( scalar @local_color >= 3 ) {
$color{same} = $local_color[0];
$color{file1} = $local_color[1];
$color{file2} = $local_color[2];
}
if ( scalar @filename < 2 ) {
warn qq{Too few input files listed!\n};
&help;
}
}
else {
&help;
}
#
# Actual code here
#
open my $INF1, $filename[0] or die $!;
open my $INF2, $filename[1] or die $!;
open my $OUTF, q{>}, $outfile or die $!;
write_header( $OUTF, \@filename, $outfile, \%color );
my $i = 0;
process_files( $INF1, $INF2, $OUTF, \$i, \@filename, \%color );
process_files( $INF1, $INF2, $OUTF, \$i, \@filename, \%color );
process_remaining_file( $INF1, $OUTF, 0, \$i, \@filename, \%color );
close $INF1;
process_remaining_file( $INF2, $OUTF, 1, \$i, \@filename, \%color );
close $INF2;
write_footer($OUTF);
close $OUTF;
sub process_files {
my ( $INF1, $INF2, $OUTF, $linecount, $fn, $color ) = @_;
while ( defined $INF1 and defined $INF2 ) {
my @p1;
my @p2;
my $l1 = <$INF1>;
last unless defined $l1;
chomp $l1;
@p1 = split //, $l1;
my $l2 = <$INF2>;
last unless defined $l2;
chomp $l2;
@p2 = split //, $l2;
$$linecount++;
my $out1 = sprintf q{%06d: }, $color->{same}, $$linecount;
my $out2 = sprintf q{%06d: }, $color->{same}, $$linecount;
my $state = 0;
while ( scalar @p1 and scalar @p2 ) {
my $e1 = shift @p1;
my $e2 = shift @p2;
if ( ( ( ord $e1 == ord $e2 ) and ( !$state ) ) or ( ( ord $e1 != ord $e2 ) and ($state) ) ) {
$out1 .= $e1;
$out2 .= $e2;
}
else {
$state = !$state;
$out1 .= sprintf qq{%s}, $color->{ ( $state ? q{file1} : q{same} ) }, $e1;
$out2 .= sprintf qq{%s}, $color->{ ( $state ? q{file2} : q{same} ) }, $e2;
}
}
if ( scalar @p1 ) {
if ($state) {
$out1 .= sprintf qq{%s}, join( q{}, @p1 );
}
else {
$out1 .= sprintf qq{%s}, $color->{file1}, join( q{}, @p1 );
}
}
elsif ( scalar @p2 ) {
if ($state) {
$out2 .= sprintf qq{%s}, join( q{}, @p2 );
}
else {
$out2 .= sprintf qq{%s}, $color->{file2}, join( q{}, @p2 );
}
}
$out1 .= qq{\n};
$out2 .= qq{\n};
print $OUTF $out1, $out2, qq{\n};
}
}
sub process_remaining_file {
my ( $inhandle, $outhandle, $file_id, $linecount, $fn, $color ) = @_;
while ( defined $inhandle ) {
my $line = <$inhandle>;
last unless defined $line;
$$linecount++;
chomp $line;
my $out1;
my $out2;
if ($file_id) {
$out1 = sprintf qq{%06d: -%s closed-\n}, $$linecount, $fn->[0];
$out2 = sprintf qq{%06d: %s\n}, $$linecount, $color->{file2}, $line;
}
else {
$out2 = sprintf qq{%06d: -%s closed-\n}, $$linecount, $fn->[1];
$out1 = sprintf qq{%06d: %s\n}, $$linecount, $color->{file1}, $line;
}
print $outhandle $out1, $out2, qq{\n};
}
}
sub help {
printf <
Output filename: $outfilename
File
Color
$color{same}
Matching
$color{file1}
$filename->[0]
$color{file2}
$filename->[1]
HEADER
}
sub write_footer {
my ($OUTF) = @_;
print $OUTF <