#!env perl -w
use strict;
#use GraphViz;
use Getopt::Long;
GetOptions \our %Conf, qw(--verbose|v no|n leaves|l cc|c=s@ allccs|a nodes);
my $signature = qr/^([\w']*) ::/o;
my $fn;
my %funcs;
#my $g = GraphViz->new();
while (<>) {
if($_ =~ $signature) { $fn = $1; next }
#if($_ =~ $signature) { $fn = $1; $g->add_node($fn); next }
if($fn) { $funcs{$fn} .= $_ }
}
our %nodes;
for my $key (keys %funcs) {
for my $func (keys %funcs) {
next if $func eq $key;
print "$key -> $func\n" if $Conf{verbose} && $funcs{$key} =~ /\b$func\b/;
push @{ $nodes{$key} }, $func if $funcs{$key} =~ /\b$func\b/;
# $g->add_edge($key, $func) if($funcs{$key} =~ $func)
}
}
if ($Conf{leaves}) {
print "$_\n" for grep { not defined $nodes{$_} } keys %funcs;
}
if ($Conf{cc}) {
my %ccset = map { $_ => 1 } @{ $Conf{cc} };
comp_cc(\%ccset);
print "$_\n" for sort keys %ccset;
}
if ($Conf{allccs}) {
$|++ if $Conf{verbose};
my %allccs;
for my $f (keys %nodes) {
print "." if $Conf{verbose};
my %cc = ($f => 1);
print "calculating cc for $f\n";
$allccs{$f} = [ keys %{comp_cc(\%cc)} ];
}
print ::Y(\%allccs),"\n";
}
#print $g->as_png unless $Conf{no};
if ($Conf{nodes}) {
print ::Y(\%nodes), "\n";
}
sub comp_cc {
my ($ccset) = @_;
my $oldn = 0;
#::YY(\%nodes);
while ($oldn != keys %$ccset) {
$oldn = keys %$ccset;
for my $f (keys %$ccset) {
# $ccset->{$_} = 1 for @{ $nodes{$f} };
for (@{ $nodes{$f} }) {
#print "Adding $_ based on $f\n" unless $ccset->{$_};
$ccset->{$_} = 1;
}
}
}
$ccset;
}
sub ::Y { require YAML; YAML::Dump(@_) }
sub ::YY { require Carp; Carp::confess(::Y(@_)) }