diff --git a/envcov.sh b/envcov.sh index 1126939..7241472 100644 --- a/envcov.sh +++ b/envcov.sh @@ -13,7 +13,7 @@ else ARCHITECTURE=${CURRENT_ARCH} fi -LCOV_PATH="${scripts}/lcov-1.13/bin" +LCOV_PATH="${scripts}/lcov-1.14/bin" OBJ_DIR="${OBJECT_FILE_DIR_normal}/${ARCHITECTURE}" # Fix for the new LLVM-COV that requires gcov to have a -v parameter diff --git a/lcov-1.13/.version b/lcov-1.13/.version deleted file mode 100644 index 3645c8d..0000000 --- a/lcov-1.13/.version +++ /dev/null @@ -1,3 +0,0 @@ -VERSION=1.13 -RELEASE=1 -FULL=1.13 diff --git a/lcov-1.14/.version b/lcov-1.14/.version new file mode 100644 index 0000000..ad1509c --- /dev/null +++ b/lcov-1.14/.version @@ -0,0 +1,3 @@ +VERSION=1.14 +RELEASE=1 +FULL=1.14 diff --git a/lcov-1.13/COPYING b/lcov-1.14/COPYING similarity index 100% rename from lcov-1.13/COPYING rename to lcov-1.14/COPYING diff --git a/lcov-1.13/bin/copy_dates.sh b/lcov-1.14/bin/copy_dates.sh similarity index 98% rename from lcov-1.13/bin/copy_dates.sh rename to lcov-1.14/bin/copy_dates.sh index 2c2af8a..aef5f5e 100755 --- a/lcov-1.13/bin/copy_dates.sh +++ b/lcov-1.14/bin/copy_dates.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Usage: copy_dates.sh SOURCE TARGET # diff --git a/lcov-1.13/bin/gendesc b/lcov-1.14/bin/gendesc similarity index 98% rename from lcov-1.13/bin/gendesc rename to lcov-1.14/bin/gendesc index cfa467b..334ee78 100755 --- a/lcov-1.13/bin/gendesc +++ b/lcov-1.14/bin/gendesc @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # Copyright (c) International Business Machines Corp., 2002 # @@ -36,6 +36,7 @@ # use strict; +use warnings; use File::Basename; use Getopt::Long; use Cwd qw/abs_path/; @@ -43,7 +44,7 @@ use Cwd qw/abs_path/; # Constants our $tool_dir = abs_path(dirname($0)); -our $lcov_version = "LCOV version 1.13"; +our $lcov_version = "LCOV version 1.14"; our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; our $tool_name = basename($0); diff --git a/lcov-1.13/bin/genhtml b/lcov-1.14/bin/genhtml similarity index 95% rename from lcov-1.13/bin/genhtml rename to lcov-1.14/bin/genhtml index edb4866..2352300 100755 --- a/lcov-1.13/bin/genhtml +++ b/lcov-1.14/bin/genhtml @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # Copyright (c) International Business Machines Corp., 2002,2012 # @@ -65,17 +65,18 @@ # use strict; +use warnings; use File::Basename; use File::Temp qw(tempfile); use Getopt::Long; use Digest::MD5 qw(md5_base64); -use Cwd qw/abs_path/; +use Cwd qw/abs_path cwd/; # Global constants our $title = "LCOV - code coverage report"; our $tool_dir = abs_path(dirname($0)); -our $lcov_version = "LCOV version 1.13"; +our $lcov_version = "LCOV version 1.14"; our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; our $tool_name = basename($0); @@ -145,14 +146,6 @@ our $HEAD_NO_DETAIL = 1; our $HEAD_DETAIL_HIDDEN = 2; our $HEAD_DETAIL_SHOWN = 3; -# Offsets for storing branch coverage data in vectors -our $BR_BLOCK = 0; -our $BR_BRANCH = 1; -our $BR_TAKEN = 2; -our $BR_VEC_ENTRIES = 3; -our $BR_VEC_WIDTH = 32; -our $BR_VEC_MAX = vec(pack('b*', 1 x $BR_VEC_WIDTH), 0, $BR_VEC_WIDTH); - # Additional offsets used when converting branch coverage data to HTML our $BR_LEN = 3; our $BR_OPEN = 4; @@ -202,12 +195,7 @@ sub get_html_prolog($); sub get_html_epilog($); sub write_dir_page($$$$$$$$$$$$$$$$$); sub classify_rate($$$$); -sub br_taken_add($$); -sub br_taken_sub($$); -sub br_ivec_len($); -sub br_ivec_get($$); -sub br_ivec_push($$$$); -sub combine_brcount($$$); +sub combine_brcount($$$;$); sub get_br_found_and_hit($); sub warn_handler($); sub die_handler($); @@ -247,7 +235,7 @@ sub write_test_table_epilog(*); sub write_source($$$$$$$); sub write_source_prolog(*); -sub write_source_line(*$$$$$$); +sub write_source_line(*$$$$$); sub write_source_epilog(*); sub write_frameset(*$$$); @@ -300,6 +288,7 @@ our @opt_ignore_errors; # Ignore certain error classes during processing our @ignore; our $opt_config_file; # User-specified configuration file location our %opt_rc; +our $opt_missed; # List/sort lines by missed counts our $charset = "UTF-8"; # Default charset for HTML pages our @fileview_sortlist; our @fileview_sortname = ("", "-sort-l", "-sort-f", "-sort-b"); @@ -310,8 +299,7 @@ our $lcov_func_coverage = 1; our $lcov_branch_coverage = 0; our $rc_desc_html = 0; # lcovrc: genhtml_desc_html -our $cwd = `pwd`; # Current working directory -chomp($cwd); +our $cwd = cwd(); # Current working directory # @@ -387,6 +375,8 @@ if ($config || %opt_rc) "genhtml_sort" => \$sort, "genhtml_charset" => \$charset, "genhtml_desc_html" => \$rc_desc_html, + "genhtml_demangle_cpp" => \$demangle_cpp, + "genhtml_missed" => \$opt_missed, "lcov_function_coverage" => \$lcov_func_coverage, "lcov_branch_coverage" => \$lcov_branch_coverage, }); @@ -433,6 +423,7 @@ if (!GetOptions("output-directory|o=s" => \$output_directory, "config-file=s" => \$opt_config_file, "rc=s%" => \%opt_rc, "precision=i" => \$default_precision, + "missed" => \$opt_missed, )) { print(STDERR "Use $tool_name --help to get usage information\n"); @@ -634,6 +625,7 @@ HTML output: --(no-)sort Enable (disable) sorted coverage views --demangle-cpp Demangle C++ function names --precision NUM Set precision of coverage rate + --missed Show miss counts as negative numbers For more information see: $lcov_url END_OF_USAGE @@ -1375,6 +1367,16 @@ sub process_file($$$) } +sub compress_brcount($) +{ + my ($brcount) = @_; + my $db; + + $db = brcount_to_db($brcount); + return db_to_brcount($db, $brcount); +} + + # # read_info_file(info_filename) # @@ -1446,8 +1448,6 @@ sub read_info_file($) my $negative; # If set, warn about negative counts my $changed_testname; # If set, warn about changed testname my $line_checksum; # Checksum of current line - my $br_found; - my $br_hit; my $notified_about_relative_paths; local *INFO_HANDLE; # Filehandle for .info file @@ -1515,7 +1515,7 @@ sub read_info_file($) { # Filename information found # Retrieve data for new entry - $filename = File::Spec->rel2abs($1, Cwd::cwd()); + $filename = File::Spec->rel2abs($1, $cwd); if (!File::Spec->file_name_is_absolute($1) && !$notified_about_relative_paths) @@ -1625,17 +1625,13 @@ sub read_info_file($) ($1, $2, $3, $4); last if (!$br_coverage); - $sumbrcount->{$line} = - br_ivec_push($sumbrcount->{$line}, - $block, $branch, $taken); + $sumbrcount->{$line} .= + "$block,$branch,$taken:"; # Add test-specific counts if (defined($testname)) { - $testbrcount->{$line} = - br_ivec_push( - $testbrcount->{$line}, - $block, $branch, - $taken); + $testbrcount->{$line} .= + "$block,$branch,$taken:"; } last; }; @@ -1720,11 +1716,12 @@ sub read_info_file($) } $data->{"f_hit"} = $hitcount; - # Get found/hit values for branch data - ($br_found, $br_hit) = get_br_found_and_hit($sumbrcount); - - $data->{"b_found"} = $br_found; - $data->{"b_hit"} = $br_hit; + # Combine branch data for the same branches + (undef, $data->{"b_found"}, $data->{"b_hit"}) = + compress_brcount($sumbrcount); + foreach $testname (keys(%{$testbrdata})) { + compress_brcount($testbrdata->{$testname}); + } } if (scalar(keys(%result)) == 0) @@ -2022,16 +2019,21 @@ sub brcount_to_db($) my $line; my $db; - # Add branches from first count to database + # Add branches to database foreach $line (keys(%{$brcount})) { my $brdata = $brcount->{$line}; - my $i; - my $num = br_ivec_len($brdata); - for ($i = 0; $i < $num; $i++) { - my ($block, $branch, $taken) = br_ivec_get($brdata, $i); + foreach my $entry (split(/:/, $brdata)) { + my ($block, $branch, $taken) = split(/,/, $entry); + my $old = $db->{$line}->{$block}->{$branch}; + + if (!defined($old) || $old eq "-") { + $old = $taken; + } elsif ($taken ne "-") { + $old += $taken; + } - $db->{$line}->{$block}->{$branch} = $taken; + $db->{$line}->{$block}->{$branch} = $old; } } @@ -2040,16 +2042,16 @@ sub brcount_to_db($) # -# db_to_brcount(db) +# db_to_brcount(db[, brcount]) # -# Convert branch coverage data back to brcount format. +# Convert branch coverage data back to brcount format. If brcount is specified, +# the converted data is directly inserted in brcount. # -sub db_to_brcount($) +sub db_to_brcount($;$) { - my ($db) = @_; + my ($db, $brcount) = @_; my $line; - my $brcount = {}; my $br_found = 0; my $br_hit = 0; @@ -2068,8 +2070,7 @@ sub db_to_brcount($) $br_found++; $br_hit++ if ($taken ne "-" && $taken > 0); - $brdata = br_ivec_push($brdata, $block, - $branch, $taken); + $brdata .= "$block,$branch,$taken:"; } } $brcount->{$line} = $brdata; @@ -2080,50 +2081,91 @@ sub db_to_brcount($) # -# combine_brcount(brcount1, brcount2, type) +# brcount_db_combine(db1, db2, op) # -# If add is BR_ADD, add branch coverage data and return list (brcount_added, -# br_found, br_hit). If add is BR_SUB, subtract the taken values of brcount2 -# from brcount1 and return (brcount_sub, br_found, br_hit). +# db1 := db1 op db2, where +# db1, db2: brcount data as returned by brcount_to_db +# op: one of $BR_ADD and BR_SUB # +sub brcount_db_combine($$$) +{ + my ($db1, $db2, $op) = @_; + + foreach my $line (keys(%{$db2})) { + my $ldata = $db2->{$line}; -sub combine_brcount($$$) + foreach my $block (keys(%{$ldata})) { + my $bdata = $ldata->{$block}; + + foreach my $branch (keys(%{$bdata})) { + my $taken = $bdata->{$branch}; + my $new = $db1->{$line}->{$block}->{$branch}; + + if (!defined($new) || $new eq "-") { + $new = $taken; + } elsif ($taken ne "-") { + if ($op == $BR_ADD) { + $new += $taken; + } elsif ($op == $BR_SUB) { + $new -= $taken; + $new = 0 if ($new < 0); + } + } + + $db1->{$line}->{$block}->{$branch} = $new; + } + } + } +} + + +# +# brcount_db_get_found_and_hit(db) +# +# Return (br_found, br_hit) for db. +# + +sub brcount_db_get_found_and_hit($) { - my ($brcount1, $brcount2, $type) = @_; - my $line; - my $block; - my $branch; - my $taken; - my $db; - my $br_found = 0; - my $br_hit = 0; - my $result; + my ($db) = @_; + my ($br_found , $br_hit) = (0, 0); + + foreach my $line (keys(%{$db})) { + my $ldata = $db->{$line}; + + foreach my $block (keys(%{$ldata})) { + my $bdata = $ldata->{$block}; - # Convert branches from first count to database - $db = brcount_to_db($brcount1); - # Combine values from database and second count - foreach $line (keys(%{$brcount2})) { - my $brdata = $brcount2->{$line}; - my $num = br_ivec_len($brdata); - my $i; - - for ($i = 0; $i < $num; $i++) { - ($block, $branch, $taken) = br_ivec_get($brdata, $i); - my $new_taken = $db->{$line}->{$block}->{$branch}; - - if ($type == $BR_ADD) { - $new_taken = br_taken_add($new_taken, $taken); - } elsif ($type == $BR_SUB) { - $new_taken = br_taken_sub($new_taken, $taken); + foreach my $branch (keys(%{$bdata})) { + my $taken = $bdata->{$branch}; + + $br_found++; + $br_hit++ if ($taken ne "-" && $taken > 0); } - $db->{$line}->{$block}->{$branch} = $new_taken - if (defined($new_taken)); } } - # Convert database back to brcount format - ($result, $br_found, $br_hit) = db_to_brcount($db); - return ($result, $br_found, $br_hit); + return ($br_found, $br_hit); +} + + +# combine_brcount(brcount1, brcount2, type, inplace) +# +# If add is BR_ADD, add branch coverage data and return list brcount_added. +# If add is BR_SUB, subtract the taken values of brcount2 from brcount1 and +# return brcount_sub. If inplace is set, the result is inserted into brcount1. +# + +sub combine_brcount($$$;$) +{ + my ($brcount1, $brcount2, $type, $inplace) = @_; + my ($db1, $db2); + + $db1 = brcount_to_db($brcount1); + $db2 = brcount_to_db($brcount2); + brcount_db_combine($db1, $db2, $type); + + return db_to_brcount($db1, $inplace ? $brcount1 : undef); } @@ -2584,9 +2626,18 @@ sub get_date_string() my $hour; my $min; my $sec; + my @timeresult; + if (defined $ENV{'SOURCE_DATE_EPOCH'}) + { + @timeresult = gmtime($ENV{'SOURCE_DATE_EPOCH'}); + } + else + { + @timeresult = localtime(); + } ($year, $month, $day, $hour, $min, $sec) = - (localtime())[5, 4, 3, 2, 1, 0]; + @timeresult[5, 4, 3, 2, 1, 0]; return sprintf("%d-%02d-%02d %02d:%02d:%02d", $year+1900, $month+1, $day, $hour, $min, $sec); @@ -3695,6 +3746,10 @@ END_OF_HTML $class = $rate_name[classify_rate($found, $hit, $med, $hi)]; } + if ($opt_missed) { + # Show negative number of items without coverage + $hit = -($found - $hit); + } write_html($handle, <$rate $hit / $found @@ -3892,6 +3947,14 @@ END_OF_HTML # ************************************************************* } +sub cmp_blocks($$) +{ + my ($a, $b) = @_; + my ($fa, $fb) = ($a->[0], $b->[0]); + + return $fa->[0] <=> $fb->[0] if ($fa->[0] != $fb->[0]); + return $fa->[1] <=> $fb->[1]; +} # # get_branch_blocks(brdata) @@ -3909,12 +3972,12 @@ sub get_branch_blocks($) my $last_block_num; my $block = []; my @blocks; - my $i; - my $num = br_ivec_len($brdata); + + return () if (!defined($brdata)); # Group branches - for ($i = 0; $i < $num; $i++) { - my ($block_num, $branch, $taken) = br_ivec_get($brdata, $i); + foreach my $entry (split(/:/, $brdata)) { + my ($block_num, $branch, $taken) = split(/,/, $entry); my $br; if (defined($last_block_num) && $block_num != $last_block_num) { @@ -3935,7 +3998,7 @@ sub get_branch_blocks($) $block->[scalar(@{$block}) - 1]->[$BR_LEN]++; } - return @blocks; + return sort(cmp_blocks @blocks); } # @@ -4092,16 +4155,15 @@ sub format_count($$) # # write_source_line(filehandle, line_num, source, hit_count, converted, -# brdata, add_anchor) +# brdata) # # Write formatted source code line. Return a line in a format as needed # by gen_png() # -sub write_source_line(*$$$$$$) +sub write_source_line(*$$$$$) { - my ($handle, $line, $source, $count, $converted, $brdata, - $add_anchor) = @_; + my ($handle, $line, $source, $count, $converted, $brdata) = @_; my $source_format; my $count_format; my $result; @@ -4138,11 +4200,8 @@ sub write_source_line(*$$$$$$) # Write out a line number navigation anchor every $nav_resolution # lines if necessary - if ($add_anchor) - { - $anchor_start = ""; - $anchor_end = ""; - } + $anchor_start = ""; + $anchor_end = ""; # ************************************************************* @@ -4587,10 +4646,57 @@ END_OF_HTML write_header_epilog(*HTML_HANDLE, $base_dir); } +sub get_sorted_by_rate($$) +{ + my ($hash, $type) = @_; + + if ($type == $SORT_LINE) { + # Sort by line coverage + return sort({$hash->{$a}[7] <=> $hash->{$b}[7]} keys(%{$hash})); + } elsif ($type == $SORT_FUNC) { + # Sort by function coverage; + return sort({$hash->{$a}[8] <=> $hash->{$b}[8]} keys(%{$hash})); + } elsif ($type == $SORT_BRANCH) { + # Sort by br coverage; + return sort({$hash->{$a}[9] <=> $hash->{$b}[9]} keys(%{$hash})); + } +} + +sub get_sorted_by_missed($$) +{ + my ($hash, $type) = @_; + + if ($type == $SORT_LINE) { + # Sort by number of instrumented lines without coverage + return sort( + { + ($hash->{$b}[0] - $hash->{$b}[1]) <=> + ($hash->{$a}[0] - $hash->{$a}[1]) + } keys(%{$hash})); + } elsif ($type == $SORT_FUNC) { + # Sort by number of instrumented functions without coverage + return sort( + { + ($hash->{$b}[2] - $hash->{$b}[3]) <=> + ($hash->{$a}[2] - $hash->{$a}[3]) + } keys(%{$hash})); + } elsif ($type == $SORT_BRANCH) { + # Sort by number of instrumented branches without coverage + return sort( + { + ($hash->{$b}[4] - $hash->{$b}[5]) <=> + ($hash->{$a}[4] - $hash->{$a}[5]) + } keys(%{$hash})); + } +} # # get_sorted_keys(hash_ref, sort_type) # +# hash_ref: filename -> stats +# stats: [ lines_found, lines_hit, fn_found, fn_hit, br_found, br_hit, +# link_name, line_rate, fn_rate, br_rate ] +# sub get_sorted_keys($$) { @@ -4599,15 +4705,10 @@ sub get_sorted_keys($$) if ($type == $SORT_FILE) { # Sort by name return sort(keys(%{$hash})); - } elsif ($type == $SORT_LINE) { - # Sort by line coverage - return sort({$hash->{$a}[7] <=> $hash->{$b}[7]} keys(%{$hash})); - } elsif ($type == $SORT_FUNC) { - # Sort by function coverage; - return sort({$hash->{$a}[8] <=> $hash->{$b}[8]} keys(%{$hash})); - } elsif ($type == $SORT_BRANCH) { - # Sort by br coverage; - return sort({$hash->{$a}[9] <=> $hash->{$b}[9]} keys(%{$hash})); + } elsif ($opt_missed) { + return get_sorted_by_missed($hash, $type); + } else { + return get_sorted_by_rate($hash, $type); } } @@ -4930,186 +5031,14 @@ sub get_func_found_and_hit($) } -# -# br_taken_to_num(taken) -# -# Convert a branch taken value .info format to number format. -# - -sub br_taken_to_num($) -{ - my ($taken) = @_; - - return 0 if ($taken eq '-'); - return $taken + 1; -} - - -# -# br_num_to_taken(taken) -# -# Convert a branch taken value in number format to .info format. -# - -sub br_num_to_taken($) -{ - my ($taken) = @_; - - return '-' if ($taken == 0); - return $taken - 1; -} - - -# -# br_taken_add(taken1, taken2) -# -# Return the result of taken1 + taken2 for 'branch taken' values. -# - -sub br_taken_add($$) -{ - my ($t1, $t2) = @_; - - return $t1 if (!defined($t2)); - return $t2 if (!defined($t1)); - return $t1 if ($t2 eq '-'); - return $t2 if ($t1 eq '-'); - return $t1 + $t2; -} - - -# -# br_taken_sub(taken1, taken2) -# -# Return the result of taken1 - taken2 for 'branch taken' values. Return 0 -# if the result would become negative. -# - -sub br_taken_sub($$) -{ - my ($t1, $t2) = @_; - - return $t1 if (!defined($t2)); - return undef if (!defined($t1)); - return $t1 if ($t1 eq '-'); - return $t1 if ($t2 eq '-'); - return 0 if $t2 > $t1; - return $t1 - $t2; -} - - -# -# br_ivec_len(vector) -# -# Return the number of entries in the branch coverage vector. -# - -sub br_ivec_len($) -{ - my ($vec) = @_; - - return 0 if (!defined($vec)); - return (length($vec) * 8 / $BR_VEC_WIDTH) / $BR_VEC_ENTRIES; -} - - -# -# br_ivec_get(vector, number) -# -# Return an entry from the branch coverage vector. -# - -sub br_ivec_get($$) -{ - my ($vec, $num) = @_; - my $block; - my $branch; - my $taken; - my $offset = $num * $BR_VEC_ENTRIES; - - # Retrieve data from vector - $block = vec($vec, $offset + $BR_BLOCK, $BR_VEC_WIDTH); - $block = -1 if ($block == $BR_VEC_MAX); - $branch = vec($vec, $offset + $BR_BRANCH, $BR_VEC_WIDTH); - $taken = vec($vec, $offset + $BR_TAKEN, $BR_VEC_WIDTH); - - # Decode taken value from an integer - $taken = br_num_to_taken($taken); - - return ($block, $branch, $taken); -} - - -# -# br_ivec_push(vector, block, branch, taken) -# -# Add an entry to the branch coverage vector. If an entry with the same -# branch ID already exists, add the corresponding taken values. -# - -sub br_ivec_push($$$$) -{ - my ($vec, $block, $branch, $taken) = @_; - my $offset; - my $num = br_ivec_len($vec); - my $i; - - $vec = "" if (!defined($vec)); - $block = $BR_VEC_MAX if $block < 0; - - # Check if branch already exists in vector - for ($i = 0; $i < $num; $i++) { - my ($v_block, $v_branch, $v_taken) = br_ivec_get($vec, $i); - $v_block = $BR_VEC_MAX if $v_block < 0; - - next if ($v_block != $block || $v_branch != $branch); - - # Add taken counts - $taken = br_taken_add($taken, $v_taken); - last; - } - - $offset = $i * $BR_VEC_ENTRIES; - $taken = br_taken_to_num($taken); - - # Add to vector - vec($vec, $offset + $BR_BLOCK, $BR_VEC_WIDTH) = $block; - vec($vec, $offset + $BR_BRANCH, $BR_VEC_WIDTH) = $branch; - vec($vec, $offset + $BR_TAKEN, $BR_VEC_WIDTH) = $taken; - - return $vec; -} - - -# -# get_br_found_and_hit(sumbrcount) -# -# Return (br_found, br_hit) for sumbrcount -# - sub get_br_found_and_hit($) { - my ($sumbrcount) = @_; - my $line; - my $br_found = 0; - my $br_hit = 0; - - foreach $line (keys(%{$sumbrcount})) { - my $brdata = $sumbrcount->{$line}; - my $i; - my $num = br_ivec_len($brdata); - - for ($i = 0; $i < $num; $i++) { - my $taken; - - (undef, undef, $taken) = br_ivec_get($brdata, $i); + my ($brcount) = @_; + my $db; - $br_found++; - $br_hit++ if ($taken ne "-" && $taken > 0); - } - } + $db = brcount_to_db($brcount); - return ($br_found, $br_hit); + return brcount_db_get_found_and_hit($db); } @@ -5194,7 +5123,6 @@ sub write_source($$$$$$$) my $funcdata = $_[5]; my $sumbrcount = $_[6]; my $datafunc = get_hash_reverse($funcdata); - my $add_anchor; my @file; if ($_[2]) @@ -5245,25 +5173,11 @@ sub write_source($$$$$$$) "$line_number\n"); } - $add_anchor = 0; - if ($frames) { - if (($line_number - 1) % $nav_resolution == 0) { - $add_anchor = 1; - } - } - if ($func_coverage) { - if ($line_number == 1) { - $add_anchor = 1; - } elsif (defined($datafunc->{$line_number + - $func_offset})) { - $add_anchor = 1; - } - } push (@result, write_source_line(HTML_HANDLE, $line_number, $_, $count_data{$line_number}, $converted->{$line_number}, - $sumbrcount->{$line_number}, $add_anchor)); + $sumbrcount->{$line_number})); } close(SOURCE_HANDLE); diff --git a/lcov-1.13/bin/geninfo b/lcov-1.14/bin/geninfo similarity index 95% rename from lcov-1.13/bin/geninfo rename to lcov-1.14/bin/geninfo index 3f720c7..f41eaec 100755 --- a/lcov-1.13/bin/geninfo +++ b/lcov-1.14/bin/geninfo @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # Copyright (c) International Business Machines Corp., 2002,2012 # @@ -50,6 +50,7 @@ # use strict; +use warnings; use File::Basename; use File::Spec::Functions qw /abs2rel catdir file_name_is_absolute splitdir splitpath catpath/; @@ -63,11 +64,12 @@ if( $^O eq "msys" ) # Constants our $tool_dir = abs_path(dirname($0)); -our $lcov_version = "LCOV version 1.13"; +our $lcov_version = "LCOV version 1.14"; our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; our $gcov_tool = "gcov"; our $tool_name = basename($0); +our $GCOV_VERSION_8_0_0 = 0x80000; our $GCOV_VERSION_4_7_0 = 0x40700; our $GCOV_VERSION_3_4_0 = 0x30400; our $GCOV_VERSION_3_3_0 = 0x30300; @@ -151,6 +153,7 @@ our $UNNAMED_BLOCK = -1; # Prototypes sub print_usage(*); +sub transform_pattern($); sub gen_info($); sub process_dafile($$); sub match_filename($@); @@ -181,7 +184,7 @@ sub sort_uniq(@); sub sort_uniq_lex(@); sub graph_cleanup($); sub graph_find_base($); -sub graph_from_bb($$$); +sub graph_from_bb($$$$); sub graph_add_order($$$); sub read_bb_word(*;$); sub read_bb_value(*;$); @@ -239,6 +242,9 @@ our $config; # Configuration file contents our @ignore_errors; # List of errors to ignore (parameter) our @ignore; # List of errors to ignore (array) our $initial; +our @include_patterns; # List of source file patterns to include +our @exclude_patterns; # List of source file patterns to exclude +our %excluded_files; # Files excluded due to include/exclude options our $no_recursion = 0; our $maxdepth; our $no_markers = 0; @@ -382,11 +388,13 @@ if (!GetOptions("test-name|t=s" => \$test_name, "gcov-tool=s" => \$gcov_tool, "ignore-errors=s" => \@ignore_errors, "initial|i" => \$initial, + "include=s" => \@include_patterns, + "exclude=s" => \@exclude_patterns, "no-recursion" => \$no_recursion, "no-markers" => \$no_markers, "derive-func-data" => \$opt_derive_func_data, "debug" => \$debug, - "external" => \$opt_external, + "external|e" => \$opt_external, "no-external" => \$opt_no_external, "compat=s" => \$opt_compat, "config-file=s" => \$opt_config_file, @@ -415,6 +423,16 @@ else $opt_external = 0; $opt_no_external = undef; } + + if(@include_patterns) { + # Need perlreg expressions instead of shell pattern + @include_patterns = map({ transform_pattern($_); } @include_patterns); + } + + if(@exclude_patterns) { + # Need perlreg expressions instead of shell pattern + @exclude_patterns = map({ transform_pattern($_); } @exclude_patterns); + } } @data_directory = @ARGV; @@ -451,7 +469,12 @@ push(@gcov_options, "-c") if ($gcov_caps->{'branch-counts'} && $br_coverage); push(@gcov_options, "-a") if ($gcov_caps->{'all-blocks'} && $opt_gcov_all_blocks && $br_coverage); -push(@gcov_options, "-p") if ($gcov_caps->{'preserve-paths'}); +if ($gcov_caps->{'hash-filenames'}) +{ + push(@gcov_options, "-x"); +} else { + push(@gcov_options, "-p") if ($gcov_caps->{'preserve-paths'}); +} # Determine compatibility modes parse_compat_modes($opt_compat); @@ -622,12 +645,53 @@ sequentially. --config-file FILENAME Specify configuration file location --rc SETTING=VALUE Override configuration file setting --compat MODE=on|off|auto Set compat MODE (libtool, hammer, split_crc) + --include PATTERN Include files matching PATTERN + --exclude PATTERN Exclude files matching PATTERN For more information see: $lcov_url END_OF_USAGE ; } + +# +# transform_pattern(pattern) +# +# Transform shell wildcard expression to equivalent Perl regular expression. +# Return transformed pattern. +# + +sub transform_pattern($) +{ + my $pattern = $_[0]; + + # Escape special chars + + $pattern =~ s/\\/\\\\/g; + $pattern =~ s/\//\\\//g; + $pattern =~ s/\^/\\\^/g; + $pattern =~ s/\$/\\\$/g; + $pattern =~ s/\(/\\\(/g; + $pattern =~ s/\)/\\\)/g; + $pattern =~ s/\[/\\\[/g; + $pattern =~ s/\]/\\\]/g; + $pattern =~ s/\{/\\\{/g; + $pattern =~ s/\}/\\\}/g; + $pattern =~ s/\./\\\./g; + $pattern =~ s/\,/\\\,/g; + $pattern =~ s/\|/\\\|/g; + $pattern =~ s/\+/\\\+/g; + $pattern =~ s/\!/\\\!/g; + + # Transform ? => (.) and * => (.*) + + $pattern =~ s/\*/\(\.\*\)/g; + $pattern =~ s/\?/\(\.\)/g; + + return $pattern; +} + + # # get_common_prefix(min_dir, filenames) # @@ -743,6 +807,12 @@ sub gen_info($) process_dafile($file, $prefix); } } + + # Report whether files were excluded. + if (%excluded_files) { + info("Excluded data for %d files due to include/exclude options\n", + scalar keys %excluded_files); + } } @@ -1176,6 +1246,40 @@ sub process_dafile($$) \@matches, \@gcov_content); } + if (@include_patterns) + { + my $keep = 0; + + foreach my $pattern (@include_patterns) + { + $keep ||= ($source_filename =~ (/^$pattern$/)); + } + + if (!$keep) + { + $excluded_files{$source_filename} = (); + unlink($gcov_file); + next; + } + } + + if (@exclude_patterns) + { + my $exclude = 0; + + foreach my $pattern (@exclude_patterns) + { + $exclude ||= ($source_filename =~ (/^$pattern$/)); + } + + if ($exclude) + { + $excluded_files{$source_filename} = (); + unlink($gcov_file); + next; + } + } + # Skip external files if requested if (!$opt_external) { if (is_external($source_filename)) { @@ -1386,7 +1490,9 @@ sub solve_relative_path($$) $result =~ s/\/\//\//g; # Remove . - $result =~ s/\/\.\//\//g; + while ($result =~ s/\/\.\//\//g) + { + } $result =~ s/\/\.$/\//g; # Remove trailing / @@ -1803,7 +1909,7 @@ sub read_gcov_file($) # Also remove CR from line-end s/\015$//; - if (/^\s*(\d+|\$+):\s*(\d+)-block\s+(\d+)\s*$/) { + if (/^\s*(\d+|\$+|\%+):\s*(\d+)-block\s+(\d+)\s*$/) { # Block information - used to group related # branches $last_line = $2; @@ -1837,6 +1943,9 @@ sub read_gcov_file($) { my ($count, $line, $code) = ($1, $2, $3); + # Skip instance-specific counts + next if ($line <= (scalar(@result) / 3)); + $last_line = $line; $last_block = $UNNAMED_BLOCK; # Check for exclusion markers @@ -1866,6 +1975,9 @@ sub read_gcov_file($) } } + # Strip unexecuted basic block marker + $count =~ s/\*$//; + # :: if ($line eq "0") { @@ -2846,9 +2958,13 @@ sub graph_find_base($) } # -# graph_from_bb(bb, fileorder, bb_filename) +# graph_from_bb(bb, fileorder, bb_filename, fileorder_first) # # Convert data from bb to the graph format and list of instrumented lines. +# +# If FILEORDER_FIRST is set, use fileorder data to determine a functions +# base source file. +# # Returns (instr, graph). # # bb : function name -> file data @@ -2866,9 +2982,9 @@ sub graph_find_base($) # line data : [ line1, line2, ... ] # -sub graph_from_bb($$$) +sub graph_from_bb($$$$) { - my ($bb, $fileorder, $bb_filename) = @_; + my ($bb, $fileorder, $bb_filename, $fileorder_first) = @_; my $graph = {}; my $instr = {}; my $basefile; @@ -2885,7 +3001,8 @@ sub graph_from_bb($$$) $order = $fileorder->{$func}; # Account for lines in functions - if (defined($basefile) && defined($filedata->{$basefile})) { + if (defined($basefile) && defined($filedata->{$basefile}) && + !$fileorder_first) { # If the basefile contributes to this function, # account this function to the basefile. $graph->{$basefile}->{$func} = $filedata->{$basefile}; @@ -3047,7 +3164,8 @@ sub read_bb($) } } close(HANDLE); - ($instr, $graph) = graph_from_bb($bb, $fileorder, $bb_filename); + + ($instr, $graph) = graph_from_bb($bb, $fileorder, $bb_filename, 0); graph_cleanup($graph); return ($instr, $graph); @@ -3235,7 +3353,8 @@ sub read_bbg($) } } close(HANDLE); - ($instr, $graph) = graph_from_bb($bb, $fileorder, $bbg_filename); + ($instr, $graph) = graph_from_bb($bb, $fileorder, $bbg_filename, 0); + graph_cleanup($graph); return ($instr, $graph); @@ -3413,7 +3532,7 @@ sub determine_gcno_split_crc($$$$) # read_gcno_function_record(handle, graph, big_endian, rec_length, version) # # Read a gcno format function record from handle and add the relevant data -# to graph. Return (filename, function) on success, undef on error. +# to graph. Return (filename, function, artificial) on success, undef on error. # sub read_gcno_function_record(*$$$$$) @@ -3423,6 +3542,7 @@ sub read_gcno_function_record(*$$$$$) my $function; my $lineno; my $lines; + my $artificial; graph_expect("function record"); # Skip ident and checksum @@ -3440,6 +3560,11 @@ sub read_gcno_function_record(*$$$$$) graph_expect("function name"); $function = read_gcno_string($handle, $big_endian); return undef if (!defined($function)); + if ($version >= $GCOV_VERSION_8_0_0) { + $artificial = read_gcno_value($handle, $big_endian, + "compiler-generated entity flag"); + return undef if (!defined($artificial)); + } # Read filename graph_expect("filename"); $filename = read_gcno_string($handle, $big_endian); @@ -3447,11 +3572,16 @@ sub read_gcno_function_record(*$$$$$) # Read first line number $lineno = read_gcno_value($handle, $big_endian, "initial line number"); return undef if (!defined($lineno)); + # Skip column and ending line number + if ($version >= $GCOV_VERSION_8_0_0) { + graph_skip($handle, 4, "column number") or return undef; + graph_skip($handle, 4, "ending line number") or return undef; + } # Add to list push(@{$bb->{$function}->{$filename}}, $lineno); graph_add_order($fileorder, $function, $filename); - return ($filename, $function); + return ($filename, $function, $artificial); } # @@ -3481,6 +3611,15 @@ sub map_gcno_version($) return $major << 16 | $minor << 8; } +sub remove_fn_from_hash($$) +{ + my ($hash, $fns) = @_; + + foreach my $fn (@$fns) { + delete($hash->{$fn}); + } +} + # # read_gcno(filename) # @@ -3512,6 +3651,8 @@ sub read_gcno($) my $graph; my $filelength; my $version; + my $artificial; + my @artificial_fns; local *HANDLE; open(HANDLE, "<", $gcno_filename) or goto open_error; @@ -3534,6 +3675,10 @@ sub read_gcno($) debug(sprintf("found version 0x%08x\n", $version)); # Skip stamp graph_skip(*HANDLE, 4, "file timestamp") or goto incomplete; + if ($version >= $GCOV_VERSION_8_0_0) { + graph_skip(*HANDLE, 4, "support unexecuted blocks flag") + or goto incomplete; + } while (!eof(HANDLE)) { my $next_pos; my $curr_pos; @@ -3561,16 +3706,17 @@ sub read_gcno($) } # Process record if ($tag == $tag_function) { - ($filename, $function) = read_gcno_function_record( + ($filename, $function, $artificial) = + read_gcno_function_record( *HANDLE, $bb, $fileorder, $big_endian, $length, $version); goto incomplete if (!defined($function)); + push(@artificial_fns, $function) if ($artificial); } elsif ($tag == $tag_lines) { # Read lines record $filename = read_gcno_lines_record(*HANDLE, $gcno_filename, $bb, $fileorder, - $filename, $function, - $big_endian); + $filename, $function, $big_endian); goto incomplete if (!defined($filename)); } else { # Skip record contents @@ -3587,7 +3733,12 @@ sub read_gcno($) or goto incomplete; } close(HANDLE); - ($instr, $graph) = graph_from_bb($bb, $fileorder, $gcno_filename); + + # Remove artificial functions from result data + remove_fn_from_hash($bb, \@artificial_fns); + remove_fn_from_hash($fileorder, \@artificial_fns); + + ($instr, $graph) = graph_from_bb($bb, $fileorder, $gcno_filename, 1); graph_cleanup($graph); return ($instr, $graph); @@ -3639,6 +3790,7 @@ sub get_gcov_capabilities() 'p' => 'preserve-paths', 'u' => 'unconditional-branches', 'v' => 'version', + 'x' => 'hash-filenames', ); foreach (split(/\n/, $help)) { diff --git a/lcov-1.13/bin/genpng b/lcov-1.14/bin/genpng similarity index 99% rename from lcov-1.13/bin/genpng rename to lcov-1.14/bin/genpng index e651beb..943a49d 100755 --- a/lcov-1.13/bin/genpng +++ b/lcov-1.14/bin/genpng @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # Copyright (c) International Business Machines Corp., 2002 # @@ -30,6 +30,7 @@ # use strict; +use warnings; use File::Basename; use Getopt::Long; use Cwd qw/abs_path/; @@ -37,7 +38,7 @@ use Cwd qw/abs_path/; # Constants our $tool_dir = abs_path(dirname($0)); -our $lcov_version = "LCOV version 1.13"; +our $lcov_version = "LCOV version 1.14"; our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; our $tool_name = basename($0); diff --git a/lcov-1.13/bin/get_changes.sh b/lcov-1.14/bin/get_changes.sh similarity index 77% rename from lcov-1.13/bin/get_changes.sh rename to lcov-1.14/bin/get_changes.sh index cfa97d6..ec373b4 100755 --- a/lcov-1.13/bin/get_changes.sh +++ b/lcov-1.14/bin/get_changes.sh @@ -1,10 +1,10 @@ -#!/bin/bash +#!/usr/bin/env bash # # Usage: get_changes.sh # # Print lcov change log information as provided by Git -TOOLDIR=$(cd $(dirname $0) ; pwd) +TOOLDIR=$(cd $(dirname $0) >/dev/null ; pwd) cd $TOOLDIR diff --git a/lcov-1.13/bin/get_version.sh b/lcov-1.14/bin/get_version.sh similarity index 92% rename from lcov-1.13/bin/get_version.sh rename to lcov-1.14/bin/get_version.sh index c9d70ed..ac5a363 100755 --- a/lcov-1.13/bin/get_version.sh +++ b/lcov-1.14/bin/get_version.sh @@ -1,11 +1,11 @@ -#!/bin/bash +#!/usr/bin/env bash # # Usage: get_version.sh --version|--release|--full # # Print lcov version or release information as provided by Git, .version # or a fallback. -TOOLDIR=$(cd $(dirname $0) ; pwd) +TOOLDIR=$(cd $(dirname $0) >/dev/null ; pwd) GITVER=$(cd $TOOLDIR ; git describe --tags 2>/dev/null) if [ -z "$GITVER" ] ; then diff --git a/lcov-1.13/bin/install.sh b/lcov-1.14/bin/install.sh similarity index 81% rename from lcov-1.13/bin/install.sh rename to lcov-1.14/bin/install.sh index d43c921..2cdef45 100755 --- a/lcov-1.13/bin/install.sh +++ b/lcov-1.14/bin/install.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # install.sh [--uninstall] sourcefile targetfile [install options] # @@ -36,6 +36,10 @@ do_install() install -d $(dirname $TARGET) install -p $PARAMS $SOURCE $TARGET + if [ -n "$LCOV_PERL_PATH" ] ; then + # Replace Perl interpreter specification + sed -e "1 s%^#\!.*perl.*$%#\!$LCOV_PERL_PATH%" -i $TARGET + fi } @@ -51,7 +55,7 @@ do_uninstall() # Does target exist? if test -r $TARGET ; then # Is target of the same version as this package? - if diff -I '^our \$lcov_version' -I '^\.TH ' $SOURCE $TARGET >/dev/null; then + if diff -I '^our \$lcov_version' -I '^\.TH ' -I '^#!' $SOURCE $TARGET >/dev/null; then rm -f $TARGET else echo WARNING: Skipping uninstall for $TARGET - versions differ! >&2 diff --git a/lcov-1.13/bin/lcov b/lcov-1.14/bin/lcov similarity index 94% rename from lcov-1.13/bin/lcov rename to lcov-1.14/bin/lcov index f68df66..33c9f4d 100755 --- a/lcov-1.13/bin/lcov +++ b/lcov-1.14/bin/lcov @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # Copyright (c) International Business Machines Corp., 2002,2012 # @@ -60,6 +60,7 @@ # use strict; +use warnings; use File::Basename; use File::Path; use File::Find; @@ -72,7 +73,7 @@ use Cwd qw /abs_path getcwd/; # Global constants our $tool_dir = abs_path(dirname($0)); -our $lcov_version = "LCOV version 1.13"; +our $lcov_version = "LCOV version 1.14"; our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; our $tool_name = basename($0); @@ -89,13 +90,6 @@ our @GKV_NAME = ( "external", "upstream" ); our $pkg_gkv_file = ".gcov_kernel_version"; our $pkg_build_file = ".build_directory"; -our $BR_BLOCK = 0; -our $BR_BRANCH = 1; -our $BR_TAKEN = 2; -our $BR_VEC_ENTRIES = 3; -our $BR_VEC_WIDTH = 32; -our $BR_VEC_MAX = vec(pack('b*', 1 x $BR_VEC_WIDTH), 0, $BR_VEC_WIDTH); - # Branch data combination types our $BR_SUB = 0; our $BR_ADD = 1; @@ -140,7 +134,6 @@ sub print_overall_rate($$$$$$$$$); sub lcov_geninfo(@); sub create_package($$$;$); sub get_func_found_and_hit($); -sub br_ivec_get($$); sub summary(); sub rate($$;$$$); @@ -163,7 +156,7 @@ our $convert_filenames; # If set, convert filenames when applying diff our $strip; # If set, strip leading directories when applying diff our $temp_dir_name; # Name of temporary directory our $cwd = `pwd`; # Current working directory -our $to_file; # If set, indicates that output is written to a file +our $data_stdout; # If set, indicates that data is written to stdout our $follow; # If set, indicates that find shall follow links our $diff_path = ""; # Path removed from tracefile when applying diff our $base_directory; # Base directory (cwd of gcc during compilation) @@ -174,6 +167,8 @@ our $no_compat_libtool; # If set, indicates that libtool mode is to be disabled our $gcov_tool; our @opt_ignore_errors; our $initial; +our @include_patterns; # List of source file patterns to include +our @exclude_patterns; # List of source file patterns to exclude our $no_recursion = 0; our $to_package; our $from_package; @@ -289,6 +284,8 @@ if (!GetOptions("directory|d|di=s" => \@directory, "gcov-tool=s" => \$gcov_tool, "ignore-errors=s" => \@opt_ignore_errors, "initial|i" => \$initial, + "include=s" => \@include_patterns, + "exclude=s" => \@exclude_patterns, "no-recursion" => \$no_recursion, "to-package=s" => \$to_package, "from-package=s" => \$from_package, @@ -387,11 +384,11 @@ if (@ARGV && !($extract || $remove || $diff || @opt_summary)) } # Check for output filename -$to_file = ($output_filename && ($output_filename ne "-")); +$data_stdout = !($output_filename && ($output_filename ne "-")); if ($capture) { - if (!$to_file) + if ($data_stdout) { # Option that tells geninfo to write to stdout $output_filename = "-"; @@ -406,6 +403,7 @@ if (!$from_package && !@directory && ($capture || $reset)) { # Check for requested functionality if ($reset) { + $data_stdout = 0; # Differentiate between user space and kernel reset if (@directory) { @@ -455,6 +453,7 @@ elsif ($extract) } elsif ($list) { + $data_stdout = 0; list(); } elsif ($diff) @@ -470,6 +469,7 @@ elsif ($diff) } elsif (@opt_summary) { + $data_stdout = 0; ($ln_overall_found, $ln_overall_hit, $fn_overall_found, $fn_overall_hit, $br_overall_found, $br_overall_hit) = summary(); @@ -543,6 +543,8 @@ Options: --config-file FILENAME Specify configuration file location --rc SETTING=VALUE Override configuration file setting --compat MODE=on|off|auto Set compat MODE (libtool, hammer, split_crc) + --include PATTERN Include files matching PATTERN + --exclude PATTERN Exclude files matching PATTERN For more information see: $lcov_url END_OF_USAGE @@ -890,6 +892,12 @@ sub lcov_geninfo(@) if (defined($opt_config_file)) { @param = (@param, "--config-file", $opt_config_file); } + foreach (@include_patterns) { + @param = (@param, "--include", $_); + } + foreach (@exclude_patterns) { + @param = (@param, "--exclude", $_); + } system(@param) and exit($? >> 8); } @@ -1456,7 +1464,7 @@ sub info(@) if (!$quiet) { # Print info string - if ($to_file) + if (!$data_stdout) { printf(@_) } @@ -1494,188 +1502,23 @@ sub create_temp_dir() return $dir; } - -# -# br_taken_to_num(taken) -# -# Convert a branch taken value .info format to number format. -# - -sub br_taken_to_num($) -{ - my ($taken) = @_; - - return 0 if ($taken eq '-'); - return $taken + 1; -} - - -# -# br_num_to_taken(taken) -# -# Convert a branch taken value in number format to .info format. -# - -sub br_num_to_taken($) -{ - my ($taken) = @_; - - return '-' if ($taken == 0); - return $taken - 1; -} - - -# -# br_taken_add(taken1, taken2) -# -# Return the result of taken1 + taken2 for 'branch taken' values. -# - -sub br_taken_add($$) -{ - my ($t1, $t2) = @_; - - return $t1 if (!defined($t2)); - return $t2 if (!defined($t1)); - return $t1 if ($t2 eq '-'); - return $t2 if ($t1 eq '-'); - return $t1 + $t2; -} - - -# -# br_taken_sub(taken1, taken2) -# -# Return the result of taken1 - taken2 for 'branch taken' values. Return 0 -# if the result would become negative. -# - -sub br_taken_sub($$) +sub compress_brcount($) { - my ($t1, $t2) = @_; - - return $t1 if (!defined($t2)); - return undef if (!defined($t1)); - return $t1 if ($t1 eq '-'); - return $t1 if ($t2 eq '-'); - return 0 if $t2 > $t1; - return $t1 - $t2; -} - - -# -# -# br_ivec_len(vector) -# -# Return the number of entries in the branch coverage vector. -# - -sub br_ivec_len($) -{ - my ($vec) = @_; - - return 0 if (!defined($vec)); - return (length($vec) * 8 / $BR_VEC_WIDTH) / $BR_VEC_ENTRIES; -} - - -# -# br_ivec_push(vector, block, branch, taken) -# -# Add an entry to the branch coverage vector. If an entry with the same -# branch ID already exists, add the corresponding taken values. -# - -sub br_ivec_push($$$$) -{ - my ($vec, $block, $branch, $taken) = @_; - my $offset; - my $num = br_ivec_len($vec); - my $i; - - $vec = "" if (!defined($vec)); - $block = $BR_VEC_MAX if $block < 0; - - # Check if branch already exists in vector - for ($i = 0; $i < $num; $i++) { - my ($v_block, $v_branch, $v_taken) = br_ivec_get($vec, $i); - $v_block = $BR_VEC_MAX if $v_block < 0; - - next if ($v_block != $block || $v_branch != $branch); - - # Add taken counts - $taken = br_taken_add($taken, $v_taken); - last; - } - - $offset = $i * $BR_VEC_ENTRIES; - $taken = br_taken_to_num($taken); - - # Add to vector - vec($vec, $offset + $BR_BLOCK, $BR_VEC_WIDTH) = $block; - vec($vec, $offset + $BR_BRANCH, $BR_VEC_WIDTH) = $branch; - vec($vec, $offset + $BR_TAKEN, $BR_VEC_WIDTH) = $taken; - - return $vec; -} - - -# -# br_ivec_get(vector, number) -# -# Return an entry from the branch coverage vector. -# + my ($brcount) = @_; + my $db; -sub br_ivec_get($$) -{ - my ($vec, $num) = @_; - my $block; - my $branch; - my $taken; - my $offset = $num * $BR_VEC_ENTRIES; - - # Retrieve data from vector - $block = vec($vec, $offset + $BR_BLOCK, $BR_VEC_WIDTH); - $block = -1 if ($block == $BR_VEC_MAX); - $branch = vec($vec, $offset + $BR_BRANCH, $BR_VEC_WIDTH); - $taken = vec($vec, $offset + $BR_TAKEN, $BR_VEC_WIDTH); - - # Decode taken value from an integer - $taken = br_num_to_taken($taken); - - return ($block, $branch, $taken); + $db = brcount_to_db($brcount); + return db_to_brcount($db, $brcount); } - -# -# get_br_found_and_hit(brcount) -# -# Return (br_found, br_hit) for brcount -# - sub get_br_found_and_hit($) { my ($brcount) = @_; - my $line; - my $br_found = 0; - my $br_hit = 0; - - foreach $line (keys(%{$brcount})) { - my $brdata = $brcount->{$line}; - my $i; - my $num = br_ivec_len($brdata); - - for ($i = 0; $i < $num; $i++) { - my $taken; - - (undef, undef, $taken) = br_ivec_get($brdata, $i); + my $db; - $br_found++; - $br_hit++ if ($taken ne "-" && $taken > 0); - } - } + $db = brcount_to_db($brcount); - return ($br_found, $br_hit); + return brcount_db_get_found_and_hit($db); } @@ -1714,7 +1557,7 @@ sub get_br_found_and_hit($) # %sumbrcount : line number -> branch coverage data for all tests # %funcdata : function name -> line number # %checkdata : line number -> checksum of source code line -# $brdata : vector of items: block, branch, taken +# $brdata : text "block,branch,taken:..." # # Note that .info file sections referring to the same file and test name # will automatically be combined by adding all execution counts. @@ -1918,17 +1761,13 @@ sub read_info_file($) ($1, $2, $3, $4); last if (!$br_coverage); - $sumbrcount->{$line} = - br_ivec_push($sumbrcount->{$line}, - $block, $branch, $taken); + $sumbrcount->{$line} .= + "$block,$branch,$taken:"; # Add test-specific counts if (defined($testname)) { - $testbrcount->{$line} = - br_ivec_push( - $testbrcount->{$line}, - $block, $branch, - $taken); + $testbrcount->{$line} .= + "$block,$branch,$taken:"; } last; }; @@ -2013,12 +1852,11 @@ sub read_info_file($) } $data->{"f_hit"} = $hitcount; - # Get found/hit values for branch data - { - my ($br_found, $br_hit) = get_br_found_and_hit($sumbrcount); - - $data->{"b_found"} = $br_found; - $data->{"b_hit"} = $br_hit; + # Combine branch data for the same branches + (undef, $data->{"b_found"}, $data->{"b_hit"}) = + compress_brcount($sumbrcount); + foreach $testname (keys(%{$testbrdata})) { + compress_brcount($testbrdata->{$testname}); } } @@ -2316,18 +2154,23 @@ sub brcount_to_db($) { my ($brcount) = @_; my $line; - my $db; + my $db = {}; - # Add branches from first count to database + # Add branches to database foreach $line (keys(%{$brcount})) { my $brdata = $brcount->{$line}; - my $i; - my $num = br_ivec_len($brdata); - for ($i = 0; $i < $num; $i++) { - my ($block, $branch, $taken) = br_ivec_get($brdata, $i); + foreach my $entry (split(/:/, $brdata)) { + my ($block, $branch, $taken) = split(/,/, $entry); + my $old = $db->{$line}->{$block}->{$branch}; + + if (!defined($old) || $old eq "-") { + $old = $taken; + } elsif ($taken ne "-") { + $old += $taken; + } - $db->{$line}->{$block}->{$branch} = $taken; + $db->{$line}->{$block}->{$branch} = $old; } } @@ -2336,16 +2179,16 @@ sub brcount_to_db($) # -# db_to_brcount(db) +# db_to_brcount(db[, brcount]) # -# Convert branch coverage data back to brcount format. +# Convert branch coverage data back to brcount format. If brcount is specified, +# the converted data is directly inserted in brcount. # -sub db_to_brcount($) +sub db_to_brcount($;$) { - my ($db) = @_; + my ($db, $brcount) = @_; my $line; - my $brcount = {}; my $br_found = 0; my $br_hit = 0; @@ -2364,8 +2207,7 @@ sub db_to_brcount($) $br_found++; $br_hit++ if ($taken ne "-" && $taken > 0); - $brdata = br_ivec_push($brdata, $block, - $branch, $taken); + $brdata .= "$block,$branch,$taken:"; } } $brcount->{$line} = $brdata; @@ -2375,50 +2217,92 @@ sub db_to_brcount($) } -# combine_brcount(brcount1, brcount2, type) # -# If add is BR_ADD, add branch coverage data and return list (brcount_added, -# br_found, br_hit). If add is BR_SUB, subtract the taken values of brcount2 -# from brcount1 and return (brcount_sub, br_found, br_hit). +# brcount_db_combine(db1, db2, op) +# +# db1 := db1 op db2, where +# db1, db2: brcount data as returned by brcount_to_db +# op: one of $BR_ADD and BR_SUB +# +sub brcount_db_combine($$$) +{ + my ($db1, $db2, $op) = @_; + + foreach my $line (keys(%{$db2})) { + my $ldata = $db2->{$line}; + + foreach my $block (keys(%{$ldata})) { + my $bdata = $ldata->{$block}; + + foreach my $branch (keys(%{$bdata})) { + my $taken = $bdata->{$branch}; + my $new = $db1->{$line}->{$block}->{$branch}; + + if (!defined($new) || $new eq "-") { + $new = $taken; + } elsif ($taken ne "-") { + if ($op == $BR_ADD) { + $new += $taken; + } elsif ($op == $BR_SUB) { + $new -= $taken; + $new = 0 if ($new < 0); + } + } + + $db1->{$line}->{$block}->{$branch} = $new; + } + } + } +} + + +# +# brcount_db_get_found_and_hit(db) +# +# Return (br_found, br_hit) for db. # -sub combine_brcount($$$) +sub brcount_db_get_found_and_hit($) { - my ($brcount1, $brcount2, $type) = @_; - my $line; - my $block; - my $branch; - my $taken; - my $db; - my $br_found = 0; - my $br_hit = 0; - my $result; + my ($db) = @_; + my ($br_found , $br_hit) = (0, 0); - # Convert branches from first count to database - $db = brcount_to_db($brcount1); - # Combine values from database and second count - foreach $line (keys(%{$brcount2})) { - my $brdata = $brcount2->{$line}; - my $num = br_ivec_len($brdata); - my $i; + foreach my $line (keys(%{$db})) { + my $ldata = $db->{$line}; - for ($i = 0; $i < $num; $i++) { - ($block, $branch, $taken) = br_ivec_get($brdata, $i); - my $new_taken = $db->{$line}->{$block}->{$branch}; + foreach my $block (keys(%{$ldata})) { + my $bdata = $ldata->{$block}; - if ($type == $BR_ADD) { - $new_taken = br_taken_add($new_taken, $taken); - } elsif ($type == $BR_SUB) { - $new_taken = br_taken_sub($new_taken, $taken); + foreach my $branch (keys(%{$bdata})) { + my $taken = $bdata->{$branch}; + + $br_found++; + $br_hit++ if ($taken ne "-" && $taken > 0); } - $db->{$line}->{$block}->{$branch} = $new_taken - if (defined($new_taken)); } } - # Convert database back to brcount format - ($result, $br_found, $br_hit) = db_to_brcount($db); - return ($result, $br_found, $br_hit); + return ($br_found, $br_hit); +} + + +# combine_brcount(brcount1, brcount2, type, inplace) +# +# If add is BR_ADD, add branch coverage data and return list brcount_added. +# If add is BR_SUB, subtract the taken values of brcount2 from brcount1 and +# return brcount_sub. If inplace is set, the result is inserted into brcount1. +# + +sub combine_brcount($$$;$) +{ + my ($brcount1, $brcount2, $type, $inplace) = @_; + my ($db1, $db2); + + $db1 = brcount_to_db($brcount1); + $db2 = brcount_to_db($brcount2); + brcount_db_combine($db1, $db2, $type); + + return db_to_brcount($db1, $inplace ? $brcount1 : undef); } @@ -2645,7 +2529,7 @@ sub add_traces() } # Write combined data - if ($to_file) + if (!$data_stdout) { info("Writing data to $output_filename\n"); open(INFO_HANDLE, ">", $output_filename) @@ -2750,14 +2634,11 @@ sub write_info_file(*$) foreach $line (sort({$a <=> $b} keys(%{$testbrcount}))) { my $brdata = $testbrcount->{$line}; - my $num = br_ivec_len($brdata); - my $i; - for ($i = 0; $i < $num; $i++) { + foreach my $brentry (split(/:/, $brdata)) { my ($block, $branch, $taken) = - br_ivec_get($brdata, $i); + split(/,/, $brentry); - $block = $BR_VEC_MAX if ($block < 0); print(INFO_HANDLE "BRDA:$line,$block,". "$branch,$taken\n"); $br_found++; @@ -2875,7 +2756,7 @@ sub extract() } # Write extracted data - if ($to_file) + if (!$data_stdout) { info("Extracted $extracted files\n"); info("Writing data to $output_filename\n"); @@ -2931,7 +2812,7 @@ sub remove() } # Write data - if ($to_file) + if (!$data_stdout) { info("Deleted $removed files\n"); info("Writing data to $output_filename\n"); @@ -3997,10 +3878,10 @@ sub diff() $testfncdata->{$testname.",diff"}); delete($testfncdata->{$testname.",diff"}); # Add branch counts - ($testbrdata->{$testname}) = combine_brcount( + combine_brcount( $testbrdata->{$testname}, $testbrdata->{$testname.",diff"}, - $BR_ADD); + $BR_ADD, 1); delete($testbrdata->{$testname.",diff"}); } # Move test data to new testname @@ -4065,7 +3946,7 @@ sub diff() "unchanged.\n"); # Write data - if ($to_file) + if (!$data_stdout) { info("Writing data to $output_filename\n"); open(INFO_HANDLE, ">", $output_filename) diff --git a/lcov-1.13/bin/updateversion.pl b/lcov-1.14/bin/updateversion.pl similarity index 99% rename from lcov-1.13/bin/updateversion.pl rename to lcov-1.14/bin/updateversion.pl index 02d2ec2..19db81e 100755 --- a/lcov-1.13/bin/updateversion.pl +++ b/lcov-1.14/bin/updateversion.pl @@ -1,6 +1,7 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl use strict; +use warnings; use File::Basename;