# Synopsis: generate a list of highest metrics for files. (C/C++) # # Requires one existing Understand for C++ databases # # Categories: Project Report # # Languages: C # # Usage: sub usage($) { return << "END_USAGE"; ${ \( shift @_ ) } Usage: c_highestmetrics_files.pl -db database -root_path path -maxcount maxcount -min_line line -min_linecode linecode -min_classes classes -output_file file -db database Specify Understand database (required for uperl, inherited from Understand) -root_path path Specify a path for files to into account () -maxcount maxcount Specify the max number of functions per categories (default=10) -min_line linecode Specify the min number of lines (default=750) -min_linecode line Specify the min number of lines of code (default=1000) -min_classes classes Specify the min number of declared classes (default=20) -output_file file Specify the name of the output file END_USAGE } # For the latest Understand perl API documentation, see # http://www.scitools.com/perl.html # use Understand; use Tie::RefHash; use Getopt::Long; use strict; my $dbPath; my $help; my $maxcount = 10; my $root_path = ""; my $countLine_Threshold = 1000; my $countLineCode_Threshold = 750; my $countDeclClass_Threshold = 20; my $output_file = ""; # if option is not found in the command line, corresponding variable is not changed, and use the initialized value. GetOptions( "db=s" => \$dbPath, "maxcount=s" => \$maxcount, "root_path=s" => \$root_path, "min_line=s" => \$countLine_Threshold, "min_linecode=s" => \$countLineCode_Threshold, "min_classes=s" => \$countDeclClass_Threshold, "output_file=s" => \$output_file, "help" => \$help, ); # open the database my $db=openDatabase($dbPath); my $title = "Files"; my $kindFiles = "File"; my $kindCodeFiles = "Code File"; my $kindHeaderFiles = "Header File"; my $fh; my $writeInFile = 0; prepareOutput(); display("-------------------------------------------------------\n"); display("Highest metrics for files\n\n"); display("Database : ".$dbPath."\n"); display("maxcount : ".$maxcount."\n"); display("root_path : ".$root_path."\n"); display("min_line : ".$countLine_Threshold."\n"); display("min_linecode : ".$countLineCode_Threshold."\n"); display("min_classes : ".$countDeclClass_Threshold."\n"); display("output_file : ".$output_file."\n"); display("\n"); generateHighestMetrics($db, $title, $kindFiles, lc $root_path, "CountLine", $countLine_Threshold, $maxcount); generateHighestMetrics($db, $title, $kindCodeFiles, lc $root_path, "CountLineCode", $countLineCode_Threshold, $maxcount); generateHighestMetrics($db, $title, $kindHeaderFiles, lc $root_path, "CountDeclClass", $countDeclClass_Threshold, $maxcount); display("-------------------------------------------------------\n"); closeDatabase($db); closeOutput(); # ------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------ # subroutines # ------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------ sub openDatabase($) { my ($dbPath) = @_; my $db = Understand::Gui::db(); # path not allowed if opened by understand if ($db && $dbPath) { die "database already opened by GUI, don't use -db option\n"; } # open database if not already open if (!$db) { my $status; die usage("Error, database not specified\n\n") unless ($dbPath); ($db,$status)=Understand::open($dbPath); die "Error opening database: ",$status,"\n" if $status; } return($db); } sub closeDatabase($) { my ($db)=@_; # close database only if we opened it $db->close() if ($dbPath); } # ------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------ sub prepareOutput { if($output_file eq "") { $writeInFile = 0; } else { if(open($fh, '>', $output_file)) { $writeInFile = 1; } } } # ------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------ sub closeOutput { if($writeInFile) { close $fh; } } # ------------------------------------------------------------------------------------------ # Parameters # - db # - title # - kind # - threshold name # - metrics name # - max result count # ------------------------------------------------------------------------------------------ sub generateHighestMetrics { my ($db, $title, $kind, $root_path, $metrics, $threshold, $maxcount) = @_; # retrieve threshold option value $threshold = 1 if ($threshold < 1); # build hash of matching entities tie my %ents, 'Tie::RefHash'; my $ents; foreach my $file ($db->ents($kind)) { # keep file if not in excluded path and if metrics > threshold my $val = $file->metric($metrics); if ($val >= $threshold) { if(index(lc $file->longname(), $root_path) != -1) { $ents{$file} = $val; } } } printTitleMetric($title, $metrics, $threshold); # output, sorted by value, then by name my $cur = 1; foreach my $file (sort { $ents{$b} <=> $ents{$a} || lc($b->longname()) cmp lc($a->longname()); } keys %ents) { if($cur <= $maxcount) { printOneResult($file, $ents{$file}); } $cur++; } display("\n"); } # ------------------------------------------------------------------------------------------ # Parameters # - report # - title # - metrics name # - threshold # ------------------------------------------------------------------------------------------ sub printTitleMetric { my ($title, $metrics, $threshold) = @_; display("-------------------------------------------------------\n"); display($title); display(" with highest metric "); display($metrics); display(" ( > "); display($threshold); display(" ) :\n"); display("-------------------------------------------------------\n"); } # ------------------------------------------------------------------------------------------ # Parameters # - report # - entity # - metric value # ------------------------------------------------------------------------------------------ sub printOneResult { my ($entity, $value) = @_; #value in red my $str = sprintf("%5d " ,$value); display($str); # entity my $length = length($entity->longname()); $str = $entity->longname(); # if entity is not a file, print its kind if($entity->kindname() eq "File") {} else { $str .= sprintf("%*s" , 60 - $length , "("); $str .= $entity->kindname(); $str .= ")"; } display($str); display("\n"); } # ------------------------------------------------------------------------------------------ # Parameters # - text # ------------------------------------------------------------------------------------------ sub display { my ($text) = @_; if($writeInFile) { print $fh $text; } else { print $text; } }