#!/usr/bin/perl
#gprof2dot: generate a dot file from gprof call graph.
#Usage: just run binary with no params to see usage.
# tirath.ramdas@eng.monash.edu.au, 2006.
# I'm a C guy, and I'm sure it shows... this has got to be some of the
# worst perl ever written, and for that I can only apologise! :-)
#In case of slight differences between gprof flavors, tweaking
# the following may get things to work...
#Finding the start of the call graph is done by looking for these
# tokens on the start of three successive lines, immediately
# preceeding the callgraph.
@find_start_of_callgraph=("granularity:","index");
#inputs: input and output file names
$number_of_params=$#ARGV;
if($number_of_params<1){
print "Usage: gprof2dot [input file name] [output file name] {optional: \"calls\"}\n\tSpecifying the \"calls\" param labels arcs with number of calls. \n\tThe default is \"self seconds\".\n";
exit(-1);
}
$input_file = @ARGV[0];
$output_file = @ARGV[1];
#select whether to print number of calls or amt of time on graph arcs
$arc_label_selection=0;
if($number_of_params>1){
if(@ARGV[2] ne "calls"){
print "Usage: gprof2dot [input file name] [output file name] {optional: \"calls\"}\n\tSpecifying the \"calls\" param labels arcs with number of calls. \n\tThe default is \"self seconds\".\n";
exit(-1);
}
$arc_label_selection=2;
}
open(INPUT, $input_file) or die("Cannot open file '$input_file' for reading\n");
#find the start of the callgraph...
$i=0;
while($line=){
#get next line from input
chomp $line;
my @fields = split(" ",$line);
# print ">>",$line,"\n";
if($fields[0] eq $find_start_of_callgraph[$i]){
# print "Found ",$fields[0],"\n";
if($i==1){
#found the last token... found the callgraph!
last;
}
#look for the next token
$i++;
# print "Looking for ",$find_start_of_callgraph[$i],"\n";
}
}#read input looking for start $f callgraph
#Now we're at the head of the callgraph, but even here formats can
# get a bit hairy... let's explicitly look for the first "[NNN]"...
while($line=){
#get next line from input
chomp $line;
my @fields = split(" ",$line);
if($fields[0]=~ /\[(\d+)\]/g){
#found first tree head, record it then start proper callgraph
# processing
$head=$fields[-2];
$drawtree=1;
last;
}
}#read input looking for start $f callgraph
open(OUTPUT,">$output_file") or die("Cannot open file '$output_file' for writing\n");
print OUTPUT "\ndigraph untitled{\n\n\tnode [style=filled];\n\tedge [fontsize=\"9.00\"];\n";
$i=0;
while($line=){
#get next line from input
chomp $line;
my @fields = split(" ",$line);
print ">>",$line,"\n";
if($fields[0]=~ /\[(\d+)\]/g){
#found new tree head, start a new subtree...
$head=$fields[-2];
$drawtree=1;
print "match 1\n";
}
elsif($fields[0]=~ /(\d+)\.(\d+)/){
if($drawtree==1){
print "\t",$head,"->",$fields[-2],"[label=\"",$fields[$arc_label_selection],"\"]","\n";
print OUTPUT "\t",$head,"->",$fields[-2],"[label=\"",$fields[$arc_label_selection],"\"]","\n";
}
else{
print "Ignoring because beyond \"----\"\n";
}
print "match 2\n";
}
elsif($fields[0] =~ /(\-)+/g){
$drawtree=0;
print "match 3\n";
}
elsif(($fields[0] ne "")
&&($fields[0] ne "")){
print "\n\nleft callgraph.\n";
#it seems we've left the callgraph...
last;
}
}#process the callgraph
#finish up...
print OUTPUT "\n}\n";
close(OUTPUT);
close(INPUT);