#! /usr/bin/perl -w # Takes a set of ps images (belonging to one file) and produces a # conglomerate picture of that file: static functions in the middle, # others around it. Each one gets a box about its area. use strict; my $SCRUNCH = $ARGV [0]; my $BOXSCRUNCH = $ARGV [1]; my $Tmp; my $DEBUG = 1; shift @ARGV; # skip SCRUNCH and BOXSCRUNCH shift @ARGV; DecorateFuncs (@ARGV); #TMPFILE=`mktemp ${TMPDIR:-/tmp}/$$.XXXXXX` # Arrange. my $ArgList = ""; foreach $Tmp (@ARGV) { $ArgList .= "'$Tmp' "; } my @Arranged = `../draw_arrangement $SCRUNCH 0 360 0 $ArgList`; my $CFile = $ARGV [0]; $CFile =~ s/\.c\..*$/.c/; if ($DEBUG) { print ("% Conglomeration of $CFile\n"); } print "gsave angle rotate\n"; # Now output the file, except last line. my $LastLine = pop (@Arranged); my $Fill = Box_2 ($LastLine,$CFile); print $Fill; # Draw box with file name my @Output = Box ('normal', 'Helvetica-Bold', 32, $CFile, $LastLine); splice(@Output, $#Output, 0, "grestore\n"); #print @Output; print (@Arranged); #add a duplicate box to test if this works print @Output; sub ParseBound { my $BBoxLine = shift; $BBoxLine =~ /(-?[\d.]+)\s+(-?[\d.]+)\s+(-?[\d.]+)\s+(-?[\d.]+)/; # XMin, YMin, XMax, YMax return ($1 * $BOXSCRUNCH, $2 * $BOXSCRUNCH, $3 * $BOXSCRUNCH, $4 * $BOXSCRUNCH); } # Box (type, font, fontsize, Label, BBoxLine) sub Box { my $Type = shift; my $Font = shift; my $Fontsize = shift; my $Label = shift; my $BBoxLine = shift; my @Output = (); # print (STDERR "Box ('$Type', '$Font', '$Fontsize', '$Label', '$BBoxLine')\n"); push (@Output, "% start of box\n"); push (@Output, "D5\n") if ($Type eq "dashed"); # print (STDERR "BBoxLine: '$BBoxLine'\n"); # print (STDERR "Parsed: '" . join ("' '", ParseBound ($BBoxLine)) . "\n"); my ($XMin, $YMin, $XMax, $YMax) = ParseBound ($BBoxLine); my $LeftSpaced = $XMin + 6; my $BottomSpaced = $YMin + 6; # Put black box around it push (@Output, ( "($Label) $LeftSpaced $BottomSpaced $Fontsize /$Font\n", "$YMin $XMin $YMax $XMax U\n" ) ); push (@Output, "D\n") if ($Type eq "dashed"); # fill bounding box push (@Output, "% end of box\n"); # Output bounding box push (@Output, "% bound $XMin $YMin $XMax $YMax\n"); return @Output; } sub Box_2 { my $BBoxLine = shift; my $CFile = shift; my $CovFile = "./coverage.dat"; my ($XMin, $YMin, $XMax, $YMax) = ParseBound ($BBoxLine); my @output = `fgrep $CFile $CovFile`; chomp $output[0]; my ($junk, $Class, $per) = split /\t/, $output[0]; return "$XMin $YMin $XMax $YMax $Class\n"; } # Decorate (rgb-vals(1 string) filename) sub Decorate { my $RGB = shift; my $Filename = shift; my @Input = ReadPS ($Filename); my $LastLine = pop (@Input); my @Output = (); # Color at the beginning. push (@Output, "C$RGB\n"); # Now output the file, except last line. push (@Output, @Input); # Draw dashed box with function name # FIXME Make bound cover the label as well! my $FuncName = $Filename; $FuncName =~ s/^[^.]+\.c\.(.+?)\..*$/$1/; push (@Output, Box ('dashed', 'Helvetica', 24, $FuncName, $LastLine)); # Slap over the top. WritePS ($Filename, @Output); } # Add colored boxes around functions sub DecorateFuncs { my $FName = ""; my $FType = ""; foreach $FName (@ARGV) { $FName =~ /\+([A-Z]+)\+/; $FType = $1; if ($FType eq 'STATIC') { Decorate ("2", $FName); # Light green. } elsif ($FType eq 'INDIRECT') { Decorate ("3", $FName); # Green. } elsif ($FType eq 'EXPORTED') { Decorate ("4", $FName); # Red. } elsif ($FType eq 'NORMAL') { Decorate ("5", $FName); # Blue. } else { die ("Unknown extension $FName"); } } } sub ReadPS { my $Filename = shift; my @Contents = (); open (INFILE, "$Filename") or die ("Could not read $Filename: $!"); @Contents = ; close (INFILE); return @Contents; } sub WritePS { my $Filename = shift; open (OUTFILE, ">$Filename") or die ("Could not write $Filename: $!"); print (OUTFILE @_); close (OUTFILE); }