#!/usr/bin/perl use strict; use File::Find qw(find); use Getopt::Std qw(getopts); use Carp; use vars ( q!$opt_v!, # give debug info q!$opt_w!, # warn about missing descs on modules q!$opt_a!, # include relative paths q!$opt_s!, # sort output within each directory ); $| = 1; getopts('wvas') || die "bad usage"; @ARGV = @INC unless @ARGV; # Globals. wish I didn't really have to do this. use vars ( q!$Start_Dir!, # The top directory find was called with q!%Future!, # topdirs find will handle later ); my $Module; if ($opt_s) { if (open(ME, "-|")) { $/ = ''; while () { chomp; print join("\n", sort split /\n/), "\n"; } exit; } } MAIN: { my %visited; my ($dev,$ino); @Future{@ARGV} = (1) x @ARGV; foreach $Start_Dir (@ARGV) { delete $Future{$Start_Dir}; print "\n<>\n\n" if $opt_v; next unless ($dev,$ino) = stat($Start_Dir); next if $visited{$dev,$ino}++; next unless $opt_a || $Start_Dir =~ m!^/!; find(\&wanted, $Start_Dir); } exit; } sub modname { local $_ = $File::Find::name; if (index($_, $Start_Dir . '/') == 0) { substr($_, 0, 1+length($Start_Dir)) = ''; } s { / } {::}gx; s { \.p(m|od)$ } {}x; return $_; } sub wanted { if ( $Future{$File::Find::name} ) { warn "\t(Skipping $File::Find::name, qui venit in futuro.)\n" if 0 and $opt_v; $File::Find::prune = 1; return; } return unless /\.pm$/ && -f; $Module = &modname; my $file = $_; unless (open(POD, "< $file")) { warn "\tcannot open $file: $!"; # if $opt_w; return 0; } $: = " -:"; local $/ = ''; local $_; while () { if (/=head\d\s+NAME/) { chomp($_ = ); s/^.*?-\s+//s; s/\n/ /g; #write; my $v; if (defined ($v = getversion($Module))) { print "$Module ($v) "; } else { print "$Module "; } print "- $_\n"; return 1; } } warn "\t(MISSING DESC FOR $File::Find::name)\n" if $opt_w; return 0; } sub getversion { my $mod = shift; my $vers = `$^X -m$mod -e 'print \$${mod}::VERSION' 2>&1`; #my $vers = `$^X -m$mod -e 'print \$${mod}::VERSION' 2>/dev/null`; # 2> due to errors from MM_Unix etc $vers =~ s/^\s*(.*?)\s*$/$1/; # why is there whitespace here?? return ($vers || undef); } sub getversion_internal { # This should really use system(), because otherwise we bloat. my $mod = shift; local $SIG{__WARN__} = sub {}; eval "require $mod"; if ($@) { warn "Cannot require $mod -- $@\n" if $opt_v; return; } my $vers; { no strict 'refs'; return unless defined ($vers = ${ $mod . "::VERSION" }); } $vers =~ s/^\s*(.*?)\s*$/$1/; # why is there whitespace here?? return $vers; } format = ^<<<<<<<<<<<<<<<<<~~^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Module, $_ .