The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!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(@_)) }