Elliot Lee 03bb291
#!/usr/bin/perl
Elliot Lee 03bb291
Elliot Lee 03bb291
# RPM (and it's source code) is covered under two separate licenses. 
Elliot Lee 03bb291
Elliot Lee 03bb291
# The entire code base may be distributed under the terms of the GNU
Elliot Lee 03bb291
# General Public License (GPL), which appears immediately below.
Elliot Lee 03bb291
# Alternatively, all of the source code in the lib subdirectory of the
Elliot Lee 03bb291
# RPM source code distribution as well as any code derived from that
Elliot Lee 03bb291
# code may instead be distributed under the GNU Library General Public
Elliot Lee 03bb291
# License (LGPL), at the choice of the distributor. The complete text
Elliot Lee 03bb291
# of the LGPL appears at the bottom of this file.
Elliot Lee 03bb291
Elliot Lee 03bb291
# This alternatively is allowed to enable applications to be linked
Elliot Lee 03bb291
# against the RPM library (commonly called librpm) without forcing
Elliot Lee 03bb291
# such applications to be distributed under the GPL.
Elliot Lee 03bb291
Elliot Lee 03bb291
# Any questions regarding the licensing of RPM should be addressed to
Elliot Lee 03bb291
# Erik Troan <ewt@redhat.com>.
Elliot Lee 03bb291
Elliot Lee 03bb291
# a simple makedepends like script for perl.
Elliot Lee 03bb291
 
Elliot Lee 03bb291
# To save development time I do not parse the perl grammmar but
Elliot Lee 03bb291
# instead just lex it looking for what I want.  I take special care to
Elliot Lee 03bb291
# ignore comments and pod's.
Elliot Lee 03bb291
Elliot Lee 03bb291
# It would be much better if perl could tell us the dependencies of a
Elliot Lee 03bb291
# given script.
Elliot Lee 03bb291
Elliot Lee 03bb291
# The filenames to scan are either passed on the command line or if
Elliot Lee 03bb291
# that is empty they are passed via stdin.
Elliot Lee 03bb291
Elliot Lee 03bb291
# If there are strings in the file which match the pattern
Elliot Lee 03bb291
#     m/^\s*\$RPM_Requires\s*=\s*["'](.*)['"]/i
Elliot Lee 03bb291
# then these are treated as additional names which are required by the
Elliot Lee 03bb291
# file and are printed as well.
Elliot Lee 03bb291
Elliot Lee 03bb291
# I plan to rewrite this in C so that perl is not required by RPM at
Elliot Lee 03bb291
# build time.
Elliot Lee 03bb291
Elliot Lee 03bb291
# by Ken Estes Mail.com kestes@staff.mail.com
Elliot Lee 03bb291
Elliot Lee 03bb291
if ("@ARGV") {
Elliot Lee 03bb291
  foreach (@ARGV) {
Elliot Lee 03bb291
    process_file($_);
Elliot Lee 03bb291
  }
Elliot Lee 03bb291
} else {
Elliot Lee 03bb291
  
Elliot Lee 03bb291
  # notice we are passed a list of filenames NOT as common in unix the
Elliot Lee 03bb291
  # contents of the file.
Elliot Lee 03bb291
  
Elliot Lee 03bb291
  foreach (<>) {
Elliot Lee 03bb291
    process_file($_);
Elliot Lee 03bb291
  }
Elliot Lee 03bb291
}
Elliot Lee 03bb291
Elliot Lee 03bb291
Elliot Lee 03bb291
foreach $module (sort keys %require) {
Elliot Lee 03bb291
  if (length($require{$module}) == 0) {
Elliot Lee 03bb291
    print "perl($module)\n";
Elliot Lee 03bb291
  } else {
Elliot Lee 03bb291
Elliot Lee 03bb291
    # I am not using rpm3.0 so I do not want spaces arround my
Elliot Lee 03bb291
    # operators. Also I will need to change the processing of the
Elliot Lee 03bb291
    # $RPM_* vairable when I upgrage.
Elliot Lee 03bb291
Elliot Lee 03bb291
    print "perl($module) >= $require{$module}\n";
Elliot Lee 03bb291
  }
Elliot Lee 03bb291
}
Elliot Lee 03bb291
Elliot Lee 03bb291
exit 0;
Elliot Lee 03bb291
Elliot Lee 03bb291
Elliot Lee 03bb291
Elliot Lee 03bb291
sub process_file {
Elliot Lee 03bb291
  
Elliot Lee 03bb291
  my ($file) = @_;
Elliot Lee 03bb291
  chomp $file;
Elliot Lee 03bb291
  
Elliot Lee 03bb291
  open(FILE, "<$file") || return;
Elliot Lee 03bb291
  
Elliot Lee 03bb291
  while (<FILE>) {
Elliot Lee 03bb291
    
Elliot Lee 03bb291
    # skip the documentation
Elliot Lee 03bb291
Elliot Lee 03bb291
    # we should not need to have item in this if statement (it
Elliot Lee 03bb291
    # properly belongs in the over/back section) but people do not
Elliot Lee 03bb291
    # read the perldoc.
Elliot Lee 03bb291
Elliot Lee 03bb291
    if ( (m/^=(head1|head2|pod|item)/) .. (m/^=(cut)/) ) {
Elliot Lee 03bb291
      next;
Elliot Lee 03bb291
    }
Elliot Lee 03bb291
Elliot Lee 03bb291
    if ( (m/^=(over)/) .. (m/^=(back)/) ) {
Elliot Lee 03bb291
      next;
Elliot Lee 03bb291
    }
Elliot Lee 03bb291
    
Elliot Lee 03bb291
    # skip the data section
Elliot Lee 03bb291
    if (m/^__(DATA|END)__$/) {
Elliot Lee 03bb291
      last;
Elliot Lee 03bb291
    }
Elliot Lee 03bb291
Elliot Lee 03bb291
    # Each keyword can appear multiple times.  Don't
Elliot Lee 03bb291
    #  bother with datastructures to store these strings,
Elliot Lee 03bb291
    #  if we need to print it print it now.
Elliot Lee 03bb291
    
Elliot Lee 03bb291
    if ( m/^\s*\$RPM_Requires\s*=\s*["'](.*)['"]/i) {
Elliot Lee 03bb291
      foreach $_ (split(/\s+/, $1)) {
Elliot Lee 03bb291
	print "$_\n";
Elliot Lee 03bb291
      }
Elliot Lee 03bb291
    }
Elliot Lee 03bb291
Elliot Lee 03bb291
    if ( 
Elliot Lee 03bb291
Elliot Lee 03bb291
# ouch could be in a eval, perhaps we do not want these since we catch
Elliot Lee 03bb291
# an exception they must not be required
Elliot Lee 03bb291
Elliot Lee 03bb291
#   eval { require Term::ReadLine } or die $@;
Elliot Lee 03bb291
#   eval "require Term::Rendezvous;" or die $@;
Elliot Lee 03bb291
#   eval { require Carp } if defined $^S; # If error/warning during compilation,
Elliot Lee 03bb291
Elliot Lee 03bb291
Elliot Lee 03bb291
	(m/^(\s*)         # we hope the inclusion starts the line
Elliot Lee 03bb291
	 (require|use)\s+(?!\{)     # do not want 'do {' loops
Elliot Lee 03bb291
	 # quotes around name are always legal
Elliot Lee 03bb291
	 [\'\"]?([^\;\ \'\"\t]*)[\'\"]?[\t\;\ ]
Elliot Lee 03bb291
	 # the syntax for 'use' allows version requirements
Elliot Lee 03bb291
	 \s*([.0-9]*)
Elliot Lee 03bb291
	 /x)
Elliot Lee 03bb291
       ) {
Elliot Lee 03bb291
      my ($whitespace, $statement, $module, $version) = ($1, $2, $3,$4);
Elliot Lee 03bb291
Elliot Lee 03bb291
      # we only consider require statements that are flush against
Elliot Lee 03bb291
      # the left edge. any other require statements give too many
Elliot Lee 03bb291
      # false positives, as they are usually inside of an if statement
Elliot Lee 03bb291
      # as a fallback module or a rarely used option
Elliot Lee 03bb291
Elliot Lee 03bb291
      ($whitespace ne "" && $statement eq "require") && next;
Elliot Lee 03bb291
Elliot Lee 03bb291
      # if there is some interpolation of variables just skip this
Elliot Lee 03bb291
      # dependency, we do not want
Elliot Lee 03bb291
      #        do "$ENV{LOGDIR}/$rcfile";
Elliot Lee 03bb291
   
Elliot Lee 03bb291
      ($module =~ m/\$/) && next;
Elliot Lee 03bb291
Elliot Lee 03bb291
      # skip if the phrase was "use of" -- shows up in gimp-perl, et al
Elliot Lee 03bb291
      next if $module eq 'of';
Elliot Lee 03bb291
Elliot Lee 03bb291
      # if the module ends in a comma we probaly caught some
Elliot Lee 03bb291
      # documentation of the form 'check stuff,\n do stuff, clean
Elliot Lee 03bb291
      # stuff.' there are several of these in the perl distribution
Elliot Lee 03bb291
Elliot Lee 03bb291
      ($module  =~ m/[,>]$/) && next;
Elliot Lee 03bb291
Elliot Lee 03bb291
      # if the module name starts in a dot it is not a module name.
Elliot Lee 03bb291
      # Is this necessary?  Please give me an example if you turn this
Elliot Lee 03bb291
      # back on.
Elliot Lee 03bb291
Elliot Lee 03bb291
      #      ($module =~ m/^\./) && next;
Elliot Lee 03bb291
Elliot Lee 03bb291
      # if the module ends with .pm strip it to leave only basename.
Elliot Lee 03bb291
      # starts with /, which means its an absolute path to a file
Elliot Lee 03bb291
      if ($module =~ m(^/)) {
Elliot Lee 03bb291
        print "$module\n";
Elliot Lee 03bb291
        next;
Elliot Lee 03bb291
      }
Elliot Lee 03bb291
Elliot Lee 03bb291
      # sometimes people do use POSIX qw(foo), or use POSIX(qw(foo)) etc
Elliot Lee 03bb291
      # we can strip qw.*$, as well as (.*$:
Elliot Lee 03bb291
      $module =~ s/qw.*$//;
Elliot Lee 03bb291
      $module =~ s/\(*$//;
Elliot Lee 03bb291
Elliot Lee 03bb291
      $module =~ s/\.pm$//;
Elliot Lee 03bb291
Elliot Lee 03bb291
      # some perl programmers write 'require URI/URL;' when 
Elliot Lee 03bb291
      # they mean 'require URI::URL;'
Elliot Lee 03bb291
Elliot Lee 03bb291
      $module =~ s/\//::/;
Elliot Lee 03bb291
Elliot Lee 03bb291
      # trim off trailing parenthesis if any.  Sometimes people pass
Elliot Lee 03bb291
      # the module an empty list.
Elliot Lee 03bb291
Elliot Lee 03bb291
      $module =~ s/\(\s*\)$//;
Elliot Lee 03bb291
Elliot Lee 03bb291
      if ( $module =~ m/^[0-9._]+$/ ) {
Elliot Lee 03bb291
      # if module is a number then both require and use interpret that
Elliot Lee 03bb291
      # to mean that a particular version of perl is specified
Elliot Lee 03bb291
Elliot Lee 03bb291
      if ($module =~ /5.00/) {
Elliot Lee 03bb291
        print "perl >= 0:$module\n";
Elliot Lee 03bb291
        next;
Elliot Lee 03bb291
      }
Elliot Lee 03bb291
      else {
Elliot Lee 03bb291
        print "perl >= 1:$module\n";
Elliot Lee 03bb291
        next;
Elliot Lee 03bb291
      }
Elliot Lee 03bb291
Elliot Lee 03bb291
      };
Elliot Lee 03bb291
Elliot Lee 03bb291
      # ph files do not use the package name inside the file.
Elliot Lee 03bb291
      # perlmodlib  documentation says:
Elliot Lee 03bb291
      
Elliot Lee 03bb291
      #       the .ph files made by h2ph will probably end up as
Elliot Lee 03bb291
      #       extension modules made by h2xs.
Elliot Lee 03bb291
      
Elliot Lee 03bb291
      # so do not expend much effort on these.
Elliot Lee 03bb291
Elliot Lee 03bb291
Elliot Lee 03bb291
      # there is no easy way to find out if a file named systeminfo.ph
Elliot Lee 03bb291
      # will be included with the name sys/systeminfo.ph so only use the
Elliot Lee 03bb291
      # basename of *.ph files
Elliot Lee 03bb291
Elliot Lee 03bb291
      ($module  =~ m/\.ph$/) && next;
Elliot Lee 03bb291
Elliot Lee 03bb291
      $require{$module}=$version;
Elliot Lee 03bb291
      $line{$module}=$_;
Elliot Lee 03bb291
    }
Elliot Lee 03bb291
    
Elliot Lee 03bb291
  }
Elliot Lee 03bb291
Elliot Lee 03bb291
  close(FILE) ||
Elliot Lee 03bb291
    die("$0: Could not close file: '$file' : $!\n");
Elliot Lee 03bb291
  
Elliot Lee 03bb291
  return ; 
Elliot Lee 03bb291
}