#!/usr/bin/perl -w # # Analyze whether a symbol is defined in the include tree of a source # file. # # This script is only supposed to work in the Linux kernel! If you're # lucky, you might find it to work somewhere else. # # (c) 2003, Thunder Anklin # my @includefiles = (); my @parsedfiles = (); my @file_lifo = (); my @includepath = (); my $arg; my $gcc_searchpath; my $debug = 0; sub for_each_include { # Please enter code here which shall be executed for each # includefile. # # $_[0] is the filename. } sub for_each_processed { # Please enter code here which shall be executed after a file # was processed. # # $_[0] is the filename. } sub printd { if ($debug) { printf @_; } } sub gcc_get_searchpath { local ($fd, $buf, $retval); $retval = ""; open($fd, "gcc -print-search-dirs |") or goto out; while (defined($buf = <$fd>)) { if ($buf =~ /^install:\s+(.*)\r?\n/) { if (-e $1 . "/include") { $retval = $1 . "/include"; } } } close($fd); out: return $retval; } sub includepath_add { local ($dirname) = @_; if ($dirname eq ".") { $dirname = $ENV{"PWD"}; } if (!($dirname =~ /^\//)) { $dirname = $ENV{"PWD"} . "/" . $dirname; } push(@includepath, $dirname) unless (! -d $dirname); return; } sub elem_in_stack { local ($elem, @stack) = @_; local ($i) = (0); for ($i = 0; $i < scalar(@stack); $i++) { if ($stack[$i] eq $elem) { return 1; } } return 0; } sub process_file { local ($filename) = @_; local ($buf, $i) = ("", 0); local ($fd); printd("Hit " . $filename . "\n"); push(@parsedfiles, $filename); for ($i = 0; $i < scalar(@includepath); $i++) { if (-e $includepath[$i] . "/" . $filename) { if (open($fd, "<" . $includepath[$i] . "/" . $filename)) { goto found_file; } printd("Whoops: %s: %s\n", $includepath[$i] . "/" . $filename, $!); } } if ($! == 2) { printd("WARNING: %s: no file found!\n", $filename); return 0; } return $!; found_file: while (defined($buf = <$fd>)) { if ($buf =~ /^\s*\#\s*include\s*\<([^\>]+)\>/) { local ($includefile) = ($1); if (!elem_in_stack($includefile, @includefiles)) { for_each_include($includefile); push(@includefiles, $includefile); push(@file_lifo, $includefile); } } } close($fd) or return($!); for_each_processed($filename); return 0; } if (!scalar(@ARGV)) { print(STDERR "Usage:\n" . __FILE__ . " [ -Iincludepath ... ] file [ file ... ]\n"); exit(1); } includepath_add("."); includepath_add("include"); $gcc_searchpath = gcc_get_searchpath(); if (length($gcc_searchpath) && -e $gcc_searchpath) { includepath_add($gcc_searchpath); } while (($ARGV[0] . "\n") =~ /^-I(.*)$/) { includepath_add($1); shift(); } printd("Include path:"); foreach $arg (@includepath) { print(" " . $arg); } print("\n"); if (!scalar(@ARGV)) { print(STDERR "Usage:\n" . __FILE__ . " [ -Iincludepath ... ] file [ file ... ]\n"); exit(1); } foreach $arg (@ARGV) { local ($retval) = (0); @includefiles = (); @parsedfiles = (); @file_lifo = ($arg); while (scalar(@file_lifo)) { $retval = process_file(shift(@file_lifo)); if ($retval) { printf("%s: Error: %i\n", $parsedfiles[-1], $retval); } } printd("%s: Processed %i includefiles.\n", $arg, scalar(@parsedfiles)); } exit(0); # Local variables: # perl-indent-level: 8 # End: