#!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 =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