All pastes #394311 Raw Edit

Someone

public text v1 · immutable
·published 2007-03-14 05:51 UTC
rendered paste body
#!/usr/bin/perl -w
use strict;
use warnings;
use Getopt::Std;

my $RCSID = '$Id: include.perl,v 358.3 2005-11-17 17:18:35-08 - - $';
$0 =~ s|^(.*/)?([^/]+)/*$|$2|;
my $EXITCODE = 0;
END { exit $EXITCODE; }
sub note(@){ print STDERR "$0: @_"; };
$SIG{'__WARN__'} = sub { note @_; $EXITCODE = 1; };
$SIG{'__DIE__'} = sub { warn @_; exit; };

my $MAN_PAGE = <<__END_MAN_PAGE__;
#
# NAME
#     include.perl - generate make dependencies from C source files
#
# SYNOPSIS
#     include.perl [-hsu] [filename...]
#
# DESCRIPTION
#     The include.perl utility performs a recursive search through C
#     source code and header files for #include directives, and prints
#     out a list of dependencies in sorted order with duplicates
#     removed.
#
# OPTIONS
#     Options may appear in any order but must precede all operands in
#     the manner of Getopt::Std::getopts.
#
#     -h   Print out help information in the format of a man page then
#          exit.  Other options and operands are ignored.
#
#     -s   Scan for include statements of the form `#include <...>' and
#          look for files relative to the system directory `/usr/
#          include'.  If `-u' is not explicitly specified, ignore user
#          files.
#
#     -u   Scan for include statements of the form `#include "..."' and
#          look for files relative to the current (user) directory.
#          This is the default if `-s' is not explicitly specified.  If
#          `-s' is explicitly specified, user files are processed only
#          if `-u' is also specified.
#
# OPERANDS
#     All operands are names of files to be scanned.  Each file is
#     scanned in turn for `#include' directives, this process
#     continuing for all indirectly included files to an arbitrary
#     depth.  If no filenames are specified, STDIN is read.  If
#     filenames are specified, then STDIN is read when a filename is
#     given as `-'.  Output is similar to `cc -xM' or `cc -xM1'.
#     Target names are generated by substituting a `.c' suffix by a
#     `.o' suffix.
#
# EXIT STATUS
#     0    No errors were detected.
#     1    Invalid options were detected, files could not be read, or
#          the argument list had files not ending in `.c'.
#
# DIRECTORIES
#     The directory hierarchy /usr/include contains the system include
#     files.
# $RCSID
__END_MAN_PAGE__
$MAN_PAGE =~ s/^#[ ]?//mg;

my %OPTIONS;
my %dependencies;
my %foundfiles;
my @worklist;
my $usr = 1; 
my $sys = 0;
getopts "hsu", \%OPTIONS;
if ($OPTIONS{'s'}) { 
	$sys=1; 
	$usr=0; 
}
$usr = 1 if $OPTIONS{'u'};
print $MAN_PAGE and exit if $OPTIONS{'h'};

for my $source (@ARGV) {
   next if $foundfiles {$source};
   if (!($source =~ m/.c$/)) {
      warn "$source: not a c source file\n";
      next;
   }
   $foundfiles {$source} = 1;
   unless (open FILE, $source) {
      warn "$source: $!\n";
   }else {
      my $target = $source;
      $target =~ s/.c$/.o/;
      $dependencies {"$target: $source"} = 1;
      while (defined (my $line = <FILE>)) {
         next unless $line =~ m/^\s*#include\s+(<.*?>|".*?")\s*$/;
         my $include = $1;
         $include =~ s|"(.*)"|$1|;
         $include =~ s|<(.*)>|/usr/include/$1|;
         if ($sys && $include =~ m|^/usr/include/|) {
            $dependencies {"$target: $include"} = 1;
            push @worklist, [$target, $include];
         }
         if ($usr && !($include =~ m|^/usr/include/|)) {
            $dependencies {"$target: $include"} = 1;
            push @worklist, [$target, $include];
         }
      };
   };
   close FILE;
}

while (@worklist) {
   my $pair = shift @worklist;
   my $target = $pair->[0];
   my $source = $pair->[1];
   next if $foundfiles {$source};
   $foundfiles {$source} = 1;
   unless (open FILE, $source) {
      warn "$source: $!\n";
   }else {
      while (defined (my $line = <FILE>)) {
         next unless $line =~ m/^\s*#include\s+(<.*?>|".*?")\s*$/;
         my $include = $1;
         $include =~ s|"(.*)"|$1|;
         $include =~ s|<(.*)>|/usr/include/$1|;
         if ($sys && $include =~ m|^/usr/include/|) {
            $dependencies {"$target: $include"} = 1;
            push @worklist, [$target, $include];
         }
         if ($usr && !($include =~ m|^/usr/include/|)) {
            $dependencies {"$target: $include"} = 1;
            push @worklist, [$target, $include];
         }
      };
   };
   close FILE;
}

for my $dep (sort keys %dependencies) { print $dep, "\n"; }