# HG changeset patch # User Maciej Seroka # Date 1271418977 -3600 # Node ID e662a2267ea55979d40332f530511a5a43bad3b7 # Parent d57b367400c0a9d345f1af7a464b47307c9712c8 Implemented feature to generate sub-reports for missing libraries in la_filter.pl diff -r d57b367400c0 -r e662a2267ea5 bc_tools/la_filter.pl --- 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: # tie @lines, 'Tie::File', $destfile or die ("Cannot tie file \"$destfile\". $!\n"); @@ -255,4 +288,204 @@ unshift @lines, ""; unshift @lines, ""; 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 = ) + { + 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: + # + tie @lines, 'Tie::File', $pkg_destfile or die ("Cannot tie file \"$pkg_destfile\". $!\n"); + unshift @lines, ""; + unshift @lines, ""; + 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 = ) + { + 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: + # + tie @lines, 'Tie::File', $pkg_destfile or die ("Cannot tie file \"$pkg_destfile\". $!\n"); + unshift @lines, ""; + unshift @lines, ""; + 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); +}