#!perl -w
use strict;
use Language::Zcode::Parser;
=head1 NAME
tuxedo.pl - find subs in a Z-code file
=head1 DESCRIPTION
This program finds the locations of the subroutines in a Z-code file.
Right now, the program is actually used to confirm that the pure Perl
parser is working - it compares the results with the results from
the state-of-the-art (1992) txd parser, and lists any differences.
(Note: some differences are OK. It appears that txd sometimes ignores
a @ret in a file if there's another returning opcode just before it;
in weird cases, this can lead to significant differences in the reported
last command in the sub.)
=cut
# Get args
my $infile = shift;
# We're going to open a txd AND Perl parser in order to compare results.
# Of course, some stuff, like reading the header, only needs to be done once
my $tParser = new Language::Zcode::Parser "TXD";
my $pParser = new Language::Zcode::Parser "Perl";
# If they didn't put ".z5" at the end, find it anyway
$infile = $tParser->find_zfile($infile) || exit;
# Read in the file, store it in memory
$tParser->read_memory($infile);
# Parse header of the Z-file
$tParser->parse_header();
# Run txd to get the address of each subroutine
my %tSubs = map {$_->address, $_->last_command_address}
$tParser->find_subs($infile);
my %pSubs = map {$_->address, $_->last_command_address} $pParser->find_subs();
# Analyze results
my @found = sort {$a <=> $b} keys(%tSubs); # assume txd found everything
print "Found ",scalar(keys %pSubs)," routines out of ", $#found+1,".\n";
my $ct = 0;
foreach my $r (@found) {
my $t = exists $pSubs{$r} ? $pSubs{$r} : "UNFOUND";
my $txd_end = $tSubs{$r};
if (my $diff = exists $pSubs{$r} ? $pSubs{$r} - $txd_end : "N/A") {
print "Rtn Start\tLast Cmd: Perl\ttxd\tDiff\n" unless $ct++;
printf "%x (%d)\t\t$t\t$txd_end\t$diff\n", $r, $r;
}
}
foreach my $r (keys %pSubs) {
printf "BAD: found extra sub %x (%d) ending at $pSubs{$r}\n", $r, $r
if !exists $tSubs{$r};
}
delete @tSubs{keys %pSubs};
print "Unfound subs: ";
print keys %tSubs ? map({sprintf "%x ",$_} keys %tSubs) : "None!";
print "\n";
exit;
=head1 NOTES
If I had but world enough and time, tuxedo could become a fancy (more
"formal") version of txd and its companion, infodump. But in reality,
it's more of a black-and-white version of txd.
=head1 AUTHOR
Amir Karger <akarger@cpan.org>
=head1 LICENSE
Copyright (c) 2004 Amir Karger. All rights reserved.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
=cut