${lineno_heading}${branch_heading}${line_heading} ${source_heading}
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)
#
# Group branches that belong to the same basic block.
#
# Returns: [block1, block2, ...]
# block: [branch1, branch2, ...]
# branch: [block_num, branch_num, taken_count, text_length, open, close]
#
sub get_branch_blocks($)
{
my ($brdata) = @_;
my $last_block_num;
my $block = [];
my @blocks;
return () if (!defined($brdata));
# Group branches
foreach my $entry (split(/:/, $brdata)) {
my ($block_num, $branch, $taken) = split(/,/, $entry);
my $br;
if (defined($last_block_num) && $block_num != $last_block_num) {
push(@blocks, $block);
$block = [];
}
$br = [$block_num, $branch, $taken, 3, 0, 0];
push(@{$block}, $br);
$last_block_num = $block_num;
}
push(@blocks, $block) if (scalar(@{$block}) > 0);
# Add braces to first and last branch in group
foreach $block (@blocks) {
$block->[0]->[$BR_OPEN] = 1;
$block->[0]->[$BR_LEN]++;
$block->[scalar(@{$block}) - 1]->[$BR_CLOSE] = 1;
$block->[scalar(@{$block}) - 1]->[$BR_LEN]++;
}
return sort(cmp_blocks @blocks);
}
#
# get_block_len(block)
#
# Calculate total text length of all branches in a block of branches.
#
sub get_block_len($)
{
my ($block) = @_;
my $len = 0;
my $branch;
foreach $branch (@{$block}) {
$len += $branch->[$BR_LEN];
}
return $len;
}
#
# get_branch_html(brdata)
#
# Return a list of HTML lines which represent the specified branch coverage
# data in source code view.
#
sub get_branch_html($)
{
my ($brdata) = @_;
my @blocks = get_branch_blocks($brdata);
my $block;
my $branch;
my $line_len = 0;
my $line = []; # [branch2|" ", branch|" ", ...]
my @lines; # [line1, line2, ...]
my @result;
# Distribute blocks to lines
foreach $block (@blocks) {
my $block_len = get_block_len($block);
# Does this block fit into the current line?
if ($line_len + $block_len <= $br_field_width) {
# Add it
$line_len += $block_len;
push(@{$line}, @{$block});
next;
} elsif ($block_len <= $br_field_width) {
# It would fit if the line was empty - add it to new
# line
push(@lines, $line);
$line_len = $block_len;
$line = [ @{$block} ];
next;
}
# Split the block into several lines
foreach $branch (@{$block}) {
if ($line_len + $branch->[$BR_LEN] >= $br_field_width) {
# Start a new line
if (($line_len + 1 <= $br_field_width) &&
scalar(@{$line}) > 0 &&
!$line->[scalar(@$line) - 1]->[$BR_CLOSE]) {
# Try to align branch symbols to be in
# one # row
push(@{$line}, " ");
}
push(@lines, $line);
$line_len = 0;
$line = [];
}
push(@{$line}, $branch);
$line_len += $branch->[$BR_LEN];
}
}
push(@lines, $line);
# Convert to HTML
foreach $line (@lines) {
my $current = "";
my $current_len = 0;
foreach $branch (@$line) {
# Skip alignment space
if ($branch eq " ") {
$current .= " ";
$current_len++;
next;
}
my ($block_num, $br_num, $taken, $len, $open, $close) =
@{$branch};
my $class;
my $title;
my $text;
if ($taken eq '-') {
$class = "branchNoExec";
$text = " # ";
$title = "Branch $br_num was not executed";
} elsif ($taken == 0) {
$class = "branchNoCov";
$text = " - ";
$title = "Branch $br_num was not taken";
} else {
$class = "branchCov";
$text = " + ";
$title = "Branch $br_num was taken $taken ".
"time";
$title .= "s" if ($taken > 1);
}
$current .= "[" if ($open);
$current .= "";
$current .= $text."";
$current .= "]" if ($close);
$current_len += $len;
}
# Right-align result text
if ($current_len < $br_field_width) {
$current = (" "x($br_field_width - $current_len)).
$current;
}
push(@result, $current);
}
return @result;
}
#
# format_count(count, width)
#
# Return a right-aligned representation of count that fits in width characters.
#
sub format_count($$)
{
my ($count, $width) = @_;
my $result;
my $exp;
$result = sprintf("%*.0f", $width, $count);
while (length($result) > $width) {
last if ($count < 10);
$exp++;
$count = int($count/10);
$result = sprintf("%*s", $width, ">$count*10^$exp");
}
return $result;
}
#
# write_source_line(filehandle, line_num, source, hit_count, converted,
# brdata)
#
# Write formatted source code line. Return a line in a format as needed
# by gen_png()
#
sub write_source_line(*$$$$$)
{
my ($handle, $line, $source, $count, $converted, $brdata) = @_;
my $source_format;
my $count_format;
my $result;
my $anchor_start = "";
my $anchor_end = "";
my $count_field_width = $line_field_width - 1;
my @br_html;
my $html;
# Get branch HTML data for this line
@br_html = get_branch_html($brdata) if ($br_coverage);
if (!defined($count)) {
$result = "";
$source_format = "";
$count_format = " "x$count_field_width;
}
elsif ($count == 0) {
$result = $count;
$source_format = '';
$count_format = format_count($count, $count_field_width);
}
elsif ($converted && defined($highlight)) {
$result = "*".$count;
$source_format = '';
$count_format = format_count($count, $count_field_width);
}
else {
$result = $count;
$source_format = '';
$count_format = format_count($count, $count_field_width);
}
$result .= ":".$source;
# Write out a line number navigation anchor every $nav_resolution
# lines if necessary
$anchor_start = "";
$anchor_end = "";
# *************************************************************
$html = $anchor_start;
$html .= "".sprintf("%8d", $line)." ";
$html .= shift(@br_html).":" if ($br_coverage);
$html .= "$source_format$count_format : ";
$html .= escape_html($source);
$html .= "" if ($source_format);
$html .= $anchor_end."\n";
write_html($handle, $html);
if ($br_coverage) {
# Add lines for overlong branch information
foreach (@br_html) {
write_html($handle, "".
" $_\n");
}
}
# *************************************************************
return($result);
}
#
# write_source_epilog(filehandle)
#
# Write end of source code table.
#
sub write_source_epilog(*)
{
# *************************************************************
write_html($_[0], <
|