From: Tom Christiansen <tchrist@convex.COM>
Subject: Re: Xref program for files?
Originator: tchrist@pixel.convex.com
Date: Fri, 16 Oct 1992 13:37:16 GMT
Distribution: na
Reply-To: tchrist@convex.COM (Tom Christiansen)
Organization: Convex Computer Corporation, Colorado Springs, CO
X-Disclaimer: This message was written by a user at CONVEX Computer
              Corp. The opinions expressed are those of the user and
              not necessarily those of CONVEX.

From the keyboard of rjkopp@wraith.syr.EDU (Ray Kopp):
:
:Does anyone know of a program to cross-referance Perl programs?  
:What this means is a program that pulls out all the variable names
:and then tells what line numbers they are referenced in?  It seems
:that there has to be something already done for this?  Anyone know
:of one and where it can be obtained.
:  
:I also want it to do it for all variables within the program, not 
:just one at a time.

#!/usr/local/bin/perl
# pfcf -- tchrist@convex.com

while (<>) {
    s/^\s+//;
    next if /^$/;
    next if /^#/;
    chop;

    if (/sub ([\w']+)\s*\{/) {
	warn "$1 redeclared at $ARGV line $.\n" if defined $decl{$1};
	$func = $1;
	$func = "main$func" if $func =~ /^'/;
	$decl{$func} = $_;
	$whence{$func} = "$ARGV:$.";
	next;
    }

    s/\s*#.*//; 
    next if /^$/;

    $_; 
    # comment this out and the next line gets an abort!!!
    #	NULL regexp parameter at ../tools/funcalls line 25, <> line 8.

    while (/((\bdo\s|&)([\$a-zA-Z_][\w']*))/g) {
	$func = $3;
	next if /open.*["'][<>][\$&]/;
	$func = "main$func" if $func =~ /^'/;
	$use{$func} .= "$ARGV:$.:$_\n";
    } 

} continue {
    close ARGV if eof;
} 


for (keys %decl) {
    defined $use{$_} || push(@unused, $_);
} 
&write(UNUSED, join(', ', sort @unused)) if @unused;

for (keys %use) {
    defined $decl{$_} || push(@undeclared, $_);
}
&write(UNDECLARED, join(', ', sort @undeclared)) if @undeclared;

for $routine (sort keys %use) {
    ($comment) = ($decl{$routine} =~ /(#\s*\S.*\S)/);
    ($file, $line) = split(/:/, $whence{$routine}, 2);
    &write(ROUTINE, $routine, $line, "$file $comment");

    ($ofile,$oline) = ();
    for $entry (split(/\n/, $use{$routine})) {
	($file, $line, $context) = split(':', $entry, 3);
	next if $file eq $ofile && $line == $oline;
	$nfile = ($file eq $ofile) ? '' : $file;
	&write(CONTEXT, $nfile, $line, $context);
	($ofile,$oline) = ($file, $line);
    } 

    &write(NEWLINE);
} 

exit;

##########################

sub write {
    local($~, $f0, $f1, $f2, $f3, $f4, $f5, $f6) = @_;
    write;
} 


format UNUSED =
Declared but never used: 
~~   ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    $f0

.

format UNDECLARED =
Used but not declared: 
~~   ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    $f0

.


format ROUTINE =
@<<<<<<<<<<<<<<<<<<<< @>>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	$f0,	      $f1,  $f2
.

format CONTEXT =
 @<<<<<<<<<<<<<<<<<<< @>>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$f0, $f1, $f2
. 

format NEWLINE = 

.
--
    Tom Christiansen      tchrist@convex.com      convex!tchrist

    Be consistent.
            --Larry Wall in the perl man page 
-- 
    Tom Christiansen      tchrist@convex.com      convex!tchrist
    Q. Why is this so clumsy?
    A. The trick is to use Perl's strengths rather than its weaknesses.
            --Larry Wall in <8225@jpl-devvax.JPL.NASA.GOV>
Newsgroups: comp.lang.perl,comp.lang.tcl