#!/usr/local/bin/perl # $Id: inctree,v 1.1.1.1 2001/11/16 17:16:36 dwm Exp $ # $Header: /cvs/local/share/inctree,v 1.1.1.1 2001/11/16 17:16:36 dwm Exp $ # $Log: inctree,v $ # Revision 1.1.1.1 2001/11/16 17:16:36 dwm # after rome burned. # # Revision 1.1 2001/11/16 17:16:36 dwm # . # # Revision 1.10 1998-06-11 09:35:42-05 dwm # *** empty log message *** # # Revision 1.9 1998-06-11 09:32:20-05 dwm # *** empty log message *** # # Revision 1.8 1996-06-20 11:09:00-05 dwm # *** empty log message *** # # Revision 1.7 1996-06-20 11:06:47-05 dwm # sucks on AIX build tree. # # Revision 1.6 1996-06-20 08:39:46-05 dwm # *** empty log message *** # # Revision 1.5 1996-06-20 08:34:11-05 dwm # fix for using other compiler. # # Revision 1.4 1995-06-07 20:15:35-0500 dwm # now we exclude the -c, -f*, and -M* compiler flags. # # Revision 1.3 1994-06-08 22:46:37-0500 dwm # added support for C++ # # Revision 1.2 1993/07/16 04:06:56 dwm # Zthe -? neeeded a \. # # Revision 1.1 1993/07/16 03:51:35 dwm # Initial revision # require 5.004; # 'inctree' created 93/07/09 11:40 to validate/print the #includes # for files. # from the camel book, p274 ################################# ############ GLOBALS ############ ################################# ( $prog = $0 ) =~ s#.*/##o ; $0 = join(' ', $prog, @ARGV) ; $CPP = $ENV{'CPP'} || 'gcc -E' ; $shiftwidth = 4 ; ################################# ########## SUBROUTINES ########## ################################# sub usage { print STDERR @_ if @_ ; print STDERR <<"EOU" ; usage: $prog [-d] [-D...] [-I...] [-l] [-m/pattern/] file... $prog runs the C preprocessor (default $CPP) on the specified files, passing along any -D or -I switches, then processes the output of cpp into a tree of who included what. Files included more than once are marked DUPLICATE. flags: -C... preprocessor definition (default $CPP_name). -D... defines for the preprocessor. -I... dirs to search for the #include files. -d prints debugging info. -h|-? print this message. -l prints the line numbers of the include statements. -m/../ outputs any lines including the pattern specified. -s\d sets shiftwidth (default $shiftwidth). EOU exit 1 ; } ################################# ############ MAIN ############ ################################# # require 'getopts.pl' ; # &Getopts('dD:I:lm:') || &usage ; while ( $ARGV[0] =~ /^-/ ) { $_ = shift ; if (/^-C(.*)/) { $opt_cpp = ( $1 ? $1 : shift ) ; } elsif (/^-([DU])(.*)/) { $defines .= " -$1" . ($2 ? $2 : shift ); } elsif (/^-I(.*)/) { $includes .= " -I" . ($1 ? $1 : shift ); } elsif (/^-m(.*)/) { push(@pats, $1 ? $1 : shift ); } elsif ( /^-d/ ) { $debug++ ; } elsif ( /^-l/ ) { $lines++ ; } elsif (/^-s(.*)/) { $shiftwidth = ( $1 ? $1 : shift ) ; } elsif (/^-h|^-\?/) { &usage ; } # other compiler flags elsif (/^-g(.*)|^-O(.*)|^-traditional|^-c|^-f(.*)|^-M(.*)/) { next ; } elsif (/^-v$/ ) { $verbose = $_ ; } else { push (@ccopts, $_); #&usage("Unrecognized switch $_\n") ; } } print STDERR "$defines\n" if $debug ; print STDERR "$includes\n" if $debug ; # build a subroutine to scan for patterns if ( @pats ) { $sub = "sub pats ()\n{\n" ; foreach $pat ( @pats ) { $sub .= " print '>>>>>>> ',\$_ if m$pat;\n" ; } $sub .= "}\n" ; print STDERR $sub if $debug ; eval $sub ; die $@ if $@ ; ++$pats ; } # process each file. foreach $file (@ARGV) { if (length $opt_cpp) { $CPP_name = $opt_cpp; } elsif ($file =~ /.C$|.cc$/) { $CPP_name = "g++ -E" ; } else { $CPP_name = $CPP ; } $ccopts = join (" ", @ccopts); $pipecmd = "$CPP_name $verbose $ccopts $defines $includes $file|" ; open(CPP,$pipecmd) || die "Can't run $pipecmd: $!\n" ; $line = 2 ; while () { ++$line ; pats () if $pats ; # avoid expensive call if we can. next unless /^#/ ; next unless /^# \d/ ; (undef, $newline, $filename) = split ; $filename =~ s/\"//g ; # now figure out if it's push, pop, or neither. if ($stack[$#stack] eq $filename) { $line = $newline - 1 ; next ; } if ($stack[$#stack - 1] eq $filename) # Leaving file. { $indent -= $shiftwidth ; $line = pop(@lines) - 1 ; pop(@stack) ; } else # New file. { printf "%6d ", $line -2 if $lines ; push(@lines, $line) ; $line = $newline ; print "\t" x ($indent / 8), ' ' x ($indent % 8), $filename ; print " DUPLICATE" if $seen{$filename}++ ; print "\n" ; $indent += $shiftwidth ; push(@stack, $filename) ; } } close CPP ; $indent = 0 ; %seen = () ; print "\n\n" ; $line = 0 ; } exit 0