--- a/bc_tools/la_filter.pl Wed Apr 14 12:58:22 2010 +0100
+++ b/bc_tools/la_filter.pl Fri Apr 16 12:56:17 2010 +0100
@@ -14,15 +14,15 @@
# This is a tool for filtering static BC libraries reports.
use strict;
+use Getopt::Long;
use XML::Simple;
-use File::Copy;
use Tie::File;
-use Data::Dumper;
my $report;
my $xref_file;
my $destfile;
my $missing_destfile;
+my $pkg_destfile;
my @lines;
my $line;
my $n;
@@ -33,27 +33,57 @@
my $gen_missing_report = 1; # This variable determines whether to produce report for missing libraries.
my $issues_num;
my $issue_name;
-my $xref_name;
-my $xref_type;
-my $xref_line;
-my $xref_hdr;
-my $xref_def;
+my ($xref_name, $xref_type, $xref_line, $xref_hdr, $xref_def);
my $delete_node;
my @non_public_list;
my $current_item;
my $check_against_xref;
my $temp_lib_num;
my $temp_counter;
+my $sub_reports = 1; # This variable determines whether to generate sub-reports per package.
+my @lines_to_ignore = ("\\\\build\\\\", "\\\\compsupp\\\\", "\\\\uc_dll."); # This is the list of key words based on which a line potentially containing a package name will be ignored (skipped).
+my @pkgs;
+my $baselinedlldir;
+my $lib_name;
+my $map_name;
+my $map_found;
+my ($layer_name, $package_name);
+my $pkg_found;
+my $pkgs_num;
+my $add_pkg;
+my $nomap;
+my $help;
-if ($ARGV[1]) {
- $report = $ARGV[0];
- $xref_file = $ARGV[1];
- $destfile = "filtered_" . $report;
- $missing_destfile = "missing_" . $report;
-} else {
- die "Missing parameter(s). For example: la_filter.pl libraries_report.xml my_xref_file.txt";
+sub usage($);
+sub help();
+sub usage_error();
+
+my %optmap = ( 'libraries-report' => \$report,
+ 'xref-file' => \$xref_file,
+ 'baseline-dll-dir' => \$baselinedlldir,
+ 'help' => \$help);
+
+GetOptions(\%optmap,
+ 'libraries-report=s',
+ 'xref-file=s',
+ 'baseline-dll-dir=s',
+ 'help!')
+ or usage_error();
+
+if ($help) {
+ help();
}
+# --libraries-report is mandatory.
+usage_error(), unless (defined($report));
+
+# --xref-file is mandatory.
+usage_error(), unless (defined($xref_file));
+
+# Define output files based on the libraries report name.
+$destfile = "filtered_" . $report;
+$missing_destfile = "missing_" . $report;
+
# Parse the input XMLs into hashrefs.
print "Parsing " . $report . "... ";
my $current_report = XMLin("./$report", keeproot => 1,
@@ -198,6 +228,9 @@
print OUT XMLout($current_report, keeproot => 1);
close OUT;
+# Free up memory resources.
+$current_report = ();
+
# Insert: <?xml version="1.0" encoding="ASCII" standalone="no" ?>
# <?xml-stylesheet type="text/xsl" href="BBCResults.xsl"?>
tie @lines, 'Tie::File', $destfile or die ("Cannot tie file \"$destfile\". $!\n");
@@ -255,4 +288,204 @@
unshift @lines, "<?xml-stylesheet type=\"text/xsl\" href=\"BBCResults.xsl\"?>";
unshift @lines, "<?xml version=\"1.0\" encoding=\"ASCII\" standalone=\"no\" ?>";
untie @lines;
-}
\ No newline at end of file
+}
+
+if (($sub_reports) && ($gen_missing_report)) { # Generate sub-reports per package.
+ # Parse the input XMLs into hashrefs again.
+ print "Parsing " . $missing_destfile . "... ";
+ my $current_report = XMLin("./$missing_destfile", keeproot => 1,
+ forcearray => [ 'header', 'baselineversion', 'currentversion', 'timestamp', 'day', 'month', 'year', 'hour', 'minute', 'second', #
+ 'laversion', 'formatversion', 'cmdlineparms', 'parm', 'pname', 'pvalue', 'knownissuesversion', 'os', 'version', 'buildweek', 'issuelist',#
+ 'library', 'name', 'comparefilename', 'shortname', 'baseplatform', 'currentplatform', 'issue', 'typeinfo', 'typeid', 'funcname', 'newfuncname', 'newfuncpos', #
+ 'bc_severity', 'sc_severity', 'status', 'funcpos' ], keyattr => [] );
+ print "complete \n";
+ $lib_num = @{$current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}};
+ if (!defined($baselinedlldir)) { # Define baselinedlldir.
+ $n = 0;
+ foreach (@{$current_report->{'bbcresults'}->{'header'}->[0]->{'cmdlineparms'}->[0]->{'parm'}}) { # Find baselinedlldir.
+ if ($current_report->{'bbcresults'}->{'header'}->[0]->{'cmdlineparms'}->[0]->{'parm'}->[$n]->{'pname'}->[0] eq "baselinedlldir") {
+ $baselinedlldir = $current_report->{'bbcresults'}->{'header'}->[0]->{'cmdlineparms'}->[0]->{'parm'}->[$n]->{'pvalue'}->[0];
+ last;
+ }
+ $n++;
+ }
+ }
+ print "baselinedlldir: $baselinedlldir\n";
+ # Create the list of packages that link to missing libraries and generate sub-report for no-map file libraries.
+ $nomap = 0;
+ $n = 0;
+ while ($n < $lib_num) {
+ $lib_name = $current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}->[$n]->{'shortname'}->[0];
+ $map_name = $baselinedlldir . "\\" . $lib_name . ".map";
+ $map_found = 1;
+ # Find and open corresponding map file (.map or .dll.map).
+ open (FILE, "<$map_name") or $map_name = $baselinedlldir . "\\" . $lib_name . ".dll.map" and open (FILE, "<$map_name") or print "No map file found for $lib_name\n" and $map_found = 0;
+ if ($map_found) {
+# print "Found: $map_name for $lib_name\n";
+ $pkg_found = 0;
+ while ($line = <FILE>)
+ {
+ chomp $line;
+ # Get rid of spaces at the beginning.
+ $line =~ s/^\s+//;
+ if ($line =~ m/\\sf\\/) {
+ $pkg_found = 1; # Package potentially found.
+ # Check against lines_to_ignore.
+ foreach $current_item (@lines_to_ignore) {
+ if ($line =~ m/($current_item)/) { # Skip the line.
+ $pkg_found = 0; # Change it back to not found.
+ last;
+ }
+ }
+ }
+ if ($pkg_found) {
+ # Get rid of \sf\ and the part it follows.
+ $line =~ s/^.*\\sf\\//;
+ # Get only the package name (in between \ and \).
+ ($layer_name, $package_name) = split /\\/,$line;
+ print "Package: $package_name found for: $lib_name (based on $map_name)\n";
+ $pkgs_num = @pkgs;
+ if ($pkgs_num == 0) { # Add the first package name by default.
+ push @pkgs, $package_name;
+ } else {
+ $add_pkg = 1;
+ $m = 0;
+ while ($m < $pkgs_num) {
+ if ($package_name eq @pkgs[$m]) { # Do not add a new package name.
+ $add_pkg = 0;
+ }
+ $m++;
+ }
+ if ($add_pkg) { # Add the new package name.
+ push @pkgs, $package_name;
+ }
+ }
+ last;
+ }
+ }
+ close FILE;
+ # Delete the node (to generate sub-report for libraries with no map file.
+ splice(@{$current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}},$n, 1);
+ $lib_num--;
+ } else {
+ $nomap++;
+ $n++;
+ }
+ }
+ print "Number of libraries with no map file (most likely not a part of Public API): " . $nomap . "\n";
+ if ($nomap > 0) { # Save sub-report for no-map file libraries.
+ # Write new XML to dest file.
+ $pkg_destfile = "missing_with_no_map_file_" . $report;
+ open OUT,">$pkg_destfile" or die("Cannot open file \"$pkg_destfile\" for writing. $!\n");
+ print OUT XMLout($current_report, keeproot => 1);
+ close OUT;
+ # Insert: <?xml version="1.0" encoding="ASCII" standalone="no" ?>
+ # <?xml-stylesheet type="text/xsl" href="BBCResults.xsl"?>
+ tie @lines, 'Tie::File', $pkg_destfile or die ("Cannot tie file \"$pkg_destfile\". $!\n");
+ unshift @lines, "<?xml-stylesheet type=\"text/xsl\" href=\"BBCResults.xsl\"?>";
+ unshift @lines, "<?xml version=\"1.0\" encoding=\"ASCII\" standalone=\"no\" ?>";
+ untie @lines;
+ }
+ print "Number of packages: " . @pkgs . "\n";
+ # Generate sub reports for all packages.
+ foreach $current_item (@pkgs) {
+ # Parse the input XMLs into hashrefs again.
+ print "Parsing " . $missing_destfile . "... ";
+ my $current_report = XMLin("./$missing_destfile", keeproot => 1,
+ forcearray => [ 'header', 'baselineversion', 'currentversion', 'timestamp', 'day', 'month', 'year', 'hour', 'minute', 'second', #
+ 'laversion', 'formatversion', 'cmdlineparms', 'parm', 'pname', 'pvalue', 'knownissuesversion', 'os', 'version', 'buildweek', 'issuelist',#
+ 'library', 'name', 'comparefilename', 'shortname', 'baseplatform', 'currentplatform', 'issue', 'typeinfo', 'typeid', 'funcname', 'newfuncname', 'newfuncpos', #
+ 'bc_severity', 'sc_severity', 'status', 'funcpos' ], keyattr => [] );
+ print "complete \n";
+ $lib_num = @{$current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}};
+ $n = 0;
+ print "Processing libraries for $current_item... ";
+ while ($n < $lib_num) {
+ $lib_name = $current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}->[$n]->{'shortname'}->[0];
+ $map_name = $baselinedlldir . "\\" . $lib_name . ".map";
+ $map_found = 1;
+ # Find and open corresponding map file (.map or .dll.map).
+ open (FILE, "<$map_name") or $map_name = $baselinedlldir . "\\" . $lib_name . ".dll.map" and open (FILE, "<$map_name") or $map_found = 0;
+ if ($map_found) {
+ $pkg_found = 0;
+ while ($line = <FILE>)
+ {
+ chomp $line;
+ # Get rid of spaces at the beginning.
+ $line =~ s/^\s+//;
+ if ($line =~ m/\\sf\\/) {
+ $pkg_found = 1; # Package potentially found.
+ # Check against lines_to_ignore.
+ foreach $current_item (@lines_to_ignore) {
+ if ($line =~ m/($current_item)/) { # Skip the line.
+ $pkg_found = 0; # Change it back to not found.
+ last;
+ }
+ }
+ }
+ if ($pkg_found) {
+ # Get rid of \sf\ and the part it follows.
+ $line =~ s/^.*\\sf\\//;
+ # Get only the package name (in between \ and \).
+ ($layer_name, $package_name) = split /\\/,$line;
+ last;
+ }
+ }
+ close FILE;
+ if ($package_name ne $current_item) { # Remove the node from the report for the current package.
+ splice(@{$current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}},$n, 1);
+ $lib_num--;
+ } else {
+ $n++;
+ }
+ } else { # Delete the node (library with no-map file).
+ splice(@{$current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}},$n, 1);
+ $lib_num--;
+ }
+ }
+ # Write new XML to dest file.
+ $pkg_destfile = $current_item . "_" . $missing_destfile;
+ open OUT,">$pkg_destfile" or die("Cannot open file \"$pkg_destfile\" for writing. $!\n");
+ print OUT XMLout($current_report, keeproot => 1);
+ close OUT;
+ # Insert: <?xml version="1.0" encoding="ASCII" standalone="no" ?>
+ # <?xml-stylesheet type="text/xsl" href="BBCResults.xsl"?>
+ tie @lines, 'Tie::File', $pkg_destfile or die ("Cannot tie file \"$pkg_destfile\". $!\n");
+ unshift @lines, "<?xml-stylesheet type=\"text/xsl\" href=\"BBCResults.xsl\"?>";
+ unshift @lines, "<?xml version=\"1.0\" encoding=\"ASCII\" standalone=\"no\" ?>";
+ untie @lines;
+ print "complete \n";
+ $lib_num = @{$current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}};
+ print "Number of missing libraries in $current_item package: $lib_num\n";
+ }
+}
+
+exit 0;
+
+sub usage($)
+{
+ my $error = shift;
+ my $fh = $error == 0 ? *STDOUT : *STDERR;
+ print $fh "la_filter.pl\n" .
+ "Specify the libraries report and xref file\n" .
+ "synopsis:\n" .
+ " la_filter.pl --help\n" .
+ " la_filter.pl [--libraries-report=XML_FILE] [--xref-file=TXT_FILE] [--baseline-dll-dir=PATH] \n" .
+ "options:\n" .
+ " --help Display this help and exit.\n" .
+ " --libraries-report=XML_FILE XML_FILE is the name of the libraries report xml file.\n" .
+ " --xref-file=TXT_FILE TXT_FILE is the file containing the index of source code definitions generated by Ctags.\n" .
+ " --baseline-dll-dir=PATH PATH is the full path to the directory containing map files (e.g. \\epoc32\\release\\armv5\\urel).\n" .
+ " If not specified then the baselinedlldir param from the libraries report will be used.\n";
+ exit $error;
+}
+
+sub help()
+{
+ usage(0);
+}
+
+sub usage_error()
+{
+ usage(1);
+}