12 # |
12 # |
13 # Description: |
13 # Description: |
14 # This is a tool for filtering static BC libraries reports. |
14 # This is a tool for filtering static BC libraries reports. |
15 |
15 |
16 use strict; |
16 use strict; |
|
17 use Getopt::Long; |
17 use XML::Simple; |
18 use XML::Simple; |
18 use File::Copy; |
|
19 use Tie::File; |
19 use Tie::File; |
20 use Data::Dumper; |
|
21 |
20 |
22 my $report; |
21 my $report; |
23 my $xref_file; |
22 my $xref_file; |
24 my $destfile; |
23 my $destfile; |
25 my $missing_destfile; |
24 my $missing_destfile; |
|
25 my $pkg_destfile; |
26 my @lines; |
26 my @lines; |
27 my $line; |
27 my $line; |
28 my $n; |
28 my $n; |
29 my $m; |
29 my $m; |
30 my $counter; |
30 my $counter; |
31 my $short_name; |
31 my $short_name; |
32 my $del_ok_issues = 1; # This variable determines whether to delete OK issues first. |
32 my $del_ok_issues = 1; # This variable determines whether to delete OK issues first. |
33 my $gen_missing_report = 1; # This variable determines whether to produce report for missing libraries. |
33 my $gen_missing_report = 1; # This variable determines whether to produce report for missing libraries. |
34 my $issues_num; |
34 my $issues_num; |
35 my $issue_name; |
35 my $issue_name; |
36 my $xref_name; |
36 my ($xref_name, $xref_type, $xref_line, $xref_hdr, $xref_def); |
37 my $xref_type; |
|
38 my $xref_line; |
|
39 my $xref_hdr; |
|
40 my $xref_def; |
|
41 my $delete_node; |
37 my $delete_node; |
42 my @non_public_list; |
38 my @non_public_list; |
43 my $current_item; |
39 my $current_item; |
44 my $check_against_xref; |
40 my $check_against_xref; |
45 my $temp_lib_num; |
41 my $temp_lib_num; |
46 my $temp_counter; |
42 my $temp_counter; |
47 |
43 my $sub_reports = 1; # This variable determines whether to generate sub-reports per package. |
48 if ($ARGV[1]) { |
44 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). |
49 $report = $ARGV[0]; |
45 my @pkgs; |
50 $xref_file = $ARGV[1]; |
46 my $baselinedlldir; |
51 $destfile = "filtered_" . $report; |
47 my $lib_name; |
52 $missing_destfile = "missing_" . $report; |
48 my $map_name; |
53 } else { |
49 my $map_found; |
54 die "Missing parameter(s). For example: la_filter.pl libraries_report.xml my_xref_file.txt"; |
50 my ($layer_name, $package_name); |
55 } |
51 my $pkg_found; |
|
52 my $pkgs_num; |
|
53 my $add_pkg; |
|
54 my $nomap; |
|
55 my $help; |
|
56 |
|
57 sub usage($); |
|
58 sub help(); |
|
59 sub usage_error(); |
|
60 |
|
61 my %optmap = ( 'libraries-report' => \$report, |
|
62 'xref-file' => \$xref_file, |
|
63 'baseline-dll-dir' => \$baselinedlldir, |
|
64 'help' => \$help); |
|
65 |
|
66 GetOptions(\%optmap, |
|
67 'libraries-report=s', |
|
68 'xref-file=s', |
|
69 'baseline-dll-dir=s', |
|
70 'help!') |
|
71 or usage_error(); |
|
72 |
|
73 if ($help) { |
|
74 help(); |
|
75 } |
|
76 |
|
77 # --libraries-report is mandatory. |
|
78 usage_error(), unless (defined($report)); |
|
79 |
|
80 # --xref-file is mandatory. |
|
81 usage_error(), unless (defined($xref_file)); |
|
82 |
|
83 # Define output files based on the libraries report name. |
|
84 $destfile = "filtered_" . $report; |
|
85 $missing_destfile = "missing_" . $report; |
56 |
86 |
57 # Parse the input XMLs into hashrefs. |
87 # Parse the input XMLs into hashrefs. |
58 print "Parsing " . $report . "... "; |
88 print "Parsing " . $report . "... "; |
59 my $current_report = XMLin("./$report", keeproot => 1, |
89 my $current_report = XMLin("./$report", keeproot => 1, |
60 forcearray => [ 'header', 'baselineversion', 'currentversion', 'timestamp', 'day', 'month', 'year', 'hour', 'minute', 'second', # |
90 forcearray => [ 'header', 'baselineversion', 'currentversion', 'timestamp', 'day', 'month', 'year', 'hour', 'minute', 'second', # |
254 tie @lines, 'Tie::File', $missing_destfile or die ("Cannot tie file \"$missing_destfile\". $!\n"); |
287 tie @lines, 'Tie::File', $missing_destfile or die ("Cannot tie file \"$missing_destfile\". $!\n"); |
255 unshift @lines, "<?xml-stylesheet type=\"text/xsl\" href=\"BBCResults.xsl\"?>"; |
288 unshift @lines, "<?xml-stylesheet type=\"text/xsl\" href=\"BBCResults.xsl\"?>"; |
256 unshift @lines, "<?xml version=\"1.0\" encoding=\"ASCII\" standalone=\"no\" ?>"; |
289 unshift @lines, "<?xml version=\"1.0\" encoding=\"ASCII\" standalone=\"no\" ?>"; |
257 untie @lines; |
290 untie @lines; |
258 } |
291 } |
|
292 |
|
293 if (($sub_reports) && ($gen_missing_report)) { # Generate sub-reports per package. |
|
294 # Parse the input XMLs into hashrefs again. |
|
295 print "Parsing " . $missing_destfile . "... "; |
|
296 my $current_report = XMLin("./$missing_destfile", keeproot => 1, |
|
297 forcearray => [ 'header', 'baselineversion', 'currentversion', 'timestamp', 'day', 'month', 'year', 'hour', 'minute', 'second', # |
|
298 'laversion', 'formatversion', 'cmdlineparms', 'parm', 'pname', 'pvalue', 'knownissuesversion', 'os', 'version', 'buildweek', 'issuelist',# |
|
299 'library', 'name', 'comparefilename', 'shortname', 'baseplatform', 'currentplatform', 'issue', 'typeinfo', 'typeid', 'funcname', 'newfuncname', 'newfuncpos', # |
|
300 'bc_severity', 'sc_severity', 'status', 'funcpos' ], keyattr => [] ); |
|
301 print "complete \n"; |
|
302 $lib_num = @{$current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}}; |
|
303 if (!defined($baselinedlldir)) { # Define baselinedlldir. |
|
304 $n = 0; |
|
305 foreach (@{$current_report->{'bbcresults'}->{'header'}->[0]->{'cmdlineparms'}->[0]->{'parm'}}) { # Find baselinedlldir. |
|
306 if ($current_report->{'bbcresults'}->{'header'}->[0]->{'cmdlineparms'}->[0]->{'parm'}->[$n]->{'pname'}->[0] eq "baselinedlldir") { |
|
307 $baselinedlldir = $current_report->{'bbcresults'}->{'header'}->[0]->{'cmdlineparms'}->[0]->{'parm'}->[$n]->{'pvalue'}->[0]; |
|
308 last; |
|
309 } |
|
310 $n++; |
|
311 } |
|
312 } |
|
313 print "baselinedlldir: $baselinedlldir\n"; |
|
314 # Create the list of packages that link to missing libraries and generate sub-report for no-map file libraries. |
|
315 $nomap = 0; |
|
316 $n = 0; |
|
317 while ($n < $lib_num) { |
|
318 $lib_name = $current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}->[$n]->{'shortname'}->[0]; |
|
319 $map_name = $baselinedlldir . "\\" . $lib_name . ".map"; |
|
320 $map_found = 1; |
|
321 # Find and open corresponding map file (.map or .dll.map). |
|
322 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; |
|
323 if ($map_found) { |
|
324 # print "Found: $map_name for $lib_name\n"; |
|
325 $pkg_found = 0; |
|
326 while ($line = <FILE>) |
|
327 { |
|
328 chomp $line; |
|
329 # Get rid of spaces at the beginning. |
|
330 $line =~ s/^\s+//; |
|
331 if ($line =~ m/\\sf\\/) { |
|
332 $pkg_found = 1; # Package potentially found. |
|
333 # Check against lines_to_ignore. |
|
334 foreach $current_item (@lines_to_ignore) { |
|
335 if ($line =~ m/($current_item)/) { # Skip the line. |
|
336 $pkg_found = 0; # Change it back to not found. |
|
337 last; |
|
338 } |
|
339 } |
|
340 } |
|
341 if ($pkg_found) { |
|
342 # Get rid of \sf\ and the part it follows. |
|
343 $line =~ s/^.*\\sf\\//; |
|
344 # Get only the package name (in between \ and \). |
|
345 ($layer_name, $package_name) = split /\\/,$line; |
|
346 print "Package: $package_name found for: $lib_name (based on $map_name)\n"; |
|
347 $pkgs_num = @pkgs; |
|
348 if ($pkgs_num == 0) { # Add the first package name by default. |
|
349 push @pkgs, $package_name; |
|
350 } else { |
|
351 $add_pkg = 1; |
|
352 $m = 0; |
|
353 while ($m < $pkgs_num) { |
|
354 if ($package_name eq @pkgs[$m]) { # Do not add a new package name. |
|
355 $add_pkg = 0; |
|
356 } |
|
357 $m++; |
|
358 } |
|
359 if ($add_pkg) { # Add the new package name. |
|
360 push @pkgs, $package_name; |
|
361 } |
|
362 } |
|
363 last; |
|
364 } |
|
365 } |
|
366 close FILE; |
|
367 # Delete the node (to generate sub-report for libraries with no map file. |
|
368 splice(@{$current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}},$n, 1); |
|
369 $lib_num--; |
|
370 } else { |
|
371 $nomap++; |
|
372 $n++; |
|
373 } |
|
374 } |
|
375 print "Number of libraries with no map file (most likely not a part of Public API): " . $nomap . "\n"; |
|
376 if ($nomap > 0) { # Save sub-report for no-map file libraries. |
|
377 # Write new XML to dest file. |
|
378 $pkg_destfile = "missing_with_no_map_file_" . $report; |
|
379 open OUT,">$pkg_destfile" or die("Cannot open file \"$pkg_destfile\" for writing. $!\n"); |
|
380 print OUT XMLout($current_report, keeproot => 1); |
|
381 close OUT; |
|
382 # Insert: <?xml version="1.0" encoding="ASCII" standalone="no" ?> |
|
383 # <?xml-stylesheet type="text/xsl" href="BBCResults.xsl"?> |
|
384 tie @lines, 'Tie::File', $pkg_destfile or die ("Cannot tie file \"$pkg_destfile\". $!\n"); |
|
385 unshift @lines, "<?xml-stylesheet type=\"text/xsl\" href=\"BBCResults.xsl\"?>"; |
|
386 unshift @lines, "<?xml version=\"1.0\" encoding=\"ASCII\" standalone=\"no\" ?>"; |
|
387 untie @lines; |
|
388 } |
|
389 print "Number of packages: " . @pkgs . "\n"; |
|
390 # Generate sub reports for all packages. |
|
391 foreach $current_item (@pkgs) { |
|
392 # Parse the input XMLs into hashrefs again. |
|
393 print "Parsing " . $missing_destfile . "... "; |
|
394 my $current_report = XMLin("./$missing_destfile", keeproot => 1, |
|
395 forcearray => [ 'header', 'baselineversion', 'currentversion', 'timestamp', 'day', 'month', 'year', 'hour', 'minute', 'second', # |
|
396 'laversion', 'formatversion', 'cmdlineparms', 'parm', 'pname', 'pvalue', 'knownissuesversion', 'os', 'version', 'buildweek', 'issuelist',# |
|
397 'library', 'name', 'comparefilename', 'shortname', 'baseplatform', 'currentplatform', 'issue', 'typeinfo', 'typeid', 'funcname', 'newfuncname', 'newfuncpos', # |
|
398 'bc_severity', 'sc_severity', 'status', 'funcpos' ], keyattr => [] ); |
|
399 print "complete \n"; |
|
400 $lib_num = @{$current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}}; |
|
401 $n = 0; |
|
402 print "Processing libraries for $current_item... "; |
|
403 while ($n < $lib_num) { |
|
404 $lib_name = $current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}->[$n]->{'shortname'}->[0]; |
|
405 $map_name = $baselinedlldir . "\\" . $lib_name . ".map"; |
|
406 $map_found = 1; |
|
407 # Find and open corresponding map file (.map or .dll.map). |
|
408 open (FILE, "<$map_name") or $map_name = $baselinedlldir . "\\" . $lib_name . ".dll.map" and open (FILE, "<$map_name") or $map_found = 0; |
|
409 if ($map_found) { |
|
410 $pkg_found = 0; |
|
411 while ($line = <FILE>) |
|
412 { |
|
413 chomp $line; |
|
414 # Get rid of spaces at the beginning. |
|
415 $line =~ s/^\s+//; |
|
416 if ($line =~ m/\\sf\\/) { |
|
417 $pkg_found = 1; # Package potentially found. |
|
418 # Check against lines_to_ignore. |
|
419 foreach $current_item (@lines_to_ignore) { |
|
420 if ($line =~ m/($current_item)/) { # Skip the line. |
|
421 $pkg_found = 0; # Change it back to not found. |
|
422 last; |
|
423 } |
|
424 } |
|
425 } |
|
426 if ($pkg_found) { |
|
427 # Get rid of \sf\ and the part it follows. |
|
428 $line =~ s/^.*\\sf\\//; |
|
429 # Get only the package name (in between \ and \). |
|
430 ($layer_name, $package_name) = split /\\/,$line; |
|
431 last; |
|
432 } |
|
433 } |
|
434 close FILE; |
|
435 if ($package_name ne $current_item) { # Remove the node from the report for the current package. |
|
436 splice(@{$current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}},$n, 1); |
|
437 $lib_num--; |
|
438 } else { |
|
439 $n++; |
|
440 } |
|
441 } else { # Delete the node (library with no-map file). |
|
442 splice(@{$current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}},$n, 1); |
|
443 $lib_num--; |
|
444 } |
|
445 } |
|
446 # Write new XML to dest file. |
|
447 $pkg_destfile = $current_item . "_" . $missing_destfile; |
|
448 open OUT,">$pkg_destfile" or die("Cannot open file \"$pkg_destfile\" for writing. $!\n"); |
|
449 print OUT XMLout($current_report, keeproot => 1); |
|
450 close OUT; |
|
451 # Insert: <?xml version="1.0" encoding="ASCII" standalone="no" ?> |
|
452 # <?xml-stylesheet type="text/xsl" href="BBCResults.xsl"?> |
|
453 tie @lines, 'Tie::File', $pkg_destfile or die ("Cannot tie file \"$pkg_destfile\". $!\n"); |
|
454 unshift @lines, "<?xml-stylesheet type=\"text/xsl\" href=\"BBCResults.xsl\"?>"; |
|
455 unshift @lines, "<?xml version=\"1.0\" encoding=\"ASCII\" standalone=\"no\" ?>"; |
|
456 untie @lines; |
|
457 print "complete \n"; |
|
458 $lib_num = @{$current_report->{'bbcresults'}->{'issuelist'}->[0]->{'library'}}; |
|
459 print "Number of missing libraries in $current_item package: $lib_num\n"; |
|
460 } |
|
461 } |
|
462 |
|
463 exit 0; |
|
464 |
|
465 sub usage($) |
|
466 { |
|
467 my $error = shift; |
|
468 my $fh = $error == 0 ? *STDOUT : *STDERR; |
|
469 print $fh "la_filter.pl\n" . |
|
470 "Specify the libraries report and xref file\n" . |
|
471 "synopsis:\n" . |
|
472 " la_filter.pl --help\n" . |
|
473 " la_filter.pl [--libraries-report=XML_FILE] [--xref-file=TXT_FILE] [--baseline-dll-dir=PATH] \n" . |
|
474 "options:\n" . |
|
475 " --help Display this help and exit.\n" . |
|
476 " --libraries-report=XML_FILE XML_FILE is the name of the libraries report xml file.\n" . |
|
477 " --xref-file=TXT_FILE TXT_FILE is the file containing the index of source code definitions generated by Ctags.\n" . |
|
478 " --baseline-dll-dir=PATH PATH is the full path to the directory containing map files (e.g. \\epoc32\\release\\armv5\\urel).\n" . |
|
479 " If not specified then the baselinedlldir param from the libraries report will be used.\n"; |
|
480 exit $error; |
|
481 } |
|
482 |
|
483 sub help() |
|
484 { |
|
485 usage(0); |
|
486 } |
|
487 |
|
488 sub usage_error() |
|
489 { |
|
490 usage(1); |
|
491 } |