Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(610)

Side by Side Diff: third_party/lcov/bin/genhtml

Issue 23189008: Upgrades lcov to 1.10, removes lcov-1.9 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Re-adds UNKNOWN suppression Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/lcov/bin/gendesc ('k') | third_party/lcov/bin/geninfo » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/perl -w 1 #!/usr/bin/perl -w
2 # 2 #
3 # Copyright (c) International Business Machines Corp., 2002 3 # Copyright (c) International Business Machines Corp., 2002,2012
4 # 4 #
5 # This program is free software; you can redistribute it and/or modify 5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by 6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or (at 7 # the Free Software Foundation; either version 2 of the License, or (at
8 # your option) any later version. 8 # your option) any later version.
9 # 9 #
10 # This program is distributed in the hope that it will be useful, but 10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of 11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details. 13 # General Public License for more details.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 # 65 #
66 66
67 use strict; 67 use strict;
68 use File::Basename; 68 use File::Basename;
69 use Getopt::Long; 69 use Getopt::Long;
70 use Digest::MD5 qw(md5_base64); 70 use Digest::MD5 qw(md5_base64);
71 71
72 72
73 # Global constants 73 # Global constants
74 our $title = "LCOV - code coverage report"; 74 our $title = "LCOV - code coverage report";
75 our $lcov_version» = "LCOV version 1.7"; 75 our $lcov_version» = 'LCOV version 1.10';
76 our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; 76 our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php";
77 our $tool_name = basename($0); 77 our $tool_name = basename($0);
78 78
79 # Specify coverage rate limits (in %) for classifying file entries 79 # Specify coverage rate limits (in %) for classifying file entries
80 # HI: $hi_limit <= rate <= 100 graph color: green 80 # HI: $hi_limit <= rate <= 100 graph color: green
81 # MED: $med_limit <= rate < $hi_limit graph color: orange 81 # MED: $med_limit <= rate < $hi_limit graph color: orange
82 # LO: 0 <= rate < $med_limit graph color: red 82 # LO: 0 <= rate < $med_limit graph color: red
83 83
84 # For line coverage 84 # For line coverage/all coverage types if not specified
85 our $hi_limit» = 50; 85 our $hi_limit = 90;
86 our $med_limit» = 15; 86 our $med_limit = 75;
87 87
88 # For function coverage 88 # For function coverage
89 our $fn_hi_limit» = 90; 89 our $fn_hi_limit;
90 our $fn_med_limit» = 75; 90 our $fn_med_limit;
91
92 # For branch coverage
93 our $br_hi_limit;
94 our $br_med_limit;
91 95
92 # Width of overview image 96 # Width of overview image
93 our $overview_width = 80; 97 our $overview_width = 80;
94 98
95 # Resolution of overview navigation: this number specifies the maximum 99 # Resolution of overview navigation: this number specifies the maximum
96 # difference in lines between the position a user selected from the overview 100 # difference in lines between the position a user selected from the overview
97 # and the position the source code window is scrolled to. 101 # and the position the source code window is scrolled to.
98 our $nav_resolution = 4; 102 our $nav_resolution = 4;
99 103
100 # Clicking a line in the overview image should show the source code view at 104 # Clicking a line in the overview image should show the source code view at
101 # a position a bit further up so that the requested line is not the first 105 # a position a bit further up so that the requested line is not the first
102 # line in the window. This number specifies that offset in lines. 106 # line in the window. This number specifies that offset in lines.
103 our $nav_offset = 10; 107 our $nav_offset = 10;
104 108
105 # Clicking on a function name should show the source code at a position a 109 # Clicking on a function name should show the source code at a position a
106 # few lines before the first line of code of that function. This number 110 # few lines before the first line of code of that function. This number
107 # specifies that offset in lines. 111 # specifies that offset in lines.
108 our $func_offset = 2; 112 our $func_offset = 2;
109 113
110 our $overview_title = "directory"; 114 our $overview_title = "top level";
115
116 # Width for line coverage information in the source code view
117 our $line_field_width = 12;
118
119 # Width for branch coverage information in the source code view
120 our $br_field_width = 16;
121
122 # Internal Constants
123
124 # Header types
125 our $HDR_DIR» » = 0;
126 our $HDR_FILE» » = 1;
127 our $HDR_SOURCE»» = 2;
128 our $HDR_TESTDESC» = 3;
129 our $HDR_FUNC» » = 4;
130
131 # Sort types
132 our $SORT_FILE» » = 0;
133 our $SORT_LINE» » = 1;
134 our $SORT_FUNC» » = 2;
135 our $SORT_BRANCH» = 3;
136
137 # Fileview heading types
138 our $HEAD_NO_DETAIL» = 1;
139 our $HEAD_DETAIL_HIDDEN»= 2;
140 our $HEAD_DETAIL_SHOWN» = 3;
141
142 # Offsets for storing branch coverage data in vectors
143 our $BR_BLOCK» » = 0;
144 our $BR_BRANCH» » = 1;
145 our $BR_TAKEN» » = 2;
146 our $BR_VEC_ENTRIES» = 3;
147 our $BR_VEC_WIDTH» = 32;
148
149 # Additional offsets used when converting branch coverage data to HTML
150 our $BR_LEN» = 3;
151 our $BR_OPEN» = 4;
152 our $BR_CLOSE» = 5;
153
154 # Branch data combination types
155 our $BR_SUB = 0;
156 our $BR_ADD = 1;
157
158 # Error classes which users may specify to ignore during processing
159 our $ERROR_SOURCE» = 0;
160 our %ERROR_ID = (
161 » "source" => $ERROR_SOURCE,
162 );
111 163
112 # Data related prototypes 164 # Data related prototypes
113 sub print_usage(*); 165 sub print_usage(*);
114 sub gen_html(); 166 sub gen_html();
115 sub html_create($$); 167 sub html_create($$);
116 sub process_dir($); 168 sub process_dir($);
117 sub process_file($$$); 169 sub process_file($$$);
118 sub info(@); 170 sub info(@);
119 sub read_info_file($); 171 sub read_info_file($);
120 sub get_info_entry($); 172 sub get_info_entry($);
121 sub set_info_entry($$$$$$$;$$$$); 173 sub set_info_entry($$$$$$$$$;$$$$$$);
122 sub get_prefix(@); 174 sub get_prefix($@);
123 sub shorten_prefix($); 175 sub shorten_prefix($);
124 sub get_dir_list(@); 176 sub get_dir_list(@);
125 sub get_relative_base_path($); 177 sub get_relative_base_path($);
126 sub read_testfile($); 178 sub read_testfile($);
127 sub get_date_string(); 179 sub get_date_string();
128 sub split_filename($);
129 sub create_sub_dir($); 180 sub create_sub_dir($);
130 sub subtract_counts($$); 181 sub subtract_counts($$);
131 sub add_counts($$); 182 sub add_counts($$);
132 sub apply_baseline($$); 183 sub apply_baseline($$);
133 sub remove_unused_descriptions(); 184 sub remove_unused_descriptions();
134 sub get_found_and_hit($); 185 sub get_found_and_hit($);
135 sub get_affecting_tests($$); 186 sub get_affecting_tests($$$);
136 sub combine_info_files($$); 187 sub combine_info_files($$);
137 sub merge_checksums($$$); 188 sub merge_checksums($$$);
138 sub combine_info_entries($$$); 189 sub combine_info_entries($$$);
139 sub apply_prefix($$); 190 sub apply_prefix($$);
140 sub system_no_output($@); 191 sub system_no_output($@);
141 sub read_config($); 192 sub read_config($);
142 sub apply_config($); 193 sub apply_config($);
143 sub get_html_prolog($); 194 sub get_html_prolog($);
144 sub get_html_epilog($); 195 sub get_html_epilog($);
196 sub write_dir_page($$$$$$$$$$$$$$$$$);
197 sub classify_rate($$$$);
198 sub br_taken_add($$);
199 sub br_taken_sub($$);
200 sub br_ivec_len($);
201 sub br_ivec_get($$);
202 sub br_ivec_push($$$$);
203 sub combine_brcount($$$);
204 sub get_br_found_and_hit($);
205 sub warn_handler($);
206 sub die_handler($);
207 sub parse_ignore_errors(@);
208 sub rate($$;$$$);
145 209
146 210
147 # HTML related prototypes 211 # HTML related prototypes
148 sub escape_html($); 212 sub escape_html($);
149 sub get_bar_graph_code($$$); 213 sub get_bar_graph_code($$$);
150 214
151 sub write_png_files(); 215 sub write_png_files();
152 sub write_htaccess_file(); 216 sub write_htaccess_file();
153 sub write_css_file(); 217 sub write_css_file();
154 sub write_description_file($$$$$); 218 sub write_description_file($$$$$$$);
155 sub write_function_rable(*$$$); 219 sub write_function_table(*$$$$$$$$$$);
156 220
157 sub write_html(*$); 221 sub write_html(*$);
158 sub write_html_prolog(*$$); 222 sub write_html_prolog(*$$);
159 sub write_html_epilog(*$;$); 223 sub write_html_epilog(*$;$);
160 224
161 sub write_header(*$$$$$$$$); 225 sub write_header(*$$$$$$$$$$);
162 sub write_header_prolog(*$); 226 sub write_header_prolog(*$);
163 sub write_header_line(*$@); 227 sub write_header_line(*@);
164 sub write_header_epilog(*$); 228 sub write_header_epilog(*$);
165 229
166 sub write_file_table(*$$$$$$); 230 sub write_file_table(*$$$$$$$);
167 sub write_file_table_prolog(*$$$); 231 sub write_file_table_prolog(*$@);
168 sub write_file_table_entry(*$$$$$$$); 232 sub write_file_table_entry(*$$$@);
169 sub write_file_table_detail_heading(*$$$); 233 sub write_file_table_detail_entry(*$@);
170 sub write_file_table_detail_entry(*$$$$$);
171 sub write_file_table_epilog(*); 234 sub write_file_table_epilog(*);
172 235
173 sub write_test_table_prolog(*$); 236 sub write_test_table_prolog(*$);
174 sub write_test_table_entry(*$$); 237 sub write_test_table_entry(*$$);
175 sub write_test_table_epilog(*); 238 sub write_test_table_epilog(*);
176 239
177 sub write_source($$$$$$); 240 sub write_source($$$$$$$);
178 sub write_source_prolog(*); 241 sub write_source_prolog(*);
179 sub write_source_line(*$$$$$); 242 sub write_source_line(*$$$$$$);
180 sub write_source_epilog(*); 243 sub write_source_epilog(*);
181 244
182 sub write_frameset(*$$$); 245 sub write_frameset(*$$$);
183 sub write_overview_line(*$$$); 246 sub write_overview_line(*$$$);
184 sub write_overview(*$$$$); 247 sub write_overview(*$$$$);
185 248
186 # External prototype (defined in genpng) 249 # External prototype (defined in genpng)
187 sub gen_png($$$@); 250 sub gen_png($$$@);
188 251
189 252
190 # Global variables & initialization 253 # Global variables & initialization
191 our %info_data; # Hash containing all data from .info file 254 our %info_data; # Hash containing all data from .info file
192 our $dir_prefix; # Prefix to remove from all sub directories 255 our $dir_prefix; # Prefix to remove from all sub directories
193 our %test_description; # Hash containing test descriptions if available 256 our %test_description; # Hash containing test descriptions if available
194 our $date = get_date_string(); 257 our $date = get_date_string();
195 258
196 our @info_filenames; # List of .info files to use as data source 259 our @info_filenames; # List of .info files to use as data source
197 our $test_title; # Title for output as written to each page header 260 our $test_title; # Title for output as written to each page header
198 our $output_directory; # Name of directory in which to store output 261 our $output_directory; # Name of directory in which to store output
199 our $base_filename; # Optional name of file containing baseline data 262 our $base_filename; # Optional name of file containing baseline data
200 our $desc_filename; # Name of file containing test descriptions 263 our $desc_filename; # Name of file containing test descriptions
201 our $css_filename; # Optional name of external stylesheet file to use 264 our $css_filename; # Optional name of external stylesheet file to use
202 our $quiet; # If set, suppress information messages 265 our $quiet; # If set, suppress information messages
203 our $help; # Help option flag 266 our $help; # Help option flag
204 our $version; # Version option flag 267 our $version; # Version option flag
205 our $show_details; # If set, generate detailed directory view 268 our $show_details; # If set, generate detailed directory view
206 our $no_prefix; # If set, do not remove filename prefix 269 our $no_prefix; # If set, do not remove filename prefix
207 our $func_coverage = 1;»# If set, generate function coverage statistics 270 our $func_coverage;» # If set, generate function coverage statistics
208 our $no_func_coverage; # Disable func_coverage 271 our $no_func_coverage; # Disable func_coverage
272 our $br_coverage; # If set, generate branch coverage statistics
273 our $no_br_coverage; # Disable br_coverage
209 our $sort = 1; # If set, provide directory listings with sorted entries 274 our $sort = 1; # If set, provide directory listings with sorted entries
210 our $no_sort; # Disable sort 275 our $no_sort; # Disable sort
211 our $frames; # If set, use frames for source code view 276 our $frames; # If set, use frames for source code view
212 our $keep_descriptions; # If set, do not remove unused test case descriptions 277 our $keep_descriptions; # If set, do not remove unused test case descriptions
213 our $no_sourceview; # If set, do not create a source code view for each file 278 our $no_sourceview; # If set, do not create a source code view for each file
214 our $highlight; # If set, highlight lines covered by converted data only 279 our $highlight; # If set, highlight lines covered by converted data only
215 our $legend; # If set, include legend in output 280 our $legend; # If set, include legend in output
216 our $tab_size = 8; # Number of spaces to use in place of tab 281 our $tab_size = 8; # Number of spaces to use in place of tab
217 our $config; # Configuration file contents 282 our $config; # Configuration file contents
218 our $html_prolog_file; # Custom HTML prolog file (up to and including <body>) 283 our $html_prolog_file; # Custom HTML prolog file (up to and including <body>)
219 our $html_epilog_file; # Custom HTML epilog file (from </body> onwards) 284 our $html_epilog_file; # Custom HTML epilog file (from </body> onwards)
220 our $html_prolog; # Actual HTML prolog 285 our $html_prolog; # Actual HTML prolog
221 our $html_epilog; # Actual HTML epilog 286 our $html_epilog; # Actual HTML epilog
222 our $html_ext = "html"; # Extension for generated HTML files 287 our $html_ext = "html"; # Extension for generated HTML files
223 our $html_gzip = 0; # Compress with gzip 288 our $html_gzip = 0; # Compress with gzip
289 our $demangle_cpp = 0; # Demangle C++ function names
290 our @opt_ignore_errors; # Ignore certain error classes during processing
291 our @ignore;
292 our $opt_config_file; # User-specified configuration file location
293 our %opt_rc;
294 our $charset = "UTF-8"; # Default charset for HTML pages
224 our @fileview_sortlist; 295 our @fileview_sortlist;
225 our @fileview_sortname = ("", "-sort-l", "-sort-f"); 296 our @fileview_sortname = ("", "-sort-l", "-sort-f", "-sort-b");
226 our @funcview_sortlist; 297 our @funcview_sortlist;
227 our @rate_name = ("Lo", "Med", "Hi"); 298 our @rate_name = ("Lo", "Med", "Hi");
228 our @rate_png = ("ruby.png", "amber.png", "emerald.png"); 299 our @rate_png = ("ruby.png", "amber.png", "emerald.png");
300 our $lcov_func_coverage = 1;
301 our $lcov_branch_coverage = 0;
229 302
230 our $cwd = `pwd`; # Current working directory 303 our $cwd = `pwd`; # Current working directory
231 chomp($cwd); 304 chomp($cwd);
232 our $tool_dir = dirname($0); # Directory where genhtml tool is installed 305 our $tool_dir = dirname($0); # Directory where genhtml tool is installed
233 306
234 307
235 # 308 #
236 # Code entry point 309 # Code entry point
237 # 310 #
238 311
239 $SIG{__WARN__} = \&warn_handler; 312 $SIG{__WARN__} = \&warn_handler;
240 $SIG{__DIE__} = \&die_handler; 313 $SIG{__DIE__} = \&die_handler;
241 314
315 # Prettify version string
316 $lcov_version =~ s/\$\s*Revision\s*:?\s*(\S+)\s*\$/$1/;
317
242 # Add current working directory if $tool_dir is not already an absolute path 318 # Add current working directory if $tool_dir is not already an absolute path
243 if (! ($tool_dir =~ /^\/(.*)$/)) 319 if (! ($tool_dir =~ /^\/(.*)$/))
244 { 320 {
245 $tool_dir = "$cwd/$tool_dir"; 321 $tool_dir = "$cwd/$tool_dir";
246 } 322 }
247 323
324 # Check command line for a configuration file name
325 Getopt::Long::Configure("pass_through", "no_auto_abbrev");
326 GetOptions("config-file=s" => \$opt_config_file,
327 "rc=s%" => \%opt_rc);
328 Getopt::Long::Configure("default");
329
248 # Read configuration file if available 330 # Read configuration file if available
249 if (-r $ENV{"HOME"}."/.lcovrc") 331 if (defined($opt_config_file)) {
332 » $config = read_config($opt_config_file);
333 } elsif (defined($ENV{"HOME"}) && (-r $ENV{"HOME"}."/.lcovrc"))
250 { 334 {
251 $config = read_config($ENV{"HOME"}."/.lcovrc"); 335 $config = read_config($ENV{"HOME"}."/.lcovrc");
252 } 336 }
253 elsif (-r "/etc/lcovrc") 337 elsif (-r "/etc/lcovrc")
254 { 338 {
255 $config = read_config("/etc/lcovrc"); 339 $config = read_config("/etc/lcovrc");
256 } 340 }
257 341
258 if ($config) 342 if ($config || %opt_rc)
259 { 343 {
260 » # Copy configuration file values to variables 344 » # Copy configuration file and --rc values to variables
261 apply_config({ 345 apply_config({
262 "genhtml_css_file" => \$css_filename, 346 "genhtml_css_file" => \$css_filename,
263 "genhtml_hi_limit" => \$hi_limit, 347 "genhtml_hi_limit" => \$hi_limit,
264 "genhtml_med_limit" => \$med_limit, 348 "genhtml_med_limit" => \$med_limit,
349 "genhtml_line_field_width" => \$line_field_width,
265 "genhtml_overview_width" => \$overview_width, 350 "genhtml_overview_width" => \$overview_width,
266 "genhtml_nav_resolution" => \$nav_resolution, 351 "genhtml_nav_resolution" => \$nav_resolution,
267 "genhtml_nav_offset" => \$nav_offset, 352 "genhtml_nav_offset" => \$nav_offset,
268 "genhtml_keep_descriptions" => \$keep_descriptions, 353 "genhtml_keep_descriptions" => \$keep_descriptions,
269 "genhtml_no_prefix" => \$no_prefix, 354 "genhtml_no_prefix" => \$no_prefix,
270 "genhtml_no_source" => \$no_sourceview, 355 "genhtml_no_source" => \$no_sourceview,
271 "genhtml_num_spaces" => \$tab_size, 356 "genhtml_num_spaces" => \$tab_size,
272 "genhtml_highlight" => \$highlight, 357 "genhtml_highlight" => \$highlight,
273 "genhtml_legend" => \$legend, 358 "genhtml_legend" => \$legend,
274 "genhtml_html_prolog" => \$html_prolog_file, 359 "genhtml_html_prolog" => \$html_prolog_file,
275 "genhtml_html_epilog" => \$html_epilog_file, 360 "genhtml_html_epilog" => \$html_epilog_file,
276 "genhtml_html_extension" => \$html_ext, 361 "genhtml_html_extension" => \$html_ext,
277 "genhtml_html_gzip" => \$html_gzip, 362 "genhtml_html_gzip" => \$html_gzip,
278 "genhtml_function_hi_limit" => \$fn_hi_limit, 363 "genhtml_function_hi_limit" => \$fn_hi_limit,
279 "genhtml_function_med_limit" => \$fn_med_limit, 364 "genhtml_function_med_limit" => \$fn_med_limit,
280 "genhtml_function_coverage" => \$func_coverage, 365 "genhtml_function_coverage" => \$func_coverage,
366 "genhtml_branch_hi_limit" => \$br_hi_limit,
367 "genhtml_branch_med_limit" => \$br_med_limit,
368 "genhtml_branch_coverage" => \$br_coverage,
369 "genhtml_branch_field_width" => \$br_field_width,
281 "genhtml_sort" => \$sort, 370 "genhtml_sort" => \$sort,
371 "genhtml_charset" => \$charset,
372 "lcov_function_coverage" => \$lcov_func_coverage,
373 "lcov_branch_coverage" => \$lcov_branch_coverage,
282 }); 374 });
283 } 375 }
284 376
377 # Copy related values if not specified
378 $fn_hi_limit = $hi_limit if (!defined($fn_hi_limit));
379 $fn_med_limit = $med_limit if (!defined($fn_med_limit));
380 $br_hi_limit = $hi_limit if (!defined($br_hi_limit));
381 $br_med_limit = $med_limit if (!defined($br_med_limit));
382 $func_coverage = $lcov_func_coverage if (!defined($func_coverage));
383 $br_coverage = $lcov_branch_coverage if (!defined($br_coverage));
384
285 # Parse command line options 385 # Parse command line options
286 if (!GetOptions("output-directory=s"» => \$output_directory, 386 if (!GetOptions("output-directory|o=s"» => \$output_directory,
287 » » "title=s"» » => \$test_title, 387 » » "title|t=s"» » => \$test_title,
288 » » "description-file=s"» => \$desc_filename, 388 » » "description-file|d=s"» => \$desc_filename,
289 » » "keep-descriptions"» => \$keep_descriptions, 389 » » "keep-descriptions|k"» => \$keep_descriptions,
290 » » "css-file=s"» » => \$css_filename, 390 » » "css-file|c=s"» » => \$css_filename,
291 » » "baseline-file=s"» => \$base_filename, 391 » » "baseline-file|b=s"» => \$base_filename,
292 » » "prefix=s"» » => \$dir_prefix, 392 » » "prefix|p=s"» » => \$dir_prefix,
293 "num-spaces=i" => \$tab_size, 393 "num-spaces=i" => \$tab_size,
294 "no-prefix" => \$no_prefix, 394 "no-prefix" => \$no_prefix,
295 "no-sourceview" => \$no_sourceview, 395 "no-sourceview" => \$no_sourceview,
296 » » "show-details"» » => \$show_details, 396 » » "show-details|s"» => \$show_details,
297 » » "frames"» » => \$frames, 397 » » "frames|f"» » => \$frames,
298 "highlight" => \$highlight, 398 "highlight" => \$highlight,
299 "legend" => \$legend, 399 "legend" => \$legend,
300 » » "quiet"»» » => \$quiet, 400 » » "quiet|q"» » => \$quiet,
301 "help|h|?" => \$help, 401 "help|h|?" => \$help,
302 » » "version"» » => \$version, 402 » » "version|v"» » => \$version,
303 "html-prolog=s" => \$html_prolog_file, 403 "html-prolog=s" => \$html_prolog_file,
304 "html-epilog=s" => \$html_epilog_file, 404 "html-epilog=s" => \$html_epilog_file,
305 "html-extension=s" => \$html_ext, 405 "html-extension=s" => \$html_ext,
306 "html-gzip" => \$html_gzip, 406 "html-gzip" => \$html_gzip,
307 "function-coverage" => \$func_coverage, 407 "function-coverage" => \$func_coverage,
308 "no-function-coverage" => \$no_func_coverage, 408 "no-function-coverage" => \$no_func_coverage,
409 "branch-coverage" => \$br_coverage,
410 "no-branch-coverage" => \$no_br_coverage,
309 "sort" => \$sort, 411 "sort" => \$sort,
310 "no-sort" => \$no_sort, 412 "no-sort" => \$no_sort,
413 "demangle-cpp" => \$demangle_cpp,
414 "ignore-errors=s" => \@opt_ignore_errors,
415 "config-file=s" => \$opt_config_file,
416 "rc=s%" => \%opt_rc,
311 )) 417 ))
312 { 418 {
313 print(STDERR "Use $tool_name --help to get usage information\n"); 419 print(STDERR "Use $tool_name --help to get usage information\n");
314 exit(1); 420 exit(1);
315 } else { 421 } else {
316 # Merge options 422 # Merge options
317 if ($no_func_coverage) { 423 if ($no_func_coverage) {
318 $func_coverage = 0; 424 $func_coverage = 0;
319 } 425 }
426 if ($no_br_coverage) {
427 $br_coverage = 0;
428 }
320 429
321 # Merge sort options 430 # Merge sort options
322 if ($no_sort) { 431 if ($no_sort) {
323 $sort = 0; 432 $sort = 0;
324 } 433 }
325 } 434 }
326 435
327 @info_filenames = @ARGV; 436 @info_filenames = @ARGV;
328 437
329 # Check for help option 438 # Check for help option
330 if ($help) 439 if ($help)
331 { 440 {
332 print_usage(*STDOUT); 441 print_usage(*STDOUT);
333 exit(0); 442 exit(0);
334 } 443 }
335 444
336 # Check for version option 445 # Check for version option
337 if ($version) 446 if ($version)
338 { 447 {
339 print("$tool_name: $lcov_version\n"); 448 print("$tool_name: $lcov_version\n");
340 exit(0); 449 exit(0);
341 } 450 }
342 451
452 # Determine which errors the user wants us to ignore
453 parse_ignore_errors(@opt_ignore_errors);
454
343 # Check for info filename 455 # Check for info filename
344 if (!@info_filenames) 456 if (!@info_filenames)
345 { 457 {
346 die("No filename specified\n". 458 die("No filename specified\n".
347 "Use $tool_name --help to get usage information\n"); 459 "Use $tool_name --help to get usage information\n");
348 } 460 }
349 461
350 # Generate a title if none is specified 462 # Generate a title if none is specified
351 if (!$test_title) 463 if (!$test_title)
352 { 464 {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 } 505 }
394 506
395 # Issue a warning if --no-prefix is enabled together with --prefix 507 # Issue a warning if --no-prefix is enabled together with --prefix
396 if ($no_prefix && defined($dir_prefix)) 508 if ($no_prefix && defined($dir_prefix))
397 { 509 {
398 warn("WARNING: option --prefix disabled because --no-prefix was ". 510 warn("WARNING: option --prefix disabled because --no-prefix was ".
399 "specified!\n"); 511 "specified!\n");
400 $dir_prefix = undef; 512 $dir_prefix = undef;
401 } 513 }
402 514
515 @fileview_sortlist = ($SORT_FILE);
516 @funcview_sortlist = ($SORT_FILE);
517
403 if ($sort) { 518 if ($sort) {
404 » @funcview_sortlist = (0, 1); 519 » push(@fileview_sortlist, $SORT_LINE);
405 » if ($func_coverage) { 520 » push(@fileview_sortlist, $SORT_FUNC) if ($func_coverage);
406 » » @fileview_sortlist = (0, 1, 2); 521 » push(@fileview_sortlist, $SORT_BRANCH) if ($br_coverage);
407 » } else { 522 » push(@funcview_sortlist, $SORT_LINE);
408 » » @fileview_sortlist = (0, 1);
409 » }
410 } else {
411 » @fileview_sortlist = (0);
412 » @funcview_sortlist = (0);
413 } 523 }
414 524
415 if ($frames) 525 if ($frames)
416 { 526 {
417 # Include genpng code needed for overview image generation 527 # Include genpng code needed for overview image generation
418 do("$tool_dir/genpng"); 528 do("$tool_dir/genpng");
419 } 529 }
420 530
531 # Ensure that the c++filt tool is available when using --demangle-cpp
532 if ($demangle_cpp)
533 {
534 if (system_no_output(3, "c++filt", "--version")) {
535 die("ERROR: could not find c++filt tool needed for ".
536 "--demangle-cpp\n");
537 }
538 }
539
421 # Make sure output_directory exists, create it if necessary 540 # Make sure output_directory exists, create it if necessary
422 if ($output_directory) 541 if ($output_directory)
423 { 542 {
424 stat($output_directory); 543 stat($output_directory);
425 544
426 if (! -e _) 545 if (! -e _)
427 { 546 {
428 » » system("mkdir", "-p", $output_directory) 547 » » create_sub_dir($output_directory);
429 » » » and die("ERROR: cannot create directory $_!\n");
430 } 548 }
431 } 549 }
432 550
433 # Do something 551 # Do something
434 gen_html(); 552 gen_html();
435 553
436 exit(0); 554 exit(0);
437 555
438 556
439 557
(...skipping 10 matching lines...) Expand all
450 print(HANDLE <<END_OF_USAGE); 568 print(HANDLE <<END_OF_USAGE);
451 Usage: $tool_name [OPTIONS] INFOFILE(S) 569 Usage: $tool_name [OPTIONS] INFOFILE(S)
452 570
453 Create HTML output for coverage data found in INFOFILE. Note that INFOFILE 571 Create HTML output for coverage data found in INFOFILE. Note that INFOFILE
454 may also be a list of filenames. 572 may also be a list of filenames.
455 573
456 Misc: 574 Misc:
457 -h, --help Print this help, then exit 575 -h, --help Print this help, then exit
458 -v, --version Print version number, then exit 576 -v, --version Print version number, then exit
459 -q, --quiet Do not print progress messages 577 -q, --quiet Do not print progress messages
578 --config-file FILENAME Specify configuration file location
579 --rc SETTING=VALUE Override configuration file setting
580 --ignore-errors ERRORS Continue after ERRORS (source)
460 581
461 Operation: 582 Operation:
462 -o, --output-directory OUTDIR Write HTML output to OUTDIR 583 -o, --output-directory OUTDIR Write HTML output to OUTDIR
463 -s, --show-details Generate detailed directory view 584 -s, --show-details Generate detailed directory view
464 -d, --description-file DESCFILE Read test case descriptions from DESCFILE 585 -d, --description-file DESCFILE Read test case descriptions from DESCFILE
465 -k, --keep-descriptions Do not remove unused test descriptions 586 -k, --keep-descriptions Do not remove unused test descriptions
466 -b, --baseline-file BASEFILE Use BASEFILE as baseline file 587 -b, --baseline-file BASEFILE Use BASEFILE as baseline file
467 -p, --prefix PREFIX Remove PREFIX from all directory names 588 -p, --prefix PREFIX Remove PREFIX from all directory names
468 --no-prefix Do not remove prefix from directory names 589 --no-prefix Do not remove prefix from directory names
469 --(no-)function-coverage Enable (disable) function coverage display 590 --(no-)function-coverage Enable (disable) function coverage display
591 --(no-)branch-coverage Enable (disable) branch coverage display
470 592
471 HTML output: 593 HTML output:
472 -f, --frames Use HTML frames for source code view 594 -f, --frames Use HTML frames for source code view
473 -t, --title TITLE Display TITLE in header of all pages 595 -t, --title TITLE Display TITLE in header of all pages
474 -c, --css-file CSSFILE Use external style sheet file CSSFILE 596 -c, --css-file CSSFILE Use external style sheet file CSSFILE
475 --no-source Do not create source code view 597 --no-source Do not create source code view
476 --num-spaces NUM Replace tabs with NUM spaces in source view 598 --num-spaces NUM Replace tabs with NUM spaces in source view
477 --highlight Highlight lines with converted-only data 599 --highlight Highlight lines with converted-only data
478 --legend Include color legend in HTML output 600 --legend Include color legend in HTML output
479 --html-prolog FILE Use FILE as HTML prolog for generated pages 601 --html-prolog FILE Use FILE as HTML prolog for generated pages
480 --html-epilog FILE Use FILE as HTML epilog for generated pages 602 --html-epilog FILE Use FILE as HTML epilog for generated pages
481 --html-extension EXT Use EXT as filename extension for pages 603 --html-extension EXT Use EXT as filename extension for pages
482 --html-gzip Use gzip to compress HTML 604 --html-gzip Use gzip to compress HTML
483 --(no-)sort Enable (disable) sorted coverage views 605 --(no-)sort Enable (disable) sorted coverage views
606 --demangle-cpp Demangle C++ function names
484 607
485 For more information see: $lcov_url 608 For more information see: $lcov_url
486 END_OF_USAGE 609 END_OF_USAGE
487 ; 610 ;
488 } 611 }
489 612
490 613
491 # 614 #
492 # get_rate(found, hit) 615 # get_rate(found, hit)
493 # 616 #
494 # Return a relative value for the specified found&hit values 617 # Return a relative value for the specified found&hit values
495 # which is used for sorting the corresponding entries in a 618 # which is used for sorting the corresponding entries in a
496 # file list. 619 # file list.
497 # 620 #
498 621
499 sub get_rate($$) 622 sub get_rate($$)
500 { 623 {
501 my ($found, $hit) = @_; 624 my ($found, $hit) = @_;
502 625
503 if ($found == 0) { 626 if ($found == 0) {
504 return 10000; 627 return 10000;
505 } 628 }
506 return int($hit * 1000 / $found) * 10 + 2 - (1 / $found); 629 return int($hit * 1000 / $found) * 10 + 2 - (1 / $found);
507 } 630 }
508 631
509 632
510 # 633 #
634 # get_overall_line(found, hit, name_singular, name_plural)
635 #
636 # Return a string containing overall information for the specified
637 # found/hit data.
638 #
639
640 sub get_overall_line($$$$)
641 {
642 my ($found, $hit, $name_sn, $name_pl) = @_;
643 my $name;
644
645 return "no data found" if (!defined($found) || $found == 0);
646 $name = ($found == 1) ? $name_sn : $name_pl;
647 return rate($hit, $found, "% ($hit of $found $name)");
648 }
649
650
651 #
652 # print_overall_rate(ln_do, ln_found, ln_hit, fn_do, fn_found, fn_hit, br_do
653 # br_found, br_hit)
654 #
655 # Print overall coverage rates for the specified coverage types.
656 #
657
658 sub print_overall_rate($$$$$$$$$)
659 {
660 my ($ln_do, $ln_found, $ln_hit, $fn_do, $fn_found, $fn_hit,
661 $br_do, $br_found, $br_hit) = @_;
662
663 info("Overall coverage rate:\n");
664 info(" lines......: %s\n",
665 get_overall_line($ln_found, $ln_hit, "line", "lines"))
666 if ($ln_do);
667 info(" functions..: %s\n",
668 get_overall_line($fn_found, $fn_hit, "function", "functions"))
669 if ($fn_do);
670 info(" branches...: %s\n",
671 get_overall_line($br_found, $br_hit, "branch", "branches"))
672 if ($br_do);
673 }
674
675
676 #
511 # gen_html() 677 # gen_html()
512 # 678 #
513 # Generate a set of HTML pages from contents of .info file INFO_FILENAME. 679 # Generate a set of HTML pages from contents of .info file INFO_FILENAME.
514 # Files will be written to the current directory. If provided, test case 680 # Files will be written to the current directory. If provided, test case
515 # descriptions will be read from .tests file TEST_FILENAME and included 681 # descriptions will be read from .tests file TEST_FILENAME and included
516 # in ouput. 682 # in ouput.
517 # 683 #
518 # Die on error. 684 # Die on error.
519 # 685 #
520 686
521 sub gen_html() 687 sub gen_html()
522 { 688 {
523 local *HTML_HANDLE; 689 local *HTML_HANDLE;
524 my %overview; 690 my %overview;
525 my %base_data; 691 my %base_data;
526 my $lines_found; 692 my $lines_found;
527 my $lines_hit; 693 my $lines_hit;
528 my $fn_found; 694 my $fn_found;
529 my $fn_hit; 695 my $fn_hit;
696 my $br_found;
697 my $br_hit;
530 my $overall_found = 0; 698 my $overall_found = 0;
531 my $overall_hit = 0; 699 my $overall_hit = 0;
532 my $total_fn_found = 0; 700 my $total_fn_found = 0;
533 my $total_fn_hit = 0; 701 my $total_fn_hit = 0;
702 my $total_br_found = 0;
703 my $total_br_hit = 0;
534 my $dir_name; 704 my $dir_name;
535 my $link_name; 705 my $link_name;
536 my @dir_list; 706 my @dir_list;
537 my %new_info; 707 my %new_info;
538 708
539 # Read in all specified .info files 709 # Read in all specified .info files
540 foreach (@info_filenames) 710 foreach (@info_filenames)
541 { 711 {
542 %new_info = %{read_info_file($_)}; 712 %new_info = %{read_info_file($_)};
543 713
(...skipping 19 matching lines...) Expand all
563 @dir_list = get_dir_list(keys(%info_data)); 733 @dir_list = get_dir_list(keys(%info_data));
564 734
565 if ($no_prefix) 735 if ($no_prefix)
566 { 736 {
567 # User requested that we leave filenames alone 737 # User requested that we leave filenames alone
568 info("User asked not to remove filename prefix\n"); 738 info("User asked not to remove filename prefix\n");
569 } 739 }
570 elsif (!defined($dir_prefix)) 740 elsif (!defined($dir_prefix))
571 { 741 {
572 # Get prefix common to most directories in list 742 # Get prefix common to most directories in list
573 » » $dir_prefix = get_prefix(@dir_list); 743 » » $dir_prefix = get_prefix(1, keys(%info_data));
574 744
575 if ($dir_prefix) 745 if ($dir_prefix)
576 { 746 {
577 info("Found common filename prefix \"$dir_prefix\"\n"); 747 info("Found common filename prefix \"$dir_prefix\"\n");
578 } 748 }
579 else 749 else
580 { 750 {
581 info("No common filename prefix found!\n"); 751 info("No common filename prefix found!\n");
582 $no_prefix=1; 752 $no_prefix=1;
583 } 753 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 { 788 {
619 info("Writing .htaccess file.\n"); 789 info("Writing .htaccess file.\n");
620 write_htaccess_file(); 790 write_htaccess_file();
621 } 791 }
622 792
623 info("Generating output.\n"); 793 info("Generating output.\n");
624 794
625 # Process each subdirectory and collect overview information 795 # Process each subdirectory and collect overview information
626 foreach $dir_name (@dir_list) 796 foreach $dir_name (@dir_list)
627 { 797 {
628 » » ($lines_found, $lines_hit, $fn_found, $fn_hit) 798 » » ($lines_found, $lines_hit, $fn_found, $fn_hit,
799 » » $br_found, $br_hit)
629 = process_dir($dir_name); 800 = process_dir($dir_name);
630 801
802 # Handle files in root directory gracefully
803 $dir_name = "root" if ($dir_name eq "");
804
631 # Remove prefix if applicable 805 # Remove prefix if applicable
632 if (!$no_prefix && $dir_prefix) 806 if (!$no_prefix && $dir_prefix)
633 { 807 {
634 # Match directory names beginning with $dir_prefix 808 # Match directory names beginning with $dir_prefix
635 $dir_name = apply_prefix($dir_name, $dir_prefix); 809 $dir_name = apply_prefix($dir_name, $dir_prefix);
636 } 810 }
637 811
638 # Generate name for directory overview HTML page 812 # Generate name for directory overview HTML page
639 if ($dir_name =~ /^\/(.*)$/) 813 if ($dir_name =~ /^\/(.*)$/)
640 { 814 {
641 $link_name = substr($dir_name, 1)."/index.$html_ext"; 815 $link_name = substr($dir_name, 1)."/index.$html_ext";
642 } 816 }
643 else 817 else
644 { 818 {
645 $link_name = $dir_name."/index.$html_ext"; 819 $link_name = $dir_name."/index.$html_ext";
646 } 820 }
647 821
648 $overview{$dir_name} = [$lines_found, $lines_hit, $fn_found, 822 $overview{$dir_name} = [$lines_found, $lines_hit, $fn_found,
649 » » » » » $fn_hit, $link_name, 823 » » » » » $fn_hit, $br_found, $br_hit, $link_name,
650 get_rate($lines_found, $lines_hit), 824 get_rate($lines_found, $lines_hit),
651 » » » » » get_rate($fn_found, $fn_hit)]; 825 » » » » » get_rate($fn_found, $fn_hit),
826 » » » » » get_rate($br_found, $br_hit)];
652 $overall_found += $lines_found; 827 $overall_found += $lines_found;
653 $overall_hit += $lines_hit; 828 $overall_hit += $lines_hit;
654 $total_fn_found += $fn_found; 829 $total_fn_found += $fn_found;
655 $total_fn_hit += $fn_hit; 830 $total_fn_hit += $fn_hit;
831 $total_br_found += $br_found;
832 $total_br_hit += $br_hit;
656 } 833 }
657 834
658 # Generate overview page 835 # Generate overview page
659 info("Writing directory view page.\n"); 836 info("Writing directory view page.\n");
660 837
661 # Create sorted pages 838 # Create sorted pages
662 foreach (@fileview_sortlist) { 839 foreach (@fileview_sortlist) {
663 write_dir_page($fileview_sortname[$_], ".", "", $test_title, 840 write_dir_page($fileview_sortname[$_], ".", "", $test_title,
664 undef, $overall_found, $overall_hit, 841 undef, $overall_found, $overall_hit,
665 » » » $total_fn_found, $total_fn_hit, \%overview, 842 » » » $total_fn_found, $total_fn_hit, $total_br_found,
666 » » » {}, {}, 0, $_); 843 » » » $total_br_hit, \%overview, {}, {}, {}, 0, $_);
667 } 844 }
668 845
669 # Check if there are any test case descriptions to write out 846 # Check if there are any test case descriptions to write out
670 if (%test_description) 847 if (%test_description)
671 { 848 {
672 info("Writing test case description file.\n"); 849 info("Writing test case description file.\n");
673 write_description_file( \%test_description, 850 write_description_file( \%test_description,
674 $overall_found, $overall_hit, 851 $overall_found, $overall_hit,
675 » » » » » $total_fn_found, $total_fn_hit); 852 » » » » » $total_fn_found, $total_fn_hit,
853 » » » » » $total_br_found, $total_br_hit);
676 } 854 }
677 855
856 print_overall_rate(1, $overall_found, $overall_hit,
857 $func_coverage, $total_fn_found, $total_fn_hit,
858 $br_coverage, $total_br_found, $total_br_hit);
859
678 chdir($cwd); 860 chdir($cwd);
679
680 info("Overall coverage rate:\n");
681
682 if ($overall_found == 0)
683 {
684 info(" lines......: no data found\n");
685 return;
686 }
687 info(" lines......: %.1f%% (%d of %d lines)\n",
688 $overall_hit * 100 / $overall_found, $overall_hit,
689 $overall_found,);
690
691 if ($func_coverage)
692 {
693 if ($total_fn_found == 0)
694 {
695 info(" functions..: no data found\n");
696 }
697 else
698 {
699 info(" functions..: %.1f%% (%d of %d functions)\n",
700 $total_fn_hit * 100 / $total_fn_found,
701 $total_fn_hit, $total_fn_found);
702
703 }
704 }
705
706 } 861 }
707 862
708 # 863 #
709 # html_create(handle, filename) 864 # html_create(handle, filename)
710 # 865 #
711 866
712 sub html_create($$) 867 sub html_create($$)
713 { 868 {
714 my $handle = $_[0]; 869 my $handle = $_[0];
715 my $filename = $_[1]; 870 my $filename = $_[1];
716 871
717 if ($html_gzip) 872 if ($html_gzip)
718 { 873 {
719 » » open($handle, "|gzip -c >$filename") 874 » » open($handle, "|-", "gzip -c >'$filename'")
720 or die("ERROR: cannot open $filename for writing ". 875 or die("ERROR: cannot open $filename for writing ".
721 "(gzip)!\n"); 876 "(gzip)!\n");
722 } 877 }
723 else 878 else
724 { 879 {
725 » » open($handle, ">$filename") 880 » » open($handle, ">", $filename)
726 or die("ERROR: cannot open $filename for writing!\n"); 881 or die("ERROR: cannot open $filename for writing!\n");
727 } 882 }
728 } 883 }
729 884
730 sub write_dir_page($$$$$$$$$$$$$$) 885 sub write_dir_page($$$$$$$$$$$$$$$$$)
731 { 886 {
732 my ($name, $rel_dir, $base_dir, $title, $trunc_dir, $overall_found, 887 my ($name, $rel_dir, $base_dir, $title, $trunc_dir, $overall_found,
733 » $overall_hit, $total_fn_found, $total_fn_hit, $overview, 888 » $overall_hit, $total_fn_found, $total_fn_hit, $total_br_found,
734 » $testhash, $testfnchash, $view_type, $sort_type) = @_; 889 » $total_br_hit, $overview, $testhash, $testfnchash, $testbrhash,
890 » $view_type, $sort_type) = @_;
735 891
736 # Generate directory overview page including details 892 # Generate directory overview page including details
737 html_create(*HTML_HANDLE, "$rel_dir/index$name.$html_ext"); 893 html_create(*HTML_HANDLE, "$rel_dir/index$name.$html_ext");
738 if (!defined($trunc_dir)) { 894 if (!defined($trunc_dir)) {
739 $trunc_dir = ""; 895 $trunc_dir = "";
740 } 896 }
897 $title .= " - " if ($trunc_dir ne "");
741 write_html_prolog(*HTML_HANDLE, $base_dir, "LCOV - $title$trunc_dir"); 898 write_html_prolog(*HTML_HANDLE, $base_dir, "LCOV - $title$trunc_dir");
742 write_header(*HTML_HANDLE, $view_type, $trunc_dir, $rel_dir, 899 write_header(*HTML_HANDLE, $view_type, $trunc_dir, $rel_dir,
743 $overall_found, $overall_hit, $total_fn_found, 900 $overall_found, $overall_hit, $total_fn_found,
744 » » $total_fn_hit, $sort_type); 901 » » $total_fn_hit, $total_br_found, $total_br_hit, $sort_type);
745 write_file_table(*HTML_HANDLE, $base_dir, $overview, $testhash, 902 write_file_table(*HTML_HANDLE, $base_dir, $overview, $testhash,
746 » » » $testfnchash, $view_type, $sort_type); 903 » » » $testfnchash, $testbrhash, $view_type, $sort_type);
747 write_html_epilog(*HTML_HANDLE, $base_dir); 904 write_html_epilog(*HTML_HANDLE, $base_dir);
748 close(*HTML_HANDLE); 905 close(*HTML_HANDLE);
749 } 906 }
750 907
751 908
752 # 909 #
753 # process_dir(dir_name) 910 # process_dir(dir_name)
754 # 911 #
755 912
756 sub process_dir($) 913 sub process_dir($)
757 { 914 {
758 my $abs_dir = $_[0]; 915 my $abs_dir = $_[0];
759 my $trunc_dir; 916 my $trunc_dir;
760 my $rel_dir = $abs_dir; 917 my $rel_dir = $abs_dir;
761 my $base_dir; 918 my $base_dir;
762 my $filename; 919 my $filename;
763 my %overview; 920 my %overview;
764 my $lines_found; 921 my $lines_found;
765 my $lines_hit; 922 my $lines_hit;
766 my $fn_found; 923 my $fn_found;
767 my $fn_hit; 924 my $fn_hit;
925 my $br_found;
926 my $br_hit;
768 my $overall_found=0; 927 my $overall_found=0;
769 my $overall_hit=0; 928 my $overall_hit=0;
770 my $total_fn_found=0; 929 my $total_fn_found=0;
771 my $total_fn_hit=0; 930 my $total_fn_hit=0;
931 my $total_br_found = 0;
932 my $total_br_hit = 0;
772 my $base_name; 933 my $base_name;
773 my $extension; 934 my $extension;
774 my $testdata; 935 my $testdata;
775 my %testhash; 936 my %testhash;
776 my $testfncdata; 937 my $testfncdata;
777 my %testfnchash; 938 my %testfnchash;
939 my $testbrdata;
940 my %testbrhash;
778 my @sort_list; 941 my @sort_list;
779 local *HTML_HANDLE; 942 local *HTML_HANDLE;
780 943
781 # Remove prefix if applicable 944 # Remove prefix if applicable
782 if (!$no_prefix) 945 if (!$no_prefix)
783 { 946 {
784 # Match directory name beginning with $dir_prefix 947 # Match directory name beginning with $dir_prefix
785 $rel_dir = apply_prefix($rel_dir, $dir_prefix); 948 $rel_dir = apply_prefix($rel_dir, $dir_prefix);
786 } 949 }
787 950
788 $trunc_dir = $rel_dir; 951 $trunc_dir = $rel_dir;
789 952
790 # Remove leading / 953 # Remove leading /
791 if ($rel_dir =~ /^\/(.*)$/) 954 if ($rel_dir =~ /^\/(.*)$/)
792 { 955 {
793 $rel_dir = substr($rel_dir, 1); 956 $rel_dir = substr($rel_dir, 1);
794 } 957 }
795 958
959 # Handle files in root directory gracefully
960 $rel_dir = "root" if ($rel_dir eq "");
961 $trunc_dir = "root" if ($trunc_dir eq "");
962
796 $base_dir = get_relative_base_path($rel_dir); 963 $base_dir = get_relative_base_path($rel_dir);
797 964
798 create_sub_dir($rel_dir); 965 create_sub_dir($rel_dir);
799 966
800 # Match filenames which specify files in this directory, not including 967 # Match filenames which specify files in this directory, not including
801 # sub-directories 968 # sub-directories
802 foreach $filename (grep(/^\Q$abs_dir\E\/[^\/]*$/,keys(%info_data))) 969 foreach $filename (grep(/^\Q$abs_dir\E\/[^\/]*$/,keys(%info_data)))
803 { 970 {
804 my $page_link; 971 my $page_link;
805 my $func_link; 972 my $func_link;
806 973
807 » » ($lines_found, $lines_hit, $fn_found, $fn_hit, $testdata, 974 » » ($lines_found, $lines_hit, $fn_found, $fn_hit, $br_found,
808 » » $testfncdata) = process_file($trunc_dir, $rel_dir, $filename); 975 » » $br_hit, $testdata, $testfncdata, $testbrdata) =
976 » » » process_file($trunc_dir, $rel_dir, $filename);
809 977
810 $base_name = basename($filename); 978 $base_name = basename($filename);
811 979
812 if ($no_sourceview) { 980 if ($no_sourceview) {
813 $page_link = ""; 981 $page_link = "";
814 } elsif ($frames) { 982 } elsif ($frames) {
815 # Link to frameset page 983 # Link to frameset page
816 $page_link = "$base_name.gcov.frameset.$html_ext"; 984 $page_link = "$base_name.gcov.frameset.$html_ext";
817 } else { 985 } else {
818 # Link directory to source code view page 986 # Link directory to source code view page
819 $page_link = "$base_name.gcov.$html_ext"; 987 $page_link = "$base_name.gcov.$html_ext";
820 } 988 }
821 $overview{$base_name} = [$lines_found, $lines_hit, $fn_found, 989 $overview{$base_name} = [$lines_found, $lines_hit, $fn_found,
822 » » » » » $fn_hit, $page_link, 990 » » » » » $fn_hit, $br_found, $br_hit,
991 » » » » » $page_link,
823 get_rate($lines_found, $lines_hit), 992 get_rate($lines_found, $lines_hit),
824 » » » » » get_rate($fn_found, $fn_hit)]; 993 » » » » » get_rate($fn_found, $fn_hit),
994 » » » » » get_rate($br_found, $br_hit)];
825 995
826 $testhash{$base_name} = $testdata; 996 $testhash{$base_name} = $testdata;
827 $testfnchash{$base_name} = $testfncdata; 997 $testfnchash{$base_name} = $testfncdata;
998 $testbrhash{$base_name} = $testbrdata;
828 999
829 $overall_found += $lines_found; 1000 $overall_found += $lines_found;
830 $overall_hit += $lines_hit; 1001 $overall_hit += $lines_hit;
831 1002
832 $total_fn_found += $fn_found; 1003 $total_fn_found += $fn_found;
833 $total_fn_hit += $fn_hit; 1004 $total_fn_hit += $fn_hit;
1005
1006 $total_br_found += $br_found;
1007 $total_br_hit += $br_hit;
834 } 1008 }
835 1009
836 # Create sorted pages 1010 # Create sorted pages
837 foreach (@fileview_sortlist) { 1011 foreach (@fileview_sortlist) {
838 # Generate directory overview page (without details) 1012 # Generate directory overview page (without details)
839 write_dir_page($fileview_sortname[$_], $rel_dir, $base_dir, 1013 write_dir_page($fileview_sortname[$_], $rel_dir, $base_dir,
840 $test_title, $trunc_dir, $overall_found, 1014 $test_title, $trunc_dir, $overall_found,
841 $overall_hit, $total_fn_found, $total_fn_hit, 1015 $overall_hit, $total_fn_found, $total_fn_hit,
842 » » » \%overview, {}, {}, 1, $_); 1016 » » » $total_br_found, $total_br_hit, \%overview, {},
1017 » » » {}, {}, 1, $_);
843 if (!$show_details) { 1018 if (!$show_details) {
844 next; 1019 next;
845 } 1020 }
846 # Generate directory overview page including details 1021 # Generate directory overview page including details
847 write_dir_page("-detail".$fileview_sortname[$_], $rel_dir, 1022 write_dir_page("-detail".$fileview_sortname[$_], $rel_dir,
848 $base_dir, $test_title, $trunc_dir, 1023 $base_dir, $test_title, $trunc_dir,
849 $overall_found, $overall_hit, $total_fn_found, 1024 $overall_found, $overall_hit, $total_fn_found,
850 » » » $total_fn_hit, \%overview, \%testhash, 1025 » » » $total_fn_hit, $total_br_found, $total_br_hit,
851 » » » \%testfnchash, 1, $_); 1026 » » » \%overview, \%testhash, \%testfnchash,
1027 » » » \%testbrhash, 1, $_);
852 } 1028 }
853 1029
854 # Calculate resulting line counts 1030 # Calculate resulting line counts
855 » return ($overall_found, $overall_hit, $total_fn_found, $total_fn_hit); 1031 » return ($overall_found, $overall_hit, $total_fn_found, $total_fn_hit,
1032 » » $total_br_found, $total_br_hit);
856 } 1033 }
857 1034
858 1035
859 # 1036 #
860 # get_converted_lines(testdata) 1037 # get_converted_lines(testdata)
861 # 1038 #
862 # Return hash of line numbers of those lines which were only covered in 1039 # Return hash of line numbers of those lines which were only covered in
863 # converted data sets. 1040 # converted data sets.
864 # 1041 #
865 1042
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
906 if (!defined($nonconverted{$line})) 1083 if (!defined($nonconverted{$line}))
907 { 1084 {
908 $result{$line} = 1; 1085 $result{$line} = 1;
909 } 1086 }
910 } 1087 }
911 1088
912 return \%result; 1089 return \%result;
913 } 1090 }
914 1091
915 1092
916 sub write_function_page($$$$$$$$$$$$$$) 1093 sub write_function_page($$$$$$$$$$$$$$$$$$)
917 { 1094 {
918 my ($base_dir, $rel_dir, $trunc_dir, $base_name, $title, 1095 my ($base_dir, $rel_dir, $trunc_dir, $base_name, $title,
919 » $lines_found, $lines_hit, $fn_found, $fn_hit, 1096 » $lines_found, $lines_hit, $fn_found, $fn_hit, $br_found, $br_hit,
920 » $sumcount, $funcdata, $sumfnccount, $testfncdata, $sort_type) = @_; 1097 » $sumcount, $funcdata, $sumfnccount, $testfncdata, $sumbrcount,
1098 » $testbrdata, $sort_type) = @_;
921 my $pagetitle; 1099 my $pagetitle;
922 my $filename; 1100 my $filename;
923 1101
924 # Generate function table for this file 1102 # Generate function table for this file
925 if ($sort_type == 0) { 1103 if ($sort_type == 0) {
926 $filename = "$rel_dir/$base_name.func.$html_ext"; 1104 $filename = "$rel_dir/$base_name.func.$html_ext";
927 } else { 1105 } else {
928 $filename = "$rel_dir/$base_name.func-sort-c.$html_ext"; 1106 $filename = "$rel_dir/$base_name.func-sort-c.$html_ext";
929 } 1107 }
930 html_create(*HTML_HANDLE, $filename); 1108 html_create(*HTML_HANDLE, $filename);
931 $pagetitle = "LCOV - $title - $trunc_dir/$base_name - functions"; 1109 $pagetitle = "LCOV - $title - $trunc_dir/$base_name - functions";
932 write_html_prolog(*HTML_HANDLE, $base_dir, $pagetitle); 1110 write_html_prolog(*HTML_HANDLE, $base_dir, $pagetitle);
933 write_header(*HTML_HANDLE, 4, "$trunc_dir/$base_name", 1111 write_header(*HTML_HANDLE, 4, "$trunc_dir/$base_name",
934 "$rel_dir/$base_name", $lines_found, $lines_hit, 1112 "$rel_dir/$base_name", $lines_found, $lines_hit,
935 » » $fn_found, $fn_hit, $sort_type); 1113 » » $fn_found, $fn_hit, $br_found, $br_hit, $sort_type);
936 write_function_table(*HTML_HANDLE, "$base_name.gcov.$html_ext", 1114 write_function_table(*HTML_HANDLE, "$base_name.gcov.$html_ext",
937 $sumcount, $funcdata, 1115 $sumcount, $funcdata,
938 » » » $sumfnccount, $testfncdata, $base_name, 1116 » » » $sumfnccount, $testfncdata, $sumbrcount,
1117 » » » $testbrdata, $base_name,
939 $base_dir, $sort_type); 1118 $base_dir, $sort_type);
940 write_html_epilog(*HTML_HANDLE, $base_dir, 1); 1119 write_html_epilog(*HTML_HANDLE, $base_dir, 1);
941 close(*HTML_HANDLE); 1120 close(*HTML_HANDLE);
942 } 1121 }
943 1122
944 1123
945 # 1124 #
946 # process_file(trunc_dir, rel_dir, filename) 1125 # process_file(trunc_dir, rel_dir, filename)
947 # 1126 #
948 1127
949 sub process_file($$$) 1128 sub process_file($$$)
950 { 1129 {
951 info("Processing file ".apply_prefix($_[2], $dir_prefix)."\n"); 1130 info("Processing file ".apply_prefix($_[2], $dir_prefix)."\n");
952 1131
953 my $trunc_dir = $_[0]; 1132 my $trunc_dir = $_[0];
954 my $rel_dir = $_[1]; 1133 my $rel_dir = $_[1];
955 my $filename = $_[2]; 1134 my $filename = $_[2];
956 my $base_name = basename($filename); 1135 my $base_name = basename($filename);
957 my $base_dir = get_relative_base_path($rel_dir); 1136 my $base_dir = get_relative_base_path($rel_dir);
958 my $testdata; 1137 my $testdata;
959 my $testcount; 1138 my $testcount;
960 my $sumcount; 1139 my $sumcount;
961 my $funcdata; 1140 my $funcdata;
962 my $checkdata; 1141 my $checkdata;
963 my $testfncdata; 1142 my $testfncdata;
964 my $sumfnccount; 1143 my $sumfnccount;
1144 my $testbrdata;
1145 my $sumbrcount;
965 my $lines_found; 1146 my $lines_found;
966 my $lines_hit; 1147 my $lines_hit;
967 my $fn_found; 1148 my $fn_found;
968 my $fn_hit; 1149 my $fn_hit;
1150 my $br_found;
1151 my $br_hit;
969 my $converted; 1152 my $converted;
970 my @source; 1153 my @source;
971 my $pagetitle; 1154 my $pagetitle;
972 local *HTML_HANDLE; 1155 local *HTML_HANDLE;
973 1156
974 ($testdata, $sumcount, $funcdata, $checkdata, $testfncdata, 1157 ($testdata, $sumcount, $funcdata, $checkdata, $testfncdata,
975 » $sumfnccount, $lines_found, $lines_hit, $fn_found, $fn_hit) 1158 » $sumfnccount, $testbrdata, $sumbrcount, $lines_found, $lines_hit,
1159 » $fn_found, $fn_hit, $br_found, $br_hit)
976 = get_info_entry($info_data{$filename}); 1160 = get_info_entry($info_data{$filename});
977 1161
978 # Return after this point in case user asked us not to generate 1162 # Return after this point in case user asked us not to generate
979 # source code view 1163 # source code view
980 if ($no_sourceview) 1164 if ($no_sourceview)
981 { 1165 {
982 » » return ($lines_found, $lines_hit, 1166 » » return ($lines_found, $lines_hit, $fn_found, $fn_hit,
983 » » » $fn_found, $fn_hit, $testdata); 1167 » » » $br_found, $br_hit, $testdata, $testfncdata,
1168 » » » $testbrdata);
984 } 1169 }
985 1170
986 $converted = get_converted_lines($testdata); 1171 $converted = get_converted_lines($testdata);
987 # Generate source code view for this file 1172 # Generate source code view for this file
988 html_create(*HTML_HANDLE, "$rel_dir/$base_name.gcov.$html_ext"); 1173 html_create(*HTML_HANDLE, "$rel_dir/$base_name.gcov.$html_ext");
989 $pagetitle = "LCOV - $test_title - $trunc_dir/$base_name"; 1174 $pagetitle = "LCOV - $test_title - $trunc_dir/$base_name";
990 write_html_prolog(*HTML_HANDLE, $base_dir, $pagetitle); 1175 write_html_prolog(*HTML_HANDLE, $base_dir, $pagetitle);
991 write_header(*HTML_HANDLE, 2, "$trunc_dir/$base_name", 1176 write_header(*HTML_HANDLE, 2, "$trunc_dir/$base_name",
992 "$rel_dir/$base_name", $lines_found, $lines_hit, 1177 "$rel_dir/$base_name", $lines_found, $lines_hit,
993 » » $fn_found, $fn_hit, 0); 1178 » » $fn_found, $fn_hit, $br_found, $br_hit, 0);
994 @source = write_source(*HTML_HANDLE, $filename, $sumcount, $checkdata, 1179 @source = write_source(*HTML_HANDLE, $filename, $sumcount, $checkdata,
995 » » » $converted, $funcdata); 1180 » » » $converted, $funcdata, $sumbrcount);
996 1181
997 write_html_epilog(*HTML_HANDLE, $base_dir, 1); 1182 write_html_epilog(*HTML_HANDLE, $base_dir, 1);
998 close(*HTML_HANDLE); 1183 close(*HTML_HANDLE);
999 1184
1000 if ($func_coverage) { 1185 if ($func_coverage) {
1001 # Create function tables 1186 # Create function tables
1002 foreach (@funcview_sortlist) { 1187 foreach (@funcview_sortlist) {
1003 write_function_page($base_dir, $rel_dir, $trunc_dir, 1188 write_function_page($base_dir, $rel_dir, $trunc_dir,
1004 $base_name, $test_title, 1189 $base_name, $test_title,
1005 $lines_found, $lines_hit, 1190 $lines_found, $lines_hit,
1006 » » » » » $fn_found, $fn_hit, $sumcount, 1191 » » » » » $fn_found, $fn_hit, $br_found,
1192 » » » » » $br_hit, $sumcount,
1007 $funcdata, $sumfnccount, 1193 $funcdata, $sumfnccount,
1008 » » » » » $testfncdata, $_); 1194 » » » » » $testfncdata, $sumbrcount,
1195 » » » » » $testbrdata, $_);
1009 } 1196 }
1010 } 1197 }
1011 1198
1012 # Additional files are needed in case of frame output 1199 # Additional files are needed in case of frame output
1013 if (!$frames) 1200 if (!$frames)
1014 { 1201 {
1015 » » return ($lines_found, $lines_hit, 1202 » » return ($lines_found, $lines_hit, $fn_found, $fn_hit,
1016 » » » $fn_found, $fn_hit, $testdata); 1203 » » » $br_found, $br_hit, $testdata, $testfncdata,
1204 » » » $testbrdata);
1017 } 1205 }
1018 1206
1019 # Create overview png file 1207 # Create overview png file
1020 gen_png("$rel_dir/$base_name.gcov.png", $overview_width, $tab_size, 1208 gen_png("$rel_dir/$base_name.gcov.png", $overview_width, $tab_size,
1021 @source); 1209 @source);
1022 1210
1023 # Create frameset page 1211 # Create frameset page
1024 html_create(*HTML_HANDLE, 1212 html_create(*HTML_HANDLE,
1025 "$rel_dir/$base_name.gcov.frameset.$html_ext"); 1213 "$rel_dir/$base_name.gcov.frameset.$html_ext");
1026 write_frameset(*HTML_HANDLE, $base_dir, $base_name, $pagetitle); 1214 write_frameset(*HTML_HANDLE, $base_dir, $base_name, $pagetitle);
1027 close(*HTML_HANDLE); 1215 close(*HTML_HANDLE);
1028 1216
1029 # Write overview frame 1217 # Write overview frame
1030 html_create(*HTML_HANDLE, 1218 html_create(*HTML_HANDLE,
1031 "$rel_dir/$base_name.gcov.overview.$html_ext"); 1219 "$rel_dir/$base_name.gcov.overview.$html_ext");
1032 write_overview(*HTML_HANDLE, $base_dir, $base_name, $pagetitle, 1220 write_overview(*HTML_HANDLE, $base_dir, $base_name, $pagetitle,
1033 scalar(@source)); 1221 scalar(@source));
1034 close(*HTML_HANDLE); 1222 close(*HTML_HANDLE);
1035 1223
1036 » return ($lines_found, $lines_hit, $fn_found, $fn_hit, $testdata, 1224 » return ($lines_found, $lines_hit, $fn_found, $fn_hit, $br_found,
1037 » » $testfncdata); 1225 » » $br_hit, $testdata, $testfncdata, $testbrdata);
1038 } 1226 }
1039 1227
1040 1228
1041 # 1229 #
1042 # read_info_file(info_filename) 1230 # read_info_file(info_filename)
1043 # 1231 #
1044 # Read in the contents of the .info file specified by INFO_FILENAME. Data will 1232 # Read in the contents of the .info file specified by INFO_FILENAME. Data will
1045 # be returned as a reference to a hash containing the following mappings: 1233 # be returned as a reference to a hash containing the following mappings:
1046 # 1234 #
1047 # %result: for each filename found in file -> \%data 1235 # %result: for each filename found in file -> \%data
1048 # 1236 #
1049 # %data: "test" -> \%testdata 1237 # %data: "test" -> \%testdata
1050 # "sum" -> \%sumcount 1238 # "sum" -> \%sumcount
1051 # "func" -> \%funcdata 1239 # "func" -> \%funcdata
1052 # "found" -> $lines_found (number of instrumented lines found in file) 1240 # "found" -> $lines_found (number of instrumented lines found in file)
1053 # "hit" -> $lines_hit (number of executed lines in file) 1241 # "hit" -> $lines_hit (number of executed lines in file)
1054 # "check" -> \%checkdata 1242 # "check" -> \%checkdata
1055 # "testfnc" -> \%testfncdata 1243 # "testfnc" -> \%testfncdata
1056 # "sumfnc" -> \%sumfnccount 1244 # "sumfnc" -> \%sumfnccount
1245 # "testbr" -> \%testbrdata
1246 # "sumbr" -> \%sumbrcount
1057 # 1247 #
1058 # %testdata : name of test affecting this file -> \%testcount 1248 # %testdata : name of test affecting this file -> \%testcount
1059 # %testfncdata: name of test affecting this file -> \%testfnccount 1249 # %testfncdata: name of test affecting this file -> \%testfnccount
1250 # %testbrdata: name of test affecting this file -> \%testbrcount
1060 # 1251 #
1061 # %testcount : line number -> execution count for a single test 1252 # %testcount : line number -> execution count for a single test
1062 # %testfnccount: function name -> execution count for a single test 1253 # %testfnccount: function name -> execution count for a single test
1254 # %testbrcount : line number -> branch coverage data for a single test
1063 # %sumcount : line number -> execution count for all tests 1255 # %sumcount : line number -> execution count for all tests
1064 # %sumfnccount : function name -> execution count for all tests 1256 # %sumfnccount : function name -> execution count for all tests
1257 # %sumbrcount : line number -> branch coverage data for all tests
1065 # %funcdata : function name -> line number 1258 # %funcdata : function name -> line number
1066 # %checkdata : line number -> checksum of source code line 1259 # %checkdata : line number -> checksum of source code line
1260 # $brdata : vector of items: block, branch, taken
1067 # 1261 #
1068 # Note that .info file sections referring to the same file and test name 1262 # Note that .info file sections referring to the same file and test name
1069 # will automatically be combined by adding all execution counts. 1263 # will automatically be combined by adding all execution counts.
1070 # 1264 #
1071 # Note that if INFO_FILENAME ends with ".gz", it is assumed that the file 1265 # Note that if INFO_FILENAME ends with ".gz", it is assumed that the file
1072 # is compressed using GZIP. If available, GUNZIP will be used to decompress 1266 # is compressed using GZIP. If available, GUNZIP will be used to decompress
1073 # this file. 1267 # this file.
1074 # 1268 #
1075 # Die on error. 1269 # Die on error.
1076 # 1270 #
1077 1271
1078 sub read_info_file($) 1272 sub read_info_file($)
1079 { 1273 {
1080 my $tracefile = $_[0]; # Name of tracefile 1274 my $tracefile = $_[0]; # Name of tracefile
1081 my %result; # Resulting hash: file -> data 1275 my %result; # Resulting hash: file -> data
1082 my $data; # Data handle for current entry 1276 my $data; # Data handle for current entry
1083 my $testdata; # " " 1277 my $testdata; # " "
1084 my $testcount; # " " 1278 my $testcount; # " "
1085 my $sumcount; # " " 1279 my $sumcount; # " "
1086 my $funcdata; # " " 1280 my $funcdata; # " "
1087 my $checkdata; # " " 1281 my $checkdata; # " "
1088 my $testfncdata; 1282 my $testfncdata;
1089 my $testfnccount; 1283 my $testfnccount;
1090 my $sumfnccount; 1284 my $sumfnccount;
1285 my $testbrdata;
1286 my $testbrcount;
1287 my $sumbrcount;
1091 my $line; # Current line read from .info file 1288 my $line; # Current line read from .info file
1092 my $testname; # Current test name 1289 my $testname; # Current test name
1093 my $filename; # Current filename 1290 my $filename; # Current filename
1094 my $hitcount; # Count for lines hit 1291 my $hitcount; # Count for lines hit
1095 my $count; # Execution count of current line 1292 my $count; # Execution count of current line
1096 my $negative; # If set, warn about negative counts 1293 my $negative; # If set, warn about negative counts
1097 my $changed_testname; # If set, warn about changed testname 1294 my $changed_testname; # If set, warn about changed testname
1098 my $line_checksum; # Checksum of current line 1295 my $line_checksum; # Checksum of current line
1296 my $br_found;
1297 my $br_hit;
1099 local *INFO_HANDLE; # Filehandle for .info file 1298 local *INFO_HANDLE; # Filehandle for .info file
1100 1299
1101 info("Reading data file $tracefile\n"); 1300 info("Reading data file $tracefile\n");
1102 1301
1103 # Check if file exists and is readable 1302 # Check if file exists and is readable
1104 stat($_[0]); 1303 stat($_[0]);
1105 if (!(-r _)) 1304 if (!(-r _))
1106 { 1305 {
1107 die("ERROR: cannot read file $_[0]!\n"); 1306 die("ERROR: cannot read file $_[0]!\n");
1108 } 1307 }
(...skipping 10 matching lines...) Expand all
1119 # Check for availability of GZIP tool 1318 # Check for availability of GZIP tool
1120 system_no_output(1, "gunzip" ,"-h") 1319 system_no_output(1, "gunzip" ,"-h")
1121 and die("ERROR: gunzip command not available!\n"); 1320 and die("ERROR: gunzip command not available!\n");
1122 1321
1123 # Check integrity of compressed file 1322 # Check integrity of compressed file
1124 system_no_output(1, "gunzip", "-t", $_[0]) 1323 system_no_output(1, "gunzip", "-t", $_[0])
1125 and die("ERROR: integrity check failed for ". 1324 and die("ERROR: integrity check failed for ".
1126 "compressed file $_[0]!\n"); 1325 "compressed file $_[0]!\n");
1127 1326
1128 # Open compressed file 1327 # Open compressed file
1129 » » open(INFO_HANDLE, "gunzip -c $_[0]|") 1328 » » open(INFO_HANDLE, "-|", "gunzip -c '$_[0]'")
1130 or die("ERROR: cannot start gunzip to decompress ". 1329 or die("ERROR: cannot start gunzip to decompress ".
1131 "file $_[0]!\n"); 1330 "file $_[0]!\n");
1132 } 1331 }
1133 else 1332 else
1134 { 1333 {
1135 # Open decompressed file 1334 # Open decompressed file
1136 » » open(INFO_HANDLE, $_[0]) 1335 » » open(INFO_HANDLE, "<", $_[0])
1137 or die("ERROR: cannot read file $_[0]!\n"); 1336 or die("ERROR: cannot read file $_[0]!\n");
1138 } 1337 }
1139 1338
1140 $testname = ""; 1339 $testname = "";
1141 while (<INFO_HANDLE>) 1340 while (<INFO_HANDLE>)
1142 { 1341 {
1143 chomp($_); 1342 chomp($_);
1144 $line = $_; 1343 $line = $_;
1145 1344
1146 # Switch statement 1345 # Switch statement
1147 foreach ($line) 1346 foreach ($line)
1148 { 1347 {
1149 » » » /^TN:([^,]*)/ && do 1348 » » » /^TN:([^,]*)(,diff)?/ && do
1150 { 1349 {
1151 # Test name information found 1350 # Test name information found
1152 $testname = defined($1) ? $1 : ""; 1351 $testname = defined($1) ? $1 : "";
1153 if ($testname =~ s/\W/_/g) 1352 if ($testname =~ s/\W/_/g)
1154 { 1353 {
1155 $changed_testname = 1; 1354 $changed_testname = 1;
1156 } 1355 }
1356 $testname .= $2 if (defined($2));
1157 last; 1357 last;
1158 }; 1358 };
1159 1359
1160 /^[SK]F:(.*)/ && do 1360 /^[SK]F:(.*)/ && do
1161 { 1361 {
1162 # Filename information found 1362 # Filename information found
1163 # Retrieve data for new entry 1363 # Retrieve data for new entry
1164 $filename = $1; 1364 $filename = $1;
1165 1365
1166 $data = $result{$filename}; 1366 $data = $result{$filename};
1167 ($testdata, $sumcount, $funcdata, $checkdata, 1367 ($testdata, $sumcount, $funcdata, $checkdata,
1168 » » » » $testfncdata, $sumfnccount) = 1368 » » » » $testfncdata, $sumfnccount, $testbrdata,
1369 » » » » $sumbrcount) =
1169 get_info_entry($data); 1370 get_info_entry($data);
1170 1371
1171 if (defined($testname)) 1372 if (defined($testname))
1172 { 1373 {
1173 $testcount = $testdata->{$testname}; 1374 $testcount = $testdata->{$testname};
1174 $testfnccount = $testfncdata->{$testname }; 1375 $testfnccount = $testfncdata->{$testname };
1376 $testbrcount = $testbrdata->{$testname};
1175 } 1377 }
1176 else 1378 else
1177 { 1379 {
1178 $testcount = {}; 1380 $testcount = {};
1179 $testfnccount = {}; 1381 $testfnccount = {};
1382 $testbrcount = {};
1180 } 1383 }
1181 last; 1384 last;
1182 }; 1385 };
1183 1386
1184 /^DA:(\d+),(-?\d+)(,[^,\s]+)?/ && do 1387 /^DA:(\d+),(-?\d+)(,[^,\s]+)?/ && do
1185 { 1388 {
1186 # Fix negative counts 1389 # Fix negative counts
1187 $count = $2 < 0 ? 0 : $2; 1390 $count = $2 < 0 ? 0 : $2;
1188 if ($2 < 0) 1391 if ($2 < 0)
1189 { 1392 {
(...skipping 23 matching lines...) Expand all
1213 "at $filename:$1\n"); 1416 "at $filename:$1\n");
1214 } 1417 }
1215 1418
1216 $checkdata->{$1} = $line_checksum; 1419 $checkdata->{$1} = $line_checksum;
1217 } 1420 }
1218 last; 1421 last;
1219 }; 1422 };
1220 1423
1221 /^FN:(\d+),([^,]+)/ && do 1424 /^FN:(\d+),([^,]+)/ && do
1222 { 1425 {
1426 last if (!$func_coverage);
1427
1223 # Function data found, add to structure 1428 # Function data found, add to structure
1224 $funcdata->{$2} = $1; 1429 $funcdata->{$2} = $1;
1225 1430
1226 # Also initialize function call data 1431 # Also initialize function call data
1227 if (!defined($sumfnccount->{$2})) { 1432 if (!defined($sumfnccount->{$2})) {
1228 $sumfnccount->{$2} = 0; 1433 $sumfnccount->{$2} = 0;
1229 } 1434 }
1230 if (defined($testname)) 1435 if (defined($testname))
1231 { 1436 {
1232 if (!defined($testfnccount->{$2})) { 1437 if (!defined($testfnccount->{$2})) {
1233 $testfnccount->{$2} = 0; 1438 $testfnccount->{$2} = 0;
1234 } 1439 }
1235 } 1440 }
1236 last; 1441 last;
1237 }; 1442 };
1238 1443
1239 /^FNDA:(\d+),([^,]+)/ && do 1444 /^FNDA:(\d+),([^,]+)/ && do
1240 { 1445 {
1446 last if (!$func_coverage);
1241 # Function call count found, add to structure 1447 # Function call count found, add to structure
1242 # Add summary counts 1448 # Add summary counts
1243 $sumfnccount->{$2} += $1; 1449 $sumfnccount->{$2} += $1;
1244 1450
1245 # Add test-specific counts 1451 # Add test-specific counts
1246 if (defined($testname)) 1452 if (defined($testname))
1247 { 1453 {
1248 $testfnccount->{$2} += $1; 1454 $testfnccount->{$2} += $1;
1249 } 1455 }
1250 last; 1456 last;
1251 }; 1457 };
1458
1459 /^BRDA:(\d+),(\d+),(\d+),(\d+|-)/ && do {
1460 # Branch coverage data found
1461 my ($line, $block, $branch, $taken) =
1462 ($1, $2, $3, $4);
1463
1464 last if (!$br_coverage);
1465 $sumbrcount->{$line} =
1466 br_ivec_push($sumbrcount->{$line},
1467 $block, $branch, $taken);
1468
1469 # Add test-specific counts
1470 if (defined($testname)) {
1471 $testbrcount->{$line} =
1472 br_ivec_push(
1473 $testbrcount->{$line},
1474 $block, $branch,
1475 $taken);
1476 }
1477 last;
1478 };
1479
1252 /^end_of_record/ && do 1480 /^end_of_record/ && do
1253 { 1481 {
1254 # Found end of section marker 1482 # Found end of section marker
1255 if ($filename) 1483 if ($filename)
1256 { 1484 {
1257 # Store current section data 1485 # Store current section data
1258 if (defined($testname)) 1486 if (defined($testname))
1259 { 1487 {
1260 $testdata->{$testname} = 1488 $testdata->{$testname} =
1261 $testcount; 1489 $testcount;
1262 $testfncdata->{$testname} = 1490 $testfncdata->{$testname} =
1263 $testfnccount; 1491 $testfnccount;
1492 $testbrdata->{$testname} =
1493 $testbrcount;
1264 } 1494 }
1265 1495
1266 set_info_entry($data, $testdata, 1496 set_info_entry($data, $testdata,
1267 $sumcount, $funcdata, 1497 $sumcount, $funcdata,
1268 $checkdata, $testfncdata, 1498 $checkdata, $testfncdata,
1269 » » » » » » $sumfnccount); 1499 » » » » » » $sumfnccount,
1500 » » » » » » $testbrdata,
1501 » » » » » » $sumbrcount);
1270 $result{$filename} = $data; 1502 $result{$filename} = $data;
1271 last; 1503 last;
1272 } 1504 }
1273 }; 1505 };
1274 1506
1275 # default 1507 # default
1276 last; 1508 last;
1277 } 1509 }
1278 } 1510 }
1279 close(INFO_HANDLE); 1511 close(INFO_HANDLE);
1280 1512
1281 # Calculate lines_found and lines_hit for each file 1513 # Calculate lines_found and lines_hit for each file
1282 foreach $filename (keys(%result)) 1514 foreach $filename (keys(%result))
1283 { 1515 {
1284 $data = $result{$filename}; 1516 $data = $result{$filename};
1285 1517
1286 ($testdata, $sumcount, undef, undef, $testfncdata, 1518 ($testdata, $sumcount, undef, undef, $testfncdata,
1287 » » $sumfnccount) = get_info_entry($data); 1519 » » $sumfnccount, $testbrdata, $sumbrcount) =
1520 » » » get_info_entry($data);
1288 1521
1289 # Filter out empty files 1522 # Filter out empty files
1290 if (scalar(keys(%{$sumcount})) == 0) 1523 if (scalar(keys(%{$sumcount})) == 0)
1291 { 1524 {
1292 delete($result{$filename}); 1525 delete($result{$filename});
1293 next; 1526 next;
1294 } 1527 }
1295 # Filter out empty test cases 1528 # Filter out empty test cases
1296 foreach $testname (keys(%{$testdata})) 1529 foreach $testname (keys(%{$testdata}))
1297 { 1530 {
(...skipping 18 matching lines...) Expand all
1316 # Get found/hit values for function call data 1549 # Get found/hit values for function call data
1317 $data->{"f_found"} = scalar(keys(%{$sumfnccount})); 1550 $data->{"f_found"} = scalar(keys(%{$sumfnccount}));
1318 $hitcount = 0; 1551 $hitcount = 0;
1319 1552
1320 foreach (keys(%{$sumfnccount})) { 1553 foreach (keys(%{$sumfnccount})) {
1321 if ($sumfnccount->{$_} > 0) { 1554 if ($sumfnccount->{$_} > 0) {
1322 $hitcount++; 1555 $hitcount++;
1323 } 1556 }
1324 } 1557 }
1325 $data->{"f_hit"} = $hitcount; 1558 $data->{"f_hit"} = $hitcount;
1559
1560 # Get found/hit values for branch data
1561 ($br_found, $br_hit) = get_br_found_and_hit($sumbrcount);
1562
1563 $data->{"b_found"} = $br_found;
1564 $data->{"b_hit"} = $br_hit;
1326 } 1565 }
1327 1566
1328 if (scalar(keys(%result)) == 0) 1567 if (scalar(keys(%result)) == 0)
1329 { 1568 {
1330 die("ERROR: no valid records found in tracefile $tracefile\n"); 1569 die("ERROR: no valid records found in tracefile $tracefile\n");
1331 } 1570 }
1332 if ($negative) 1571 if ($negative)
1333 { 1572 {
1334 warn("WARNING: negative counts found in tracefile ". 1573 warn("WARNING: negative counts found in tracefile ".
1335 "$tracefile\n"); 1574 "$tracefile\n");
(...skipping 19 matching lines...) Expand all
1355 # 1594 #
1356 1595
1357 sub get_info_entry($) 1596 sub get_info_entry($)
1358 { 1597 {
1359 my $testdata_ref = $_[0]->{"test"}; 1598 my $testdata_ref = $_[0]->{"test"};
1360 my $sumcount_ref = $_[0]->{"sum"}; 1599 my $sumcount_ref = $_[0]->{"sum"};
1361 my $funcdata_ref = $_[0]->{"func"}; 1600 my $funcdata_ref = $_[0]->{"func"};
1362 my $checkdata_ref = $_[0]->{"check"}; 1601 my $checkdata_ref = $_[0]->{"check"};
1363 my $testfncdata = $_[0]->{"testfnc"}; 1602 my $testfncdata = $_[0]->{"testfnc"};
1364 my $sumfnccount = $_[0]->{"sumfnc"}; 1603 my $sumfnccount = $_[0]->{"sumfnc"};
1604 my $testbrdata = $_[0]->{"testbr"};
1605 my $sumbrcount = $_[0]->{"sumbr"};
1365 my $lines_found = $_[0]->{"found"}; 1606 my $lines_found = $_[0]->{"found"};
1366 my $lines_hit = $_[0]->{"hit"}; 1607 my $lines_hit = $_[0]->{"hit"};
1367 my $fn_found = $_[0]->{"f_found"}; 1608 my $fn_found = $_[0]->{"f_found"};
1368 my $fn_hit = $_[0]->{"f_hit"}; 1609 my $fn_hit = $_[0]->{"f_hit"};
1610 my $br_found = $_[0]->{"b_found"};
1611 my $br_hit = $_[0]->{"b_hit"};
1369 1612
1370 return ($testdata_ref, $sumcount_ref, $funcdata_ref, $checkdata_ref, 1613 return ($testdata_ref, $sumcount_ref, $funcdata_ref, $checkdata_ref,
1371 » » $testfncdata, $sumfnccount, $lines_found, $lines_hit, 1614 » » $testfncdata, $sumfnccount, $testbrdata, $sumbrcount,
1372 » » $fn_found, $fn_hit); 1615 » » $lines_found, $lines_hit, $fn_found, $fn_hit,
1616 » » $br_found, $br_hit);
1373 } 1617 }
1374 1618
1375 1619
1376 # 1620 #
1377 # set_info_entry(hash_ref, testdata_ref, sumcount_ref, funcdata_ref, 1621 # set_info_entry(hash_ref, testdata_ref, sumcount_ref, funcdata_ref,
1378 # checkdata_ref, testfncdata_ref, sumfcncount_ref[,lines_found, 1622 # checkdata_ref, testfncdata_ref, sumfcncount_ref,
1379 # lines_hit, f_found, f_hit]) 1623 # testbrdata_ref, sumbrcount_ref[,lines_found,
1624 # lines_hit, f_found, f_hit, $b_found, $b_hit])
1380 # 1625 #
1381 # Update the hash referenced by HASH_REF with the provided data references. 1626 # Update the hash referenced by HASH_REF with the provided data references.
1382 # 1627 #
1383 1628
1384 sub set_info_entry($$$$$$$;$$$$) 1629 sub set_info_entry($$$$$$$$$;$$$$$$)
1385 { 1630 {
1386 my $data_ref = $_[0]; 1631 my $data_ref = $_[0];
1387 1632
1388 $data_ref->{"test"} = $_[1]; 1633 $data_ref->{"test"} = $_[1];
1389 $data_ref->{"sum"} = $_[2]; 1634 $data_ref->{"sum"} = $_[2];
1390 $data_ref->{"func"} = $_[3]; 1635 $data_ref->{"func"} = $_[3];
1391 $data_ref->{"check"} = $_[4]; 1636 $data_ref->{"check"} = $_[4];
1392 $data_ref->{"testfnc"} = $_[5]; 1637 $data_ref->{"testfnc"} = $_[5];
1393 $data_ref->{"sumfnc"} = $_[6]; 1638 $data_ref->{"sumfnc"} = $_[6];
1639 $data_ref->{"testbr"} = $_[7];
1640 $data_ref->{"sumbr"} = $_[8];
1394 1641
1395 » if (defined($_[7])) { $data_ref->{"found"} = $_[7]; } 1642 » if (defined($_[9])) { $data_ref->{"found"} = $_[9]; }
1396 » if (defined($_[8])) { $data_ref->{"hit"} = $_[8]; } 1643 » if (defined($_[10])) { $data_ref->{"hit"} = $_[10]; }
1397 » if (defined($_[9])) { $data_ref->{"f_found"} = $_[9]; } 1644 » if (defined($_[11])) { $data_ref->{"f_found"} = $_[11]; }
1398 » if (defined($_[10])) { $data_ref->{"f_hit"} = $_[10]; } 1645 » if (defined($_[12])) { $data_ref->{"f_hit"} = $_[12]; }
1646 » if (defined($_[13])) { $data_ref->{"b_found"} = $_[13]; }
1647 » if (defined($_[14])) { $data_ref->{"b_hit"} = $_[14]; }
1399 } 1648 }
1400 1649
1401 1650
1402 # 1651 #
1403 # add_counts(data1_ref, data2_ref) 1652 # add_counts(data1_ref, data2_ref)
1404 # 1653 #
1405 # DATA1_REF and DATA2_REF are references to hashes containing a mapping 1654 # DATA1_REF and DATA2_REF are references to hashes containing a mapping
1406 # 1655 #
1407 # line number -> execution count 1656 # line number -> execution count
1408 # 1657 #
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1496 # 1745 #
1497 # merge_func_data(funcdata1, funcdata2, filename) 1746 # merge_func_data(funcdata1, funcdata2, filename)
1498 # 1747 #
1499 1748
1500 sub merge_func_data($$$) 1749 sub merge_func_data($$$)
1501 { 1750 {
1502 my ($funcdata1, $funcdata2, $filename) = @_; 1751 my ($funcdata1, $funcdata2, $filename) = @_;
1503 my %result; 1752 my %result;
1504 my $func; 1753 my $func;
1505 1754
1506 » %result = %{$funcdata1}; 1755 » if (defined($funcdata1)) {
1756 » » %result = %{$funcdata1};
1757 » }
1507 1758
1508 foreach $func (keys(%{$funcdata2})) { 1759 foreach $func (keys(%{$funcdata2})) {
1509 my $line1 = $result{$func}; 1760 my $line1 = $result{$func};
1510 my $line2 = $funcdata2->{$func}; 1761 my $line2 = $funcdata2->{$func};
1511 1762
1512 if (defined($line1) && ($line1 != $line2)) { 1763 if (defined($line1) && ($line1 != $line2)) {
1513 warn("WARNING: function data mismatch at ". 1764 warn("WARNING: function data mismatch at ".
1514 "$filename:$line2\n"); 1765 "$filename:$line2\n");
1515 next; 1766 next;
1516 } 1767 }
(...skipping 11 matching lines...) Expand all
1528 # 1779 #
1529 1780
1530 sub add_fnccount($$) 1781 sub add_fnccount($$)
1531 { 1782 {
1532 my ($fnccount1, $fnccount2) = @_; 1783 my ($fnccount1, $fnccount2) = @_;
1533 my %result; 1784 my %result;
1534 my $fn_found; 1785 my $fn_found;
1535 my $fn_hit; 1786 my $fn_hit;
1536 my $function; 1787 my $function;
1537 1788
1538 » %result = %{$fnccount1}; 1789 » if (defined($fnccount1)) {
1790 » » %result = %{$fnccount1};
1791 » }
1539 foreach $function (keys(%{$fnccount2})) { 1792 foreach $function (keys(%{$fnccount2})) {
1540 $result{$function} += $fnccount2->{$function}; 1793 $result{$function} += $fnccount2->{$function};
1541 } 1794 }
1542 $fn_found = scalar(keys(%result)); 1795 $fn_found = scalar(keys(%result));
1543 $fn_hit = 0; 1796 $fn_hit = 0;
1544 foreach $function (keys(%result)) { 1797 foreach $function (keys(%result)) {
1545 if ($result{$function} > 0) { 1798 if ($result{$function} > 0) {
1546 $fn_hit++; 1799 $fn_hit++;
1547 } 1800 }
1548 } 1801 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1582 1835
1583 # Add count data for testnames unique to data set 2 1836 # Add count data for testnames unique to data set 2
1584 foreach $testname (keys(%{$testfncdata2})) { 1837 foreach $testname (keys(%{$testfncdata2})) {
1585 if (!defined($result{$testname})) { 1838 if (!defined($result{$testname})) {
1586 $result{$testname} = $testfncdata2->{$testname}; 1839 $result{$testname} = $testfncdata2->{$testname};
1587 } 1840 }
1588 } 1841 }
1589 return \%result; 1842 return \%result;
1590 } 1843 }
1591 1844
1845
1846 #
1847 # brcount_to_db(brcount)
1848 #
1849 # Convert brcount data to the following format:
1850 #
1851 # db: line number -> block hash
1852 # block hash: block number -> branch hash
1853 # branch hash: branch number -> taken value
1854 #
1855
1856 sub brcount_to_db($)
1857 {
1858 my ($brcount) = @_;
1859 my $line;
1860 my $db;
1861
1862 # Add branches from first count to database
1863 foreach $line (keys(%{$brcount})) {
1864 my $brdata = $brcount->{$line};
1865 my $i;
1866 my $num = br_ivec_len($brdata);
1867
1868 for ($i = 0; $i < $num; $i++) {
1869 my ($block, $branch, $taken) = br_ivec_get($brdata, $i);
1870
1871 $db->{$line}->{$block}->{$branch} = $taken;
1872 }
1873 }
1874
1875 return $db;
1876 }
1877
1878
1879 #
1880 # db_to_brcount(db)
1881 #
1882 # Convert branch coverage data back to brcount format.
1883 #
1884
1885 sub db_to_brcount($)
1886 {
1887 my ($db) = @_;
1888 my $line;
1889 my $brcount = {};
1890 my $br_found = 0;
1891 my $br_hit = 0;
1892
1893 # Convert database back to brcount format
1894 foreach $line (sort({$a <=> $b} keys(%{$db}))) {
1895 my $ldata = $db->{$line};
1896 my $brdata;
1897 my $block;
1898
1899 foreach $block (sort({$a <=> $b} keys(%{$ldata}))) {
1900 my $bdata = $ldata->{$block};
1901 my $branch;
1902
1903 foreach $branch (sort({$a <=> $b} keys(%{$bdata}))) {
1904 my $taken = $bdata->{$branch};
1905
1906 $br_found++;
1907 $br_hit++ if ($taken ne "-" && $taken > 0);
1908 $brdata = br_ivec_push($brdata, $block,
1909 $branch, $taken);
1910 }
1911 }
1912 $brcount->{$line} = $brdata;
1913 }
1914
1915 return ($brcount, $br_found, $br_hit);
1916 }
1917
1918
1919 #
1920 # combine_brcount(brcount1, brcount2, type)
1921 #
1922 # If add is BR_ADD, add branch coverage data and return list (brcount_added,
1923 # br_found, br_hit). If add is BR_SUB, subtract the taken values of brcount2
1924 # from brcount1 and return (brcount_sub, br_found, br_hit).
1925 #
1926
1927 sub combine_brcount($$$)
1928 {
1929 my ($brcount1, $brcount2, $type) = @_;
1930 my $line;
1931 my $block;
1932 my $branch;
1933 my $taken;
1934 my $db;
1935 my $br_found = 0;
1936 my $br_hit = 0;
1937 my $result;
1938
1939 # Convert branches from first count to database
1940 $db = brcount_to_db($brcount1);
1941 # Combine values from database and second count
1942 foreach $line (keys(%{$brcount2})) {
1943 my $brdata = $brcount2->{$line};
1944 my $num = br_ivec_len($brdata);
1945 my $i;
1946
1947 for ($i = 0; $i < $num; $i++) {
1948 ($block, $branch, $taken) = br_ivec_get($brdata, $i);
1949 my $new_taken = $db->{$line}->{$block}->{$branch};
1950
1951 if ($type == $BR_ADD) {
1952 $new_taken = br_taken_add($new_taken, $taken);
1953 } elsif ($type == $BR_SUB) {
1954 $new_taken = br_taken_sub($new_taken, $taken);
1955 }
1956 $db->{$line}->{$block}->{$branch} = $new_taken
1957 if (defined($new_taken));
1958 }
1959 }
1960 # Convert database back to brcount format
1961 ($result, $br_found, $br_hit) = db_to_brcount($db);
1962
1963 return ($result, $br_found, $br_hit);
1964 }
1965
1966
1967 #
1968 # add_testbrdata(testbrdata1, testbrdata2)
1969 #
1970 # Add branch coverage data for several tests. Return reference to
1971 # added_testbrdata.
1972 #
1973
1974 sub add_testbrdata($$)
1975 {
1976 my ($testbrdata1, $testbrdata2) = @_;
1977 my %result;
1978 my $testname;
1979
1980 foreach $testname (keys(%{$testbrdata1})) {
1981 if (defined($testbrdata2->{$testname})) {
1982 my $brcount;
1983
1984 # Branch coverage data for this testname exists
1985 # in both data sets: add
1986 ($brcount) = combine_brcount($testbrdata1->{$testname},
1987 $testbrdata2->{$testname}, $BR_ADD);
1988 $result{$testname} = $brcount;
1989 next;
1990 }
1991 # Branch coverage data for this testname is unique to
1992 # data set 1: copy
1993 $result{$testname} = $testbrdata1->{$testname};
1994 }
1995
1996 # Add count data for testnames unique to data set 2
1997 foreach $testname (keys(%{$testbrdata2})) {
1998 if (!defined($result{$testname})) {
1999 $result{$testname} = $testbrdata2->{$testname};
2000 }
2001 }
2002 return \%result;
2003 }
2004
2005
1592 # 2006 #
1593 # combine_info_entries(entry_ref1, entry_ref2, filename) 2007 # combine_info_entries(entry_ref1, entry_ref2, filename)
1594 # 2008 #
1595 # Combine .info data entry hashes referenced by ENTRY_REF1 and ENTRY_REF2. 2009 # Combine .info data entry hashes referenced by ENTRY_REF1 and ENTRY_REF2.
1596 # Return reference to resulting hash. 2010 # Return reference to resulting hash.
1597 # 2011 #
1598 2012
1599 sub combine_info_entries($$$) 2013 sub combine_info_entries($$$)
1600 { 2014 {
1601 my $entry1 = $_[0]; # Reference to hash containing first entry 2015 my $entry1 = $_[0]; # Reference to hash containing first entry
1602 my $testdata1; 2016 my $testdata1;
1603 my $sumcount1; 2017 my $sumcount1;
1604 my $funcdata1; 2018 my $funcdata1;
1605 my $checkdata1; 2019 my $checkdata1;
1606 my $testfncdata1; 2020 my $testfncdata1;
1607 my $sumfnccount1; 2021 my $sumfnccount1;
2022 my $testbrdata1;
2023 my $sumbrcount1;
1608 2024
1609 my $entry2 = $_[1]; # Reference to hash containing second entry 2025 my $entry2 = $_[1]; # Reference to hash containing second entry
1610 my $testdata2; 2026 my $testdata2;
1611 my $sumcount2; 2027 my $sumcount2;
1612 my $funcdata2; 2028 my $funcdata2;
1613 my $checkdata2; 2029 my $checkdata2;
1614 my $testfncdata2; 2030 my $testfncdata2;
1615 my $sumfnccount2; 2031 my $sumfnccount2;
2032 my $testbrdata2;
2033 my $sumbrcount2;
1616 2034
1617 my %result; # Hash containing combined entry 2035 my %result; # Hash containing combined entry
1618 my %result_testdata; 2036 my %result_testdata;
1619 my $result_sumcount = {}; 2037 my $result_sumcount = {};
1620 my $result_funcdata; 2038 my $result_funcdata;
1621 my $result_testfncdata; 2039 my $result_testfncdata;
1622 my $result_sumfnccount; 2040 my $result_sumfnccount;
2041 my $result_testbrdata;
2042 my $result_sumbrcount;
1623 my $lines_found; 2043 my $lines_found;
1624 my $lines_hit; 2044 my $lines_hit;
1625 my $fn_found; 2045 my $fn_found;
1626 my $fn_hit; 2046 my $fn_hit;
2047 my $br_found;
2048 my $br_hit;
1627 2049
1628 my $testname; 2050 my $testname;
1629 my $filename = $_[2]; 2051 my $filename = $_[2];
1630 2052
1631 # Retrieve data 2053 # Retrieve data
1632 ($testdata1, $sumcount1, $funcdata1, $checkdata1, $testfncdata1, 2054 ($testdata1, $sumcount1, $funcdata1, $checkdata1, $testfncdata1,
1633 » $sumfnccount1) = get_info_entry($entry1); 2055 » $sumfnccount1, $testbrdata1, $sumbrcount1) = get_info_entry($entry1);
1634 ($testdata2, $sumcount2, $funcdata2, $checkdata2, $testfncdata2, 2056 ($testdata2, $sumcount2, $funcdata2, $checkdata2, $testfncdata2,
1635 » $sumfnccount2) = get_info_entry($entry2); 2057 » $sumfnccount2, $testbrdata2, $sumbrcount2) = get_info_entry($entry2);
1636 2058
1637 # Merge checksums 2059 # Merge checksums
1638 $checkdata1 = merge_checksums($checkdata1, $checkdata2, $filename); 2060 $checkdata1 = merge_checksums($checkdata1, $checkdata2, $filename);
1639 2061
1640 # Combine funcdata 2062 # Combine funcdata
1641 $result_funcdata = merge_func_data($funcdata1, $funcdata2, $filename); 2063 $result_funcdata = merge_func_data($funcdata1, $funcdata2, $filename);
1642 2064
1643 # Combine function call count data 2065 # Combine function call count data
1644 $result_testfncdata = add_testfncdata($testfncdata1, $testfncdata2); 2066 $result_testfncdata = add_testfncdata($testfncdata1, $testfncdata2);
1645 ($result_sumfnccount, $fn_found, $fn_hit) = 2067 ($result_sumfnccount, $fn_found, $fn_hit) =
1646 add_fnccount($sumfnccount1, $sumfnccount2); 2068 add_fnccount($sumfnccount1, $sumfnccount2);
1647 2069
2070 # Combine branch coverage data
2071 $result_testbrdata = add_testbrdata($testbrdata1, $testbrdata2);
2072 ($result_sumbrcount, $br_found, $br_hit) =
2073 combine_brcount($sumbrcount1, $sumbrcount2, $BR_ADD);
2074
1648 # Combine testdata 2075 # Combine testdata
1649 foreach $testname (keys(%{$testdata1})) 2076 foreach $testname (keys(%{$testdata1}))
1650 { 2077 {
1651 if (defined($testdata2->{$testname})) 2078 if (defined($testdata2->{$testname}))
1652 { 2079 {
1653 # testname is present in both entries, requires 2080 # testname is present in both entries, requires
1654 # combination 2081 # combination
1655 ($result_testdata{$testname}) = 2082 ($result_testdata{$testname}) =
1656 add_counts($testdata1->{$testname}, 2083 add_counts($testdata1->{$testname},
1657 $testdata2->{$testname}); 2084 $testdata2->{$testname});
(...skipping 22 matching lines...) Expand all
1680 ($result_sumcount, $lines_found, $lines_hit) = 2107 ($result_sumcount, $lines_found, $lines_hit) =
1681 add_counts($result_sumcount, 2108 add_counts($result_sumcount,
1682 $result_testdata{$testname}); 2109 $result_testdata{$testname});
1683 } 2110 }
1684 2111
1685 # Calculate resulting sumcount 2112 # Calculate resulting sumcount
1686 2113
1687 # Store result 2114 # Store result
1688 set_info_entry(\%result, \%result_testdata, $result_sumcount, 2115 set_info_entry(\%result, \%result_testdata, $result_sumcount,
1689 $result_funcdata, $checkdata1, $result_testfncdata, 2116 $result_funcdata, $checkdata1, $result_testfncdata,
1690 » » $result_sumfnccount, $lines_found, $lines_hit, 2117 » » $result_sumfnccount, $result_testbrdata,
1691 » » $fn_found, $fn_hit); 2118 » » $result_sumbrcount, $lines_found, $lines_hit,
2119 » » $fn_found, $fn_hit, $br_found, $br_hit);
1692 2120
1693 return(\%result); 2121 return(\%result);
1694 } 2122 }
1695 2123
1696 2124
1697 # 2125 #
1698 # combine_info_files(info_ref1, info_ref2) 2126 # combine_info_files(info_ref1, info_ref2)
1699 # 2127 #
1700 # Combine .info data in hashes referenced by INFO_REF1 and INFO_REF2. Return 2128 # Combine .info data in hashes referenced by INFO_REF1 and INFO_REF2. Return
1701 # reference to resulting hash. 2129 # reference to resulting hash.
(...skipping 21 matching lines...) Expand all
1723 # resulting hash 2151 # resulting hash
1724 $hash1{$filename} = $hash2{$filename}; 2152 $hash1{$filename} = $hash2{$filename};
1725 } 2153 }
1726 } 2154 }
1727 2155
1728 return(\%hash1); 2156 return(\%hash1);
1729 } 2157 }
1730 2158
1731 2159
1732 # 2160 #
1733 # get_prefix(filename_list) 2161 # get_prefix(min_dir, filename_list)
1734 # 2162 #
1735 # Search FILENAME_LIST for a directory prefix which is common to as many 2163 # Search FILENAME_LIST for a directory prefix which is common to as many
1736 # list entries as possible, so that removing this prefix will minimize the 2164 # list entries as possible, so that removing this prefix will minimize the
1737 # sum of the lengths of all resulting shortened filenames. 2165 # sum of the lengths of all resulting shortened filenames while observing
2166 # that no filename has less than MIN_DIR parent directories.
1738 # 2167 #
1739 2168
1740 sub get_prefix(@) 2169 sub get_prefix($@)
1741 { 2170 {
1742 » my @filename_list = @_;»» # provided list of filenames 2171 » my ($min_dir, @filename_list) = @_;
1743 my %prefix; # mapping: prefix -> sum of lengths 2172 my %prefix; # mapping: prefix -> sum of lengths
1744 my $current; # Temporary iteration variable 2173 my $current; # Temporary iteration variable
1745 2174
1746 # Find list of prefixes 2175 # Find list of prefixes
1747 foreach (@filename_list) 2176 foreach (@filename_list)
1748 { 2177 {
1749 # Need explicit assignment to get a copy of $_ so that 2178 # Need explicit assignment to get a copy of $_ so that
1750 # shortening the contained prefix does not affect the list 2179 # shortening the contained prefix does not affect the list
1751 » » $current = shorten_prefix($_); 2180 » » $current = $_;
1752 while ($current = shorten_prefix($current)) 2181 while ($current = shorten_prefix($current))
1753 { 2182 {
2183 $current .= "/";
2184
1754 # Skip rest if the remaining prefix has already been 2185 # Skip rest if the remaining prefix has already been
1755 # added to hash 2186 # added to hash
1756 » » » if ($prefix{$current}) { last; } 2187 » » » if (exists($prefix{$current})) { last; }
1757 2188
1758 # Initialize with 0 2189 # Initialize with 0
1759 $prefix{$current}="0"; 2190 $prefix{$current}="0";
1760 } 2191 }
1761 2192
1762 } 2193 }
1763 2194
2195 # Remove all prefixes that would cause filenames to have less than
2196 # the minimum number of parent directories
2197 foreach my $filename (@filename_list) {
2198 my $dir = dirname($filename);
2199
2200 for (my $i = 0; $i < $min_dir; $i++) {
2201 delete($prefix{$dir."/"});
2202 $dir = shorten_prefix($dir);
2203 }
2204 }
2205
2206 # Check if any prefix remains
2207 return undef if (!%prefix);
2208
1764 # Calculate sum of lengths for all prefixes 2209 # Calculate sum of lengths for all prefixes
1765 foreach $current (keys(%prefix)) 2210 foreach $current (keys(%prefix))
1766 { 2211 {
1767 foreach (@filename_list) 2212 foreach (@filename_list)
1768 { 2213 {
1769 # Add original length 2214 # Add original length
1770 $prefix{$current} += length($_); 2215 $prefix{$current} += length($_);
1771 2216
1772 # Check whether prefix matches 2217 # Check whether prefix matches
1773 if (substr($_, 0, length($current)) eq $current) 2218 if (substr($_, 0, length($current)) eq $current)
1774 { 2219 {
1775 # Subtract prefix length for this filename 2220 # Subtract prefix length for this filename
1776 $prefix{$current} -= length($current); 2221 $prefix{$current} -= length($current);
1777 } 2222 }
1778 } 2223 }
1779 } 2224 }
1780 2225
1781 # Find and return prefix with minimal sum 2226 # Find and return prefix with minimal sum
1782 $current = (keys(%prefix))[0]; 2227 $current = (keys(%prefix))[0];
1783 2228
1784 foreach (keys(%prefix)) 2229 foreach (keys(%prefix))
1785 { 2230 {
1786 if ($prefix{$_} < $prefix{$current}) 2231 if ($prefix{$_} < $prefix{$current})
1787 { 2232 {
1788 $current = $_; 2233 $current = $_;
1789 } 2234 }
1790 } 2235 }
1791 2236
2237 $current =~ s/\/$//;
2238
1792 return($current); 2239 return($current);
1793 } 2240 }
1794 2241
1795 2242
1796 # 2243 #
1797 # shorten_prefix(prefix) 2244 # shorten_prefix(prefix)
1798 # 2245 #
1799 # Return PREFIX shortened by last directory component. 2246 # Return PREFIX shortened by last directory component.
1800 # 2247 #
1801 2248
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1873 # Die on error. 2320 # Die on error.
1874 # 2321 #
1875 2322
1876 sub read_testfile($) 2323 sub read_testfile($)
1877 { 2324 {
1878 my %result; 2325 my %result;
1879 my $test_name; 2326 my $test_name;
1880 my $changed_testname; 2327 my $changed_testname;
1881 local *TEST_HANDLE; 2328 local *TEST_HANDLE;
1882 2329
1883 » open(TEST_HANDLE, "<".$_[0]) 2330 » open(TEST_HANDLE, "<", $_[0])
1884 or die("ERROR: cannot open $_[0]!\n"); 2331 or die("ERROR: cannot open $_[0]!\n");
1885 2332
1886 while (<TEST_HANDLE>) 2333 while (<TEST_HANDLE>)
1887 { 2334 {
1888 chomp($_); 2335 chomp($_);
1889 2336
1890 # Match lines beginning with TN:<whitespace(s)> 2337 # Match lines beginning with TN:<whitespace(s)>
1891 if (/^TN:\s+(.*?)\s*$/) 2338 if (/^TN:\s+(.*?)\s*$/)
1892 { 2339 {
1893 # Store name for later use 2340 # Store name for later use
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1979 # create_sub_dir(dir_name) 2426 # create_sub_dir(dir_name)
1980 # 2427 #
1981 # Create subdirectory DIR_NAME if it does not already exist, including all its 2428 # Create subdirectory DIR_NAME if it does not already exist, including all its
1982 # parent directories. 2429 # parent directories.
1983 # 2430 #
1984 # Die on error. 2431 # Die on error.
1985 # 2432 #
1986 2433
1987 sub create_sub_dir($) 2434 sub create_sub_dir($)
1988 { 2435 {
1989 » system("mkdir", "-p" ,$_[0]) 2436 » my ($dir) = @_;
1990 » » and die("ERROR: cannot create directory $_!\n"); 2437
2438 » system("mkdir", "-p" ,$dir)
2439 » » and die("ERROR: cannot create directory $dir!\n");
1991 } 2440 }
1992 2441
1993 2442
1994 # 2443 #
1995 # write_description_file(descriptions, overall_found, overall_hit, 2444 # write_description_file(descriptions, overall_found, overall_hit,
1996 # total_fn_found, total_fn_hit) 2445 # total_fn_found, total_fn_hit, total_br_found,
2446 # total_br_hit)
1997 # 2447 #
1998 # Write HTML file containing all test case descriptions. DESCRIPTIONS is a 2448 # Write HTML file containing all test case descriptions. DESCRIPTIONS is a
1999 # reference to a hash containing a mapping 2449 # reference to a hash containing a mapping
2000 # 2450 #
2001 # test case name -> test case description 2451 # test case name -> test case description
2002 # 2452 #
2003 # Die on error. 2453 # Die on error.
2004 # 2454 #
2005 2455
2006 sub write_description_file($$$$$) 2456 sub write_description_file($$$$$$$)
2007 { 2457 {
2008 my %description = %{$_[0]}; 2458 my %description = %{$_[0]};
2009 my $found = $_[1]; 2459 my $found = $_[1];
2010 my $hit = $_[2]; 2460 my $hit = $_[2];
2011 my $fn_found = $_[3]; 2461 my $fn_found = $_[3];
2012 my $fn_hit = $_[4]; 2462 my $fn_hit = $_[4];
2463 my $br_found = $_[5];
2464 my $br_hit = $_[6];
2013 my $test_name; 2465 my $test_name;
2014 local *HTML_HANDLE; 2466 local *HTML_HANDLE;
2015 2467
2016 html_create(*HTML_HANDLE,"descriptions.$html_ext"); 2468 html_create(*HTML_HANDLE,"descriptions.$html_ext");
2017 write_html_prolog(*HTML_HANDLE, "", "LCOV - test case descriptions"); 2469 write_html_prolog(*HTML_HANDLE, "", "LCOV - test case descriptions");
2018 write_header(*HTML_HANDLE, 3, "", "", $found, $hit, $fn_found, 2470 write_header(*HTML_HANDLE, 3, "", "", $found, $hit, $fn_found,
2019 » » $fn_hit, 0); 2471 » » $fn_hit, $br_found, $br_hit, 0);
2020 2472
2021 write_test_table_prolog(*HTML_HANDLE, 2473 write_test_table_prolog(*HTML_HANDLE,
2022 "Test case descriptions - alphabetical list"); 2474 "Test case descriptions - alphabetical list");
2023 2475
2024 foreach $test_name (sort(keys(%description))) 2476 foreach $test_name (sort(keys(%description)))
2025 { 2477 {
2026 write_test_table_entry(*HTML_HANDLE, $test_name, 2478 write_test_table_entry(*HTML_HANDLE, $test_name,
2027 escape_html($description{$test_name})); 2479 escape_html($description{$test_name}));
2028 } 2480 }
2029 2481
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2139 0x54, 0x28, 0xcf, 0x63, 0x60, 0x40, 0x03, 0xff, 0xa1, 0x00, 2591 0x54, 0x28, 0xcf, 0x63, 0x60, 0x40, 0x03, 0xff, 0xa1, 0x00,
2140 0x5d, 0x9c, 0x11, 0x5d, 0x11, 0x8a, 0x24, 0x23, 0x23, 0x23, 2592 0x5d, 0x9c, 0x11, 0x5d, 0x11, 0x8a, 0x24, 0x23, 0x23, 0x23,
2141 0x86, 0x42, 0x6c, 0xa6, 0x20, 0x2b, 0x66, 0xc4, 0xa7, 0x08, 2593 0x86, 0x42, 0x6c, 0xa6, 0x20, 0x2b, 0x66, 0xc4, 0xa7, 0x08,
2142 0x59, 0x31, 0x23, 0x21, 0x45, 0x30, 0xc0, 0xc4, 0x30, 0x60, 2594 0x59, 0x31, 0x23, 0x21, 0x45, 0x30, 0xc0, 0xc4, 0x30, 0x60,
2143 0x80, 0xfa, 0x6e, 0x24, 0x3e, 0x78, 0x48, 0x0a, 0x70, 0x62, 2595 0x80, 0xfa, 0x6e, 0x24, 0x3e, 0x78, 0x48, 0x0a, 0x70, 0x62,
2144 0xa2, 0x90, 0x81, 0xd8, 0x44, 0x01, 0x00, 0xe9, 0x5c, 0x2f, 2596 0xa2, 0x90, 0x81, 0xd8, 0x44, 0x01, 0x00, 0xe9, 0x5c, 0x2f,
2145 0xf5, 0xe2, 0x9d, 0x0f, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x49, 2597 0xf5, 0xe2, 0x9d, 0x0f, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x49,
2146 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82] if ($sort); 2598 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82] if ($sort);
2147 foreach (keys(%data)) 2599 foreach (keys(%data))
2148 { 2600 {
2149 » » open(PNG_HANDLE, ">".$_) 2601 » » open(PNG_HANDLE, ">", $_)
2150 or die("ERROR: cannot create $_!\n"); 2602 or die("ERROR: cannot create $_!\n");
2151 binmode(PNG_HANDLE); 2603 binmode(PNG_HANDLE);
2152 print(PNG_HANDLE map(chr,@{$data{$_}})); 2604 print(PNG_HANDLE map(chr,@{$data{$_}}));
2153 close(PNG_HANDLE); 2605 close(PNG_HANDLE);
2154 } 2606 }
2155 } 2607 }
2156 2608
2157 2609
2158 # 2610 #
2159 # write_htaccess_file() 2611 # write_htaccess_file()
2160 # 2612 #
2161 2613
2162 sub write_htaccess_file() 2614 sub write_htaccess_file()
2163 { 2615 {
2164 local *HTACCESS_HANDLE; 2616 local *HTACCESS_HANDLE;
2165 my $htaccess_data; 2617 my $htaccess_data;
2166 2618
2167 » open(*HTACCESS_HANDLE, ">.htaccess") 2619 » open(*HTACCESS_HANDLE, ">", ".htaccess")
2168 or die("ERROR: cannot open .htaccess for writing!\n"); 2620 or die("ERROR: cannot open .htaccess for writing!\n");
2169 2621
2170 $htaccess_data = (<<"END_OF_HTACCESS") 2622 $htaccess_data = (<<"END_OF_HTACCESS")
2171 AddEncoding x-gzip .html 2623 AddEncoding x-gzip .html
2172 END_OF_HTACCESS 2624 END_OF_HTACCESS
2173 ; 2625 ;
2174 2626
2175 print(HTACCESS_HANDLE $htaccess_data); 2627 print(HTACCESS_HANDLE $htaccess_data);
2176 close(*HTACCESS_HANDLE); 2628 close(*HTACCESS_HANDLE);
2177 } 2629 }
(...skipping 12 matching lines...) Expand all
2190 2642
2191 # Check for a specified external style sheet file 2643 # Check for a specified external style sheet file
2192 if ($css_filename) 2644 if ($css_filename)
2193 { 2645 {
2194 # Simply copy that file 2646 # Simply copy that file
2195 system("cp", $css_filename, "gcov.css") 2647 system("cp", $css_filename, "gcov.css")
2196 and die("ERROR: cannot copy file $css_filename!\n"); 2648 and die("ERROR: cannot copy file $css_filename!\n");
2197 return; 2649 return;
2198 } 2650 }
2199 2651
2200 » open(CSS_HANDLE, ">gcov.css") 2652 » open(CSS_HANDLE, ">", "gcov.css")
2201 or die ("ERROR: cannot open gcov.css for writing!\n"); 2653 or die ("ERROR: cannot open gcov.css for writing!\n");
2202 2654
2203 2655
2204 # ************************************************************* 2656 # *************************************************************
2205 2657
2206 my $css_data = ($_=<<"END_OF_CSS") 2658 my $css_data = ($_=<<"END_OF_CSS")
2207 /* All views: initial background and text color */ 2659 /* All views: initial background and text color */
2208 body 2660 body
2209 { 2661 {
2210 color: #000000; 2662 color: #000000;
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
2321 text-align: right; 2773 text-align: right;
2322 color: #000000; 2774 color: #000000;
2323 font-family: sans-serif; 2775 font-family: sans-serif;
2324 font-weight: bold; 2776 font-weight: bold;
2325 white-space: nowrap; 2777 white-space: nowrap;
2326 padding-left: 12px; 2778 padding-left: 12px;
2327 padding-right: 4px; 2779 padding-right: 4px;
2328 background-color: #FF0000; 2780 background-color: #FF0000;
2329 } 2781 }
2330 2782
2331 /* All views: header legend item for legend entry */
2332 td.headerItemLeg
2333 {
2334 text-align: right;
2335 padding-right: 6px;
2336 font-family: sans-serif;
2337 font-weight: bold;
2338 vertical-align: bottom;
2339 white-space: nowrap;
2340 }
2341
2342 /* All views: header legend value for legend entry */ 2783 /* All views: header legend value for legend entry */
2343 td.headerValueLeg 2784 td.headerValueLeg
2344 { 2785 {
2345 text-align: left; 2786 text-align: left;
2346 color: #000000; 2787 color: #000000;
2347 font-family: sans-serif; 2788 font-family: sans-serif;
2348 font-size: 80%; 2789 font-size: 80%;
2349 white-space: nowrap; 2790 white-space: nowrap;
2350 padding-top: 4px; 2791 padding-top: 4px;
2351 } 2792 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2412 2853
2413 /* Directory view/File view (all): percentage entry for files with 2854 /* Directory view/File view (all): percentage entry for files with
2414 high coverage rate */ 2855 high coverage rate */
2415 td.coverPerHi 2856 td.coverPerHi
2416 { 2857 {
2417 text-align: right; 2858 text-align: right;
2418 padding-left: 10px; 2859 padding-left: 10px;
2419 padding-right: 10px; 2860 padding-right: 10px;
2420 background-color: #A7FC9D; 2861 background-color: #A7FC9D;
2421 font-weight: bold; 2862 font-weight: bold;
2863 font-family: sans-serif;
2422 } 2864 }
2423 2865
2424 /* Directory view/File view (all): line count entry for files with 2866 /* Directory view/File view (all): line count entry for files with
2425 high coverage rate */ 2867 high coverage rate */
2426 td.coverNumHi 2868 td.coverNumHi
2427 { 2869 {
2428 text-align: right; 2870 text-align: right;
2429 padding-left: 10px; 2871 padding-left: 10px;
2430 padding-right: 10px; 2872 padding-right: 10px;
2431 background-color: #A7FC9D; 2873 background-color: #A7FC9D;
2432 white-space: nowrap; 2874 white-space: nowrap;
2433 » } 2875 » font-family: sans-serif;
2434 »
2435 » /* Directory view/File view (all): legend entry for high coverage
2436 » rate */
2437 » span.coverLegendHi
2438 » {
2439 » padding-left: 10px;
2440 » padding-right: 10px;
2441 » padding-bottom: 2px;
2442 » background-color: #A7FC9D;
2443 } 2876 }
2444 2877
2445 /* Directory view/File view (all): percentage entry for files with 2878 /* Directory view/File view (all): percentage entry for files with
2446 medium coverage rate */ 2879 medium coverage rate */
2447 td.coverPerMed 2880 td.coverPerMed
2448 { 2881 {
2449 text-align: right; 2882 text-align: right;
2450 padding-left: 10px; 2883 padding-left: 10px;
2451 padding-right: 10px; 2884 padding-right: 10px;
2452 background-color: #FFEA20; 2885 background-color: #FFEA20;
2453 font-weight: bold; 2886 font-weight: bold;
2887 font-family: sans-serif;
2454 } 2888 }
2455 2889
2456 /* Directory view/File view (all): line count entry for files with 2890 /* Directory view/File view (all): line count entry for files with
2457 medium coverage rate */ 2891 medium coverage rate */
2458 td.coverNumMed 2892 td.coverNumMed
2459 { 2893 {
2460 text-align: right; 2894 text-align: right;
2461 padding-left: 10px; 2895 padding-left: 10px;
2462 padding-right: 10px; 2896 padding-right: 10px;
2463 background-color: #FFEA20; 2897 background-color: #FFEA20;
2464 white-space: nowrap; 2898 white-space: nowrap;
2465 » } 2899 » font-family: sans-serif;
2466 »
2467 » /* Directory view/File view (all): legend entry for medium coverage
2468 » rate */
2469 » span.coverLegendMed
2470 » {
2471 » padding-left: 10px;
2472 » padding-right: 10px;
2473 » padding-bottom: 2px;
2474 » background-color: #FFEA20;
2475 } 2900 }
2476 2901
2477 /* Directory view/File view (all): percentage entry for files with 2902 /* Directory view/File view (all): percentage entry for files with
2478 low coverage rate */ 2903 low coverage rate */
2479 td.coverPerLo 2904 td.coverPerLo
2480 { 2905 {
2481 text-align: right; 2906 text-align: right;
2482 padding-left: 10px; 2907 padding-left: 10px;
2483 padding-right: 10px; 2908 padding-right: 10px;
2484 background-color: #FF0000; 2909 background-color: #FF0000;
2485 font-weight: bold; 2910 font-weight: bold;
2911 font-family: sans-serif;
2486 } 2912 }
2487 2913
2488 /* Directory view/File view (all): line count entry for files with 2914 /* Directory view/File view (all): line count entry for files with
2489 low coverage rate */ 2915 low coverage rate */
2490 td.coverNumLo 2916 td.coverNumLo
2491 { 2917 {
2492 text-align: right; 2918 text-align: right;
2493 padding-left: 10px; 2919 padding-left: 10px;
2494 padding-right: 10px; 2920 padding-right: 10px;
2495 background-color: #FF0000; 2921 background-color: #FF0000;
2496 white-space: nowrap; 2922 white-space: nowrap;
2497 » } 2923 » font-family: sans-serif;
2498 »
2499 » /* Directory view/File view (all): legend entry for low coverage
2500 » rate */
2501 » span.coverLegendLo
2502 » {
2503 » padding-left: 10px;
2504 » padding-right: 10px;
2505 » padding-bottom: 2px;
2506 » background-color: #FF0000;
2507 } 2924 }
2508 2925
2509 /* File view (all): "show/hide details" link format */ 2926 /* File view (all): "show/hide details" link format */
2510 a.detail:link 2927 a.detail:link
2511 { 2928 {
2512 color: #B8D0FF; 2929 color: #B8D0FF;
2930 font-size:80%;
2513 } 2931 }
2514 2932
2515 /* File view (all): "show/hide details" link - visited format */ 2933 /* File view (all): "show/hide details" link - visited format */
2516 a.detail:visited 2934 a.detail:visited
2517 { 2935 {
2518 color: #B8D0FF; 2936 color: #B8D0FF;
2937 font-size:80%;
2519 } 2938 }
2520 2939
2521 /* File view (all): "show/hide details" link - activated format */ 2940 /* File view (all): "show/hide details" link - activated format */
2522 a.detail:active 2941 a.detail:active
2523 { 2942 {
2524 color: #FFFFFF; 2943 color: #FFFFFF;
2525 » } 2944 » font-size:80%;
2526 »
2527 » /* File view (detail): test name table headline format */
2528 » td.testNameHead
2529 » {
2530 » text-align: right;
2531 » padding-right: 10px;
2532 » background-color: #DAE7FE;
2533 » font-family: sans-serif;
2534 » font-weight: bold;
2535 » }
2536 »
2537 » /* File view (detail): test lines table headline format */
2538 » td.testLinesHead
2539 » {
2540 » text-align: center;
2541 » background-color: #DAE7FE;
2542 » font-family: sans-serif;
2543 » font-weight: bold;
2544 } 2945 }
2545 2946
2546 /* File view (detail): test name entry */ 2947 /* File view (detail): test name entry */
2547 td.testName 2948 td.testName
2548 { 2949 {
2549 text-align: right; 2950 text-align: right;
2550 padding-right: 10px; 2951 padding-right: 10px;
2551 background-color: #DAE7FE; 2952 background-color: #DAE7FE;
2953 font-family: sans-serif;
2552 } 2954 }
2553 2955
2554 /* File view (detail): test percentage entry */ 2956 /* File view (detail): test percentage entry */
2555 td.testPer 2957 td.testPer
2556 { 2958 {
2557 text-align: right; 2959 text-align: right;
2558 padding-left: 10px; 2960 padding-left: 10px;
2559 padding-right: 10px; 2961 padding-right: 10px;
2560 background-color: #DAE7FE; 2962 background-color: #DAE7FE;
2963 font-family: sans-serif;
2561 } 2964 }
2562 2965
2563 /* File view (detail): test lines count entry */ 2966 /* File view (detail): test lines count entry */
2564 td.testNum 2967 td.testNum
2565 { 2968 {
2566 text-align: right; 2969 text-align: right;
2567 padding-left: 10px; 2970 padding-left: 10px;
2568 padding-right: 10px; 2971 padding-right: 10px;
2569 background-color: #DAE7FE; 2972 background-color: #DAE7FE;
2973 font-family: sans-serif;
2570 } 2974 }
2571 2975
2572 /* Test case descriptions: test name format*/ 2976 /* Test case descriptions: test name format*/
2573 dt 2977 dt
2574 { 2978 {
2575 font-family: sans-serif; 2979 font-family: sans-serif;
2576 font-weight: bold; 2980 font-weight: bold;
2577 } 2981 }
2578 2982
2579 /* Test case descriptions: description table body */ 2983 /* Test case descriptions: description table body */
(...skipping 18 matching lines...) Expand all
2598 } 3002 }
2599 3003
2600 /* Source code view: function entry zero count*/ 3004 /* Source code view: function entry zero count*/
2601 td.coverFnLo 3005 td.coverFnLo
2602 { 3006 {
2603 text-align: right; 3007 text-align: right;
2604 padding-left: 10px; 3008 padding-left: 10px;
2605 padding-right: 10px; 3009 padding-right: 10px;
2606 background-color: #FF0000; 3010 background-color: #FF0000;
2607 font-weight: bold; 3011 font-weight: bold;
3012 font-family: sans-serif;
2608 } 3013 }
2609 3014
2610 /* Source code view: function entry nonzero count*/ 3015 /* Source code view: function entry nonzero count*/
2611 td.coverFnHi 3016 td.coverFnHi
2612 { 3017 {
2613 text-align: right; 3018 text-align: right;
2614 padding-left: 10px; 3019 padding-left: 10px;
2615 padding-right: 10px; 3020 padding-right: 10px;
2616 background-color: #DAE7FE; 3021 background-color: #DAE7FE;
2617 font-weight: bold; 3022 font-weight: bold;
3023 font-family: sans-serif;
2618 } 3024 }
2619 3025
2620 /* Source code view: source code format */ 3026 /* Source code view: source code format */
2621 /* Source code view: source code format */
2622 pre.source 3027 pre.source
2623 { 3028 {
2624 font-family: monospace; 3029 font-family: monospace;
2625 white-space: pre; 3030 white-space: pre;
3031 margin-top: 2px;
2626 } 3032 }
2627 3033
2628 /* Source code view: line number format */ 3034 /* Source code view: line number format */
2629 span.lineNum 3035 span.lineNum
2630 { 3036 {
2631 background-color: #EFE383; 3037 background-color: #EFE383;
2632 } 3038 }
2633 3039
2634 /* Source code view: format for lines which were executed */ 3040 /* Source code view: format for lines which were executed */
2635 td.lineCov, 3041 td.lineCov,
(...skipping 17 matching lines...) Expand all
2653 { 3059 {
2654 background-color: #FF6230; 3060 background-color: #FF6230;
2655 } 3061 }
2656 3062
2657 /* Source code view: format for NoCov legend */ 3063 /* Source code view: format for NoCov legend */
2658 span.coverLegendNoCov 3064 span.coverLegendNoCov
2659 { 3065 {
2660 padding-left: 10px; 3066 padding-left: 10px;
2661 padding-right: 10px; 3067 padding-right: 10px;
2662 padding-bottom: 2px; 3068 padding-bottom: 2px;
2663 » background-color: #FF0000; 3069 » background-color: #FF6230;
2664 } 3070 }
2665 3071
2666 /* Source code view (function table): standard link - visited format */ 3072 /* Source code view (function table): standard link - visited format */
2667 td.lineNoCov > a:visited, 3073 td.lineNoCov > a:visited,
2668 td.lineCov > a:visited 3074 td.lineCov > a:visited
2669 { 3075 {
2670 color: black; 3076 color: black;
2671 text-decoration: underline; 3077 text-decoration: underline;
2672 } 3078 }
2673 3079
2674 /* Source code view: format for lines which were executed only in a 3080 /* Source code view: format for lines which were executed only in a
2675 previous version */ 3081 previous version */
2676 span.lineDiffCov 3082 span.lineDiffCov
2677 { 3083 {
2678 background-color: #B5F7AF; 3084 background-color: #B5F7AF;
2679 } 3085 }
2680 3086
2681 » /* Source code view: format for DiffCov legend */ 3087 » /* Source code view: format for branches which were executed
2682 » span.LegendDiffCov 3088 » * and taken */
3089 » span.branchCov
2683 { 3090 {
3091 background-color: #CAD7FE;
3092 }
3093
3094 /* Source code view: format for branches which were executed
3095 * but not taken */
3096 span.branchNoCov
3097 {
3098 background-color: #FF6230;
3099 }
3100
3101 /* Source code view: format for branches which were not executed */
3102 span.branchNoExec
3103 {
3104 background-color: #FF6230;
3105 }
3106
3107 /* Source code view: format for the source code heading line */
3108 pre.sourceHeading
3109 {
3110 white-space: pre;
3111 font-family: monospace;
3112 font-weight: bold;
3113 margin: 0px;
3114 }
3115
3116 /* All views: header legend value for low rate */
3117 td.headerValueLegL
3118 {
3119 font-family: sans-serif;
2684 text-align: center; 3120 text-align: center;
3121 white-space: nowrap;
3122 padding-left: 4px;
3123 padding-right: 2px;
3124 background-color: #FF0000;
3125 font-size: 80%;
3126 }
3127
3128 /* All views: header legend value for med rate */
3129 td.headerValueLegM
3130 {
3131 font-family: sans-serif;
3132 text-align: center;
3133 white-space: nowrap;
3134 padding-left: 2px;
3135 padding-right: 2px;
3136 background-color: #FFEA20;
3137 font-size: 80%;
3138 }
3139
3140 /* All views: header legend value for hi rate */
3141 td.headerValueLegH
3142 {
3143 font-family: sans-serif;
3144 text-align: center;
3145 white-space: nowrap;
3146 padding-left: 2px;
3147 padding-right: 4px;
3148 background-color: #A7FC9D;
3149 font-size: 80%;
3150 }
3151
3152 /* All views except source code view: legend format for low coverage */
3153 span.coverLegendCovLo
3154 {
2685 padding-left: 10px; 3155 padding-left: 10px;
2686 padding-right: 10px; 3156 padding-right: 10px;
2687 » background-color: #B5F7AF; 3157 » padding-top: 2px;
3158 » background-color: #FF0000;
3159 » }
3160
3161 » /* All views except source code view: legend format for med coverage */
3162 » span.coverLegendCovMed
3163 » {
3164 » padding-left: 10px;
3165 » padding-right: 10px;
3166 » padding-top: 2px;
3167 » background-color: #FFEA20;
3168 » }
3169
3170 » /* All views except source code view: legend format for hi coverage */
3171 » span.coverLegendCovHi
3172 » {
3173 » padding-left: 10px;
3174 » padding-right: 10px;
3175 » padding-top: 2px;
3176 » background-color: #A7FC9D;
2688 } 3177 }
2689 END_OF_CSS 3178 END_OF_CSS
2690 ; 3179 ;
2691 3180
2692 # ************************************************************* 3181 # *************************************************************
2693 3182
2694 3183
2695 # Remove leading tab from all lines 3184 # Remove leading tab from all lines
2696 $css_data =~ s/^\t//gm; 3185 $css_data =~ s/^\t//gm;
2697 3186
2698 print(CSS_HANDLE $css_data); 3187 print(CSS_HANDLE $css_data);
2699 3188
2700 close(CSS_HANDLE); 3189 close(CSS_HANDLE);
2701 } 3190 }
2702 3191
2703 3192
2704 # 3193 #
2705 # get_bar_graph_code(base_dir, cover_found, cover_hit) 3194 # get_bar_graph_code(base_dir, cover_found, cover_hit)
2706 # 3195 #
2707 # Return a string containing HTML code which implements a bar graph display 3196 # Return a string containing HTML code which implements a bar graph display
2708 # for a coverage rate of cover_hit * 100 / cover_found. 3197 # for a coverage rate of cover_hit * 100 / cover_found.
2709 # 3198 #
2710 3199
2711 sub get_bar_graph_code($$$) 3200 sub get_bar_graph_code($$$)
2712 { 3201 {
3202 my ($base_dir, $found, $hit) = @_;
2713 my $rate; 3203 my $rate;
2714 my $alt; 3204 my $alt;
2715 my $width; 3205 my $width;
2716 my $remainder; 3206 my $remainder;
2717 my $png_name; 3207 my $png_name;
2718 my $graph_code; 3208 my $graph_code;
2719 3209
2720 # Check number of instrumented lines 3210 # Check number of instrumented lines
2721 if ($_[1] == 0) { return ""; } 3211 if ($_[1] == 0) { return ""; }
2722 3212
2723 » $rate» » = $_[2] * 100 / $_[1]; 3213 » $alt» » = rate($hit, $found, "%");
2724 » $alt» » = sprintf("%.1f", $rate)."%"; 3214 » $width» » = rate($hit, $found, undef, 0);
2725 » $width» » = sprintf("%.0f", $rate); 3215 » $remainder» = 100 - $width;
2726 » $remainder» = sprintf("%d", 100-$width);
2727 3216
2728 # Decide which .png file to use 3217 # Decide which .png file to use
2729 » $png_name = $rate_png[classify_rate($_[1], $_[2], $med_limit, 3218 » $png_name = $rate_png[classify_rate($found, $hit, $med_limit,
2730 $hi_limit)]; 3219 $hi_limit)];
2731 3220
2732 if ($width == 0) 3221 if ($width == 0)
2733 { 3222 {
2734 # Zero coverage 3223 # Zero coverage
2735 $graph_code = (<<END_OF_HTML) 3224 $graph_code = (<<END_OF_HTML)
2736 <table border=0 cellspacing=0 cellpadding=1><tr><td class="cover BarOutline"><img src="$_[0]snow.png" width=100 height=10 alt="$alt"></td></tr></ table> 3225 <table border=0 cellspacing=0 cellpadding=1><tr><td class="cover BarOutline"><img src="$_[0]snow.png" width=100 height=10 alt="$alt"></td></tr></ table>
2737 END_OF_HTML 3226 END_OF_HTML
2738 ; 3227 ;
2739 } 3228 }
(...skipping 28 matching lines...) Expand all
2768 # 3257 #
2769 3258
2770 sub classify_rate($$$$) 3259 sub classify_rate($$$$)
2771 { 3260 {
2772 my ($found, $hit, $med, $hi) = @_; 3261 my ($found, $hit, $med, $hi) = @_;
2773 my $rate; 3262 my $rate;
2774 3263
2775 if ($found == 0) { 3264 if ($found == 0) {
2776 return 2; 3265 return 2;
2777 } 3266 }
2778 » $rate = $hit * 100 / $found; 3267 » $rate = rate($hit, $found);
2779 if ($rate < $med) { 3268 if ($rate < $med) {
2780 return 0; 3269 return 0;
2781 } elsif ($rate < $hi) { 3270 } elsif ($rate < $hi) {
2782 return 1; 3271 return 1;
2783 } 3272 }
2784 return 2; 3273 return 2;
2785 } 3274 }
2786 3275
2787 3276
2788 # 3277 #
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2846 <td width="100%"> 3335 <td width="100%">
2847 <table cellpadding=1 border=0 width="100%"> 3336 <table cellpadding=1 border=0 width="100%">
2848 END_OF_HTML 3337 END_OF_HTML
2849 ; 3338 ;
2850 3339
2851 # ************************************************************* 3340 # *************************************************************
2852 } 3341 }
2853 3342
2854 3343
2855 # 3344 #
2856 # write_header_line(filehandle, type, additional params..) 3345 # write_header_line(handle, content)
2857 # 3346 #
2858 # Write a header line. 3347 # Write a header line with the specified table contents.
2859 # 3348 #
2860 3349
2861 sub write_header_line(*$@) 3350 sub write_header_line(*@)
2862 { 3351 {
2863 » my $HANDLE = shift; 3352 » my ($handle, @content) = @_;
2864 » my $type = shift; 3353 » my $entry;
2865 » my @args = @_;
2866 3354
2867 » # Reduce indentation by using gotos 3355 » write_html($handle, " <tr>\n");
2868 » if ($type eq 0) { 3356 » foreach $entry (@content) {
2869 » » goto header; 3357 » » my ($width, $class, $text, $colspan) = @{$entry};
2870 » } elsif ($type eq 1) { 3358
2871 » » goto body; 3359 » » if (defined($width)) {
2872 » } elsif ($type eq 2) { 3360 » » » $width = " width=\"$width\"";
2873 » » goto legend_dir; 3361 » » } else {
2874 » } elsif ($type eq 3) { 3362 » » » $width = "";
2875 » » goto legend_source; 3363 » » }
2876 » } elsif ($type eq 4) { 3364 » » if (defined($class)) {
2877 » » goto half_body; 3365 » » » $class = " class=\"$class\"";
3366 » » } else {
3367 » » » $class = "";
3368 » » }
3369 » » if (defined($colspan)) {
3370 » » » $colspan = " colspan=\"$colspan\"";
3371 » » } else {
3372 » » » $colspan = "";
3373 » » }
3374 » » $text = "" if (!defined($text));
3375 » » write_html($handle,
3376 » » » " <td$width$class$colspan>$text</td>\n");
2878 } 3377 }
2879 3378 » write_html($handle, " </tr>\n");
2880 header:
2881 » # *************************************************************
2882 » write_html($HANDLE, <<END_OF_HTML);
2883 <tr>
2884 <td width="5%"></td>
2885 <td width="10%" class="headerItem">$args[0]</td>
2886 <td width="35%" class="headerValue">$args[1]</td>
2887 <td width="10%"></td>
2888 <td width="10%" class="headerCovTableHead">$args[2]</td>
2889 <td width="10%" class="headerCovTableHead">$args[3]</td>
2890 <td width="15%" class="headerCovTableHead">$args[4]</td>
2891 <td width="5%"></td>
2892 </tr>
2893 END_OF_HTML
2894 » # *************************************************************
2895 » return;
2896
2897 body:
2898 » # *************************************************************
2899 » write_html($HANDLE, <<END_OF_HTML);
2900 <tr>
2901 <td></td>
2902 <td class="headerItem">$args[0]</td>
2903 <td class="headerValue">$args[1]</td>
2904 <td class="headerItem">$args[2]</td>
2905 <td class="headerCovTableEntry">$args[3]</td>
2906 <td class="headerCovTableEntry">$args[4]</td>
2907 <td class="headerCovTableEntry$args[5]">$args[6]</td>
2908 </tr>
2909 END_OF_HTML
2910 » # *************************************************************
2911 » return;
2912
2913 half_body:
2914 » # *************************************************************
2915 » write_html($HANDLE, <<END_OF_HTML);
2916 <tr>
2917 <td></td>
2918 <td class="headerItem">$args[0]</td>
2919 <td class="headerValue">$args[1]</td>
2920 </tr>
2921 END_OF_HTML
2922 » # *************************************************************
2923 » return;
2924
2925 legend_dir:
2926 » # *************************************************************
2927 » write_html($HANDLE, <<END_OF_HTML);
2928 <tr>
2929 <td></td>
2930 <td class="headerItemLeg">$args[0]</td>
2931 <td class="headerValueLeg">
2932 $args[1] </td>
2933 <td></td>
2934 <td class="headerValueLeg" colspan=3>
2935 $args[2] </td>
2936 </tr>
2937 END_OF_HTML
2938 » # *************************************************************
2939 » return;
2940
2941 legend_source:
2942 » # *************************************************************
2943 » write_html($HANDLE, <<END_OF_HTML);
2944 <tr>
2945 <td></td>
2946 <td class="headerItem">$args[0]</td>
2947 <td class="headerValueLeg" colspan=5>
2948 <span class="coverLegendNoCov">$args[1]</span>
2949 <span class="coverLegendCov">$args[2]</span>
2950 </td>
2951 </tr>
2952 END_OF_HTML
2953 » # *************************************************************
2954 } 3379 }
2955 3380
2956 3381
2957 # 3382 #
2958 # write_header_epilog(filehandle, base_dir) 3383 # write_header_epilog(filehandle, base_dir)
2959 # 3384 #
2960 # Write end of page header HTML code. 3385 # Write end of page header HTML code.
2961 # 3386 #
2962 3387
2963 sub write_header_epilog(*$) 3388 sub write_header_epilog(*$)
2964 { 3389 {
2965 # ************************************************************* 3390 # *************************************************************
2966 3391
2967 write_html($_[0], <<END_OF_HTML) 3392 write_html($_[0], <<END_OF_HTML)
2968 <tr><td><img src="$_[1]glass.png" width=3 height=3 alt=""></td>< /tr> 3393 » <tr><td><img src="$_[1]glass.png" width=3 height=3 alt=""></td ></tr>
2969 </table> 3394 </table>
2970 </td> 3395 </td>
2971 </tr> 3396 </tr>
3397
2972 <tr><td class="ruler"><img src="$_[1]glass.png" width=3 height=3 alt =""></td></tr> 3398 <tr><td class="ruler"><img src="$_[1]glass.png" width=3 height=3 alt =""></td></tr>
2973 </table> 3399 </table>
2974 3400
2975 END_OF_HTML 3401 END_OF_HTML
2976 ; 3402 ;
2977 3403
2978 # ************************************************************* 3404 # *************************************************************
2979 } 3405 }
2980 3406
2981 3407
2982 # 3408 #
2983 # write_file_table_prolog(filehandle, file_heading, lines_heading, func_heading) 3409 # write_file_table_prolog(handle, file_heading, ([heading, num_cols], ...))
2984 # 3410 #
2985 # Write heading for file table. 3411 # Write heading for file table.
2986 # 3412 #
2987 3413
2988 sub write_file_table_prolog(*$$$) 3414 sub write_file_table_prolog(*$@)
2989 { 3415 {
2990 » # ************************************************************* 3416 » my ($handle, $file_heading, @columns) = @_;
3417 » my $num_columns = 0;
3418 » my $file_width;
3419 » my $col;
3420 » my $width;
2991 3421
2992 if ($func_coverage) 3422 » $width = 20 if (scalar(@columns) == 1);
2993 { 3423 » $width = 10 if (scalar(@columns) == 2);
2994 write_html($_[0], <<END_OF_HTML) 3424 » $width = 8 if (scalar(@columns) > 2);
3425
3426 » foreach $col (@columns) {
3427 » » my ($heading, $cols) = @{$col};
3428
3429 » » $num_columns += $cols;
3430 » }
3431 » $file_width = 100 - $num_columns * $width;
3432
3433 » # Table definition
3434 » write_html($handle, <<END_OF_HTML);
2995 <center> 3435 <center>
2996 <table width="80%" cellpadding=1 cellspacing=1 border=0> 3436 <table width="80%" cellpadding=1 cellspacing=1 border=0>
2997 3437
2998 <tr> 3438 <tr>
2999 » <td width="45%"><br></td> 3439 » <td width="$file_width%"><br></td>
3000 » <td width="15%"></td> 3440 END_OF_HTML
3001 » <td width="10%"></td> 3441 » # Empty first row
3002 » <td width="10%"></td> 3442 » foreach $col (@columns) {
3003 » <td width="10%"></td> 3443 » » my ($heading, $cols) = @{$col};
3004 » <td width="10%"></td> 3444
3445 » » while ($cols-- > 0) {
3446 » » » write_html($handle, <<END_OF_HTML);
3447 » <td width="$width%"></td>
3448 END_OF_HTML
3449 » » }
3450 » }
3451 » # Next row
3452 » write_html($handle, <<END_OF_HTML);
3005 </tr> 3453 </tr>
3006 3454
3007 <tr> 3455 <tr>
3008 » <td class="tableHead">$_[1]</td> 3456 » <td class="tableHead">$file_heading</td>
3009 » <td class="tableHead" colspan=3>$_[2]</td> 3457 END_OF_HTML
3010 » <td class="tableHead" colspan=2>$_[3]</td> 3458 » # Heading row
3459 » foreach $col (@columns) {
3460 » » my ($heading, $cols) = @{$col};
3461 » » my $colspan = "";
3462
3463 » » $colspan = " colspan=$cols" if ($cols > 1);
3464 » » write_html($handle, <<END_OF_HTML);
3465 » <td class="tableHead"$colspan>$heading</td>
3466 END_OF_HTML
3467 » }
3468 » write_html($handle, <<END_OF_HTML);
3011 </tr> 3469 </tr>
3470 END_OF_HTML
3471 }
3012 3472
3473
3474 # write_file_table_entry(handle, base_dir, filename, page_link,
3475 # ([ found, hit, med_limit, hi_limit, graph ], ..)
3476 #
3477 # Write an entry of the file table.
3478 #
3479
3480 sub write_file_table_entry(*$$$@)
3481 {
3482 my ($handle, $base_dir, $filename, $page_link, @entries) = @_;
3483 my $file_code;
3484 my $entry;
3485 my $esc_filename = escape_html($filename);
3486
3487 # Add link to source if provided
3488 if (defined($page_link) && $page_link ne "") {
3489 $file_code = "<a href=\"$page_link\">$esc_filename</a>";
3490 } else {
3491 $file_code = $esc_filename;
3492 }
3493
3494 # First column: filename
3495 write_html($handle, <<END_OF_HTML);
3496 <tr>
3497 <td class="coverFile">$file_code</td>
3013 END_OF_HTML 3498 END_OF_HTML
3014 ; 3499 » # Columns as defined
3015 } 3500 » foreach $entry (@entries) {
3016 else 3501 » » my ($found, $hit, $med, $hi, $graph) = @{$entry};
3017 { 3502 » » my $bar_graph;
3018 write_html($_[0], <<END_OF_HTML) 3503 » » my $class;
3019 » <center> 3504 » » my $rate;
3020 » <table width="80%" cellpadding=1 cellspacing=1 border=0>
3021 3505
3022 » <tr> 3506 » » # Generate bar graph if requested
3023 » <td width="50%"><br></td> 3507 » » if ($graph) {
3024 » <td width="15%"></td> 3508 » » » $bar_graph = get_bar_graph_code($base_dir, $found,
3025 » <td width="15%"></td> 3509 » » » » » » » $hit);
3026 » <td width="20%"></td> 3510 » » » write_html($handle, <<END_OF_HTML);
3511 » <td class="coverBar" align="center">
3512 » $bar_graph
3513 » </td>
3514 END_OF_HTML
3515 » » }
3516 » » # Get rate color and text
3517 » » if ($found == 0) {
3518 » » » $rate = "-";
3519 » » » $class = "Hi";
3520 » » } else {
3521 » » » $rate = rate($hit, $found, "&nbsp;%");
3522 » » » $class = $rate_name[classify_rate($found, $hit,
3523 » » » » » $med, $hi)];
3524 » » }
3525 » » write_html($handle, <<END_OF_HTML);
3526 » <td class="coverPer$class">$rate</td>
3527 » <td class="coverNum$class">$hit / $found</td>
3528 END_OF_HTML
3529 » }
3530 » # End of row
3531 write_html($handle, <<END_OF_HTML);
3027 </tr> 3532 </tr>
3028
3029 <tr>
3030 <td class="tableHead">$_[1]</td>
3031 <td class="tableHead" colspan=3>$_[2]</td>
3032 </tr>
3033
3034 END_OF_HTML 3533 END_OF_HTML
3035 ;
3036 }
3037
3038 # *************************************************************
3039 } 3534 }
3040 3535
3041 3536
3042 # 3537 #
3043 # write_file_table_entry(filehandle, cover_filename, cover_bar_graph, 3538 # write_file_table_detail_entry(filehandle, test_name, ([found, hit], ...))
3044 # cover_found, cover_hit, fn_found, fn_hit,
3045 #» » » page_link, func_link)
3046 #
3047 # Write an entry of the file table.
3048 #
3049
3050 sub write_file_table_entry(*$$$$$$$)
3051 {
3052 » local *HANDLE = shift;
3053 » my ($filename, $bar_graph, $found, $hit, $fn_found, $fn_hit,
3054 » $page_link) = @_;
3055 » my $rate;
3056 » my $rate_string;
3057 » my $funcs_string;
3058 » my $class_lines = "Lo";
3059 » my $class_funcs = "Hi";
3060 » my $file_code;
3061
3062 » # Add link to source if provided
3063 » if (defined($page_link) && $page_link ne "") {
3064 » » $file_code = "<a href=\"$page_link\">$filename</a>";
3065 » } else {
3066 » » $file_code = $filename;
3067 » }
3068
3069 » # Get line coverage rate
3070 » if ($found > 0)
3071 » {
3072 » » $rate = $hit * 100 / $found;
3073 » » $rate_string = sprintf("%.1f", $rate)."&nbsp;%";
3074 » »
3075 » » $class_lines = $rate_name[classify_rate($found, $hit,
3076 » » » » » $med_limit, $hi_limit)];
3077 » }
3078 » else
3079 » {
3080 » » $rate_string = "-";
3081 » }
3082
3083 » # Get function coverage rate
3084 » if ($fn_found > 0)
3085 » {
3086 » » $rate = $fn_hit * 100 / $fn_found;
3087 » » $class_funcs = $rate_name[classify_rate($fn_found, $fn_hit,
3088 » » » » » $fn_med_limit, $fn_hi_limit)];
3089 » » $funcs_string = sprintf("%.1f", $rate)."&nbsp;%";» »
3090 » }
3091 » else
3092 » {
3093 » » # Define 0 of 0 functions as 100%
3094 » » $rate = 100;
3095 » » $funcs_string = "-";
3096 » }
3097
3098 » # *************************************************************
3099
3100 » write_html(*HANDLE, <<END_OF_HTML)
3101 » <tr>
3102 » <td class="coverFile">$file_code</td>
3103 » <td class="coverBar" align="center">
3104 » $bar_graph
3105 » </td>
3106 » <td class="coverPer$class_lines">$rate_string</td>
3107 » <td class="coverNum$class_lines">$hit / $found</td>
3108 END_OF_HTML
3109 » ;
3110
3111 if ($func_coverage)
3112 {
3113 write_html(*HANDLE, <<END_OF_HTML)
3114 » <td class="coverPer$class_funcs">$funcs_string</td>
3115 » <td class="coverNum$class_funcs">$fn_hit / $fn_found</td>
3116 END_OF_HTML
3117 » ;
3118 }
3119 write_html(*HANDLE, <<END_OF_HTML)
3120 » </tr>
3121 END_OF_HTML
3122 ;
3123
3124 » # *************************************************************
3125 }
3126
3127
3128 #
3129 # write_file_table_detail_heading(filehandle, left_heading, right_heading)
3130 #
3131 # Write heading for detail section in file table.
3132 #
3133
3134 sub write_file_table_detail_heading(*$$$)
3135 {
3136 my $func_rows = "";
3137
3138 if ($func_coverage)
3139 {
3140 $func_rows = "<td class=\"testLinesHead\" colspan=2>$_[3]</td>";
3141 }
3142
3143 » # *************************************************************
3144 » write_html($_[0], <<END_OF_HTML)
3145 » <tr>
3146 » <td class="testNameHead" colspan=2>$_[1]</td>
3147 » <td class="testLinesHead" colspan=2>$_[2]</td>
3148 $func_rows
3149 » </tr>
3150
3151 END_OF_HTML
3152 » ;
3153
3154 » # *************************************************************
3155 }
3156
3157
3158 #
3159 # write_file_table_detail_entry(filehandle, test_name,
3160 # cover_found, cover_hit, func_found, func_hit)
3161 # 3539 #
3162 # Write entry for detail section in file table. 3540 # Write entry for detail section in file table.
3163 # 3541 #
3164 3542
3165 sub write_file_table_detail_entry(*$$$$$) 3543 sub write_file_table_detail_entry(*$@)
3166 { 3544 {
3167 » my $rate; 3545 » my ($handle, $test, @entries) = @_;
3168 » my $func_rate; 3546 » my $entry;
3169 » my $name = $_[1]; 3547
3170 » 3548 » if ($test eq "") {
3171 » if ($_[2]>0) 3549 » » $test = "<span style=\"font-style:italic\">&lt;unnamed&gt;</span >";
3172 » { 3550 » } elsif ($test =~ /^(.*),diff$/) {
3173 » » $rate = sprintf("%.1f", $_[3]*100/$_[2])."&nbsp;%"; 3551 » » $test = $1." (converted)";
3174 } 3552 }
3175 » else 3553 » # Testname
3176 » { 3554 » write_html($handle, <<END_OF_HTML);
3177 » » $rate = "-"; 3555 » <tr>
3556 » <td class="testName" colspan=2>$test</td>
3557 END_OF_HTML
3558 » # Test data
3559 » foreach $entry (@entries) {
3560 » » my ($found, $hit) = @{$entry};
3561 » » my $rate = rate($hit, $found, "&nbsp;%");
3562
3563 » » write_html($handle, <<END_OF_HTML);
3564 » <td class="testPer">$rate</td>
3565 » <td class="testNum">$hit&nbsp;/&nbsp;$found</td>
3566 END_OF_HTML
3178 } 3567 }
3179 3568
3180 » if ($_[4]>0) 3569 write_html($handle, <<END_OF_HTML);
3181 » {
3182 » » $func_rate = sprintf("%.1f", $_[5]*100/$_[4])."&nbsp;%";
3183 » }
3184 » else
3185 » {
3186 » » $func_rate = "-";
3187 » }
3188
3189 » if ($name =~ /^(.*),diff$/)
3190 » {
3191 » » $name = $1." (converted)";
3192 » }
3193
3194 » if ($name eq "")
3195 » {
3196 » » $name = "<span style=\"font-style:italic\">&lt;unnamed&gt;</span >";
3197 » }
3198
3199 » # *************************************************************
3200
3201 » write_html($_[0], <<END_OF_HTML)
3202 » <tr>
3203 » <td class="testName" colspan=2>$name</td>
3204 » <td class="testPer">$rate</td>
3205 » <td class="testNum">$_[3]&nbsp;/&nbsp;$_[2]&nbsp;lines</td>
3206 END_OF_HTML
3207 » ;
3208 if ($func_coverage)
3209 {
3210 write_html($_[0], <<END_OF_HTML)
3211 » <td class="testPer">$func_rate</td>
3212 » <td class="testNum">$_[5]&nbsp;/&nbsp;$_[4]</td>
3213 END_OF_HTML
3214 » ;
3215 }
3216 write_html($_[0], <<END_OF_HTML)
3217 </tr> 3570 </tr>
3218 3571
3219 END_OF_HTML 3572 END_OF_HTML
3220 ;
3221 3573
3222 # ************************************************************* 3574 # *************************************************************
3223 } 3575 }
3224 3576
3225 3577
3226 # 3578 #
3227 # write_file_table_epilog(filehandle) 3579 # write_file_table_epilog(filehandle)
3228 # 3580 #
3229 # Write end of file table HTML code. 3581 # Write end of file table HTML code.
3230 # 3582 #
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
3315 </center> 3667 </center>
3316 <br> 3668 <br>
3317 3669
3318 END_OF_HTML 3670 END_OF_HTML
3319 ; 3671 ;
3320 3672
3321 # ************************************************************* 3673 # *************************************************************
3322 } 3674 }
3323 3675
3324 3676
3677 sub fmt_centered($$)
3678 {
3679 my ($width, $text) = @_;
3680 my $w0 = length($text);
3681 my $w1 = int(($width - $w0) / 2);
3682 my $w2 = $width - $w0 - $w1;
3683
3684 return (" "x$w1).$text.(" "x$w2);
3685 }
3686
3687
3325 # 3688 #
3326 # write_source_prolog(filehandle) 3689 # write_source_prolog(filehandle)
3327 # 3690 #
3328 # Write start of source code table. 3691 # Write start of source code table.
3329 # 3692 #
3330 3693
3331 sub write_source_prolog(*) 3694 sub write_source_prolog(*)
3332 { 3695 {
3696 my $lineno_heading = " ";
3697 my $branch_heading = "";
3698 my $line_heading = fmt_centered($line_field_width, "Line data");
3699 my $source_heading = " Source code";
3700
3701 if ($br_coverage) {
3702 $branch_heading = fmt_centered($br_field_width, "Branch data").
3703 " ";
3704 }
3333 # ************************************************************* 3705 # *************************************************************
3334 3706
3335 write_html($_[0], <<END_OF_HTML) 3707 write_html($_[0], <<END_OF_HTML)
3336 <table cellpadding=0 cellspacing=0 border=0> 3708 <table cellpadding=0 cellspacing=0 border=0>
3337 <tr> 3709 <tr>
3338 <td><br></td> 3710 <td><br></td>
3339 </tr> 3711 </tr>
3340 <tr> 3712 <tr>
3341 » <td><pre class="source"> 3713 » <td>
3714 <pre class="sourceHeading">${lineno_heading}${branch_heading}${line_heading} ${s ource_heading}</pre>
3715 <pre class="source">
3342 END_OF_HTML 3716 END_OF_HTML
3343 ; 3717 ;
3344 3718
3345 # ************************************************************* 3719 # *************************************************************
3346 } 3720 }
3347 3721
3348 3722
3349 # 3723 #
3724 # get_branch_blocks(brdata)
3725 #
3726 # Group branches that belong to the same basic block.
3727 #
3728 # Returns: [block1, block2, ...]
3729 # block: [branch1, branch2, ...]
3730 # branch: [block_num, branch_num, taken_count, text_length, open, close]
3731 #
3732
3733 sub get_branch_blocks($)
3734 {
3735 my ($brdata) = @_;
3736 my $last_block_num;
3737 my $block = [];
3738 my @blocks;
3739 my $i;
3740 my $num = br_ivec_len($brdata);
3741
3742 # Group branches
3743 for ($i = 0; $i < $num; $i++) {
3744 my ($block_num, $branch, $taken) = br_ivec_get($brdata, $i);
3745 my $br;
3746
3747 if (defined($last_block_num) && $block_num != $last_block_num) {
3748 push(@blocks, $block);
3749 $block = [];
3750 }
3751 $br = [$block_num, $branch, $taken, 3, 0, 0];
3752 push(@{$block}, $br);
3753 $last_block_num = $block_num;
3754 }
3755 push(@blocks, $block) if (scalar(@{$block}) > 0);
3756
3757 # Add braces to first and last branch in group
3758 foreach $block (@blocks) {
3759 $block->[0]->[$BR_OPEN] = 1;
3760 $block->[0]->[$BR_LEN]++;
3761 $block->[scalar(@{$block}) - 1]->[$BR_CLOSE] = 1;
3762 $block->[scalar(@{$block}) - 1]->[$BR_LEN]++;
3763 }
3764
3765 return @blocks;
3766 }
3767
3768 #
3769 # get_block_len(block)
3770 #
3771 # Calculate total text length of all branches in a block of branches.
3772 #
3773
3774 sub get_block_len($)
3775 {
3776 my ($block) = @_;
3777 my $len = 0;
3778 my $branch;
3779
3780 foreach $branch (@{$block}) {
3781 $len += $branch->[$BR_LEN];
3782 }
3783
3784 return $len;
3785 }
3786
3787
3788 #
3789 # get_branch_html(brdata)
3790 #
3791 # Return a list of HTML lines which represent the specified branch coverage
3792 # data in source code view.
3793 #
3794
3795 sub get_branch_html($)
3796 {
3797 my ($brdata) = @_;
3798 my @blocks = get_branch_blocks($brdata);
3799 my $block;
3800 my $branch;
3801 my $line_len = 0;
3802 my $line = []; # [branch2|" ", branch|" ", ...]
3803 my @lines; # [line1, line2, ...]
3804 my @result;
3805
3806 # Distribute blocks to lines
3807 foreach $block (@blocks) {
3808 my $block_len = get_block_len($block);
3809
3810 # Does this block fit into the current line?
3811 if ($line_len + $block_len <= $br_field_width) {
3812 # Add it
3813 $line_len += $block_len;
3814 push(@{$line}, @{$block});
3815 next;
3816 } elsif ($block_len <= $br_field_width) {
3817 # It would fit if the line was empty - add it to new
3818 # line
3819 push(@lines, $line);
3820 $line_len = $block_len;
3821 $line = [ @{$block} ];
3822 next;
3823 }
3824 # Split the block into several lines
3825 foreach $branch (@{$block}) {
3826 if ($line_len + $branch->[$BR_LEN] >= $br_field_width) {
3827 # Start a new line
3828 if (($line_len + 1 <= $br_field_width) &&
3829 scalar(@{$line}) > 0 &&
3830 !$line->[scalar(@$line) - 1]->[$BR_CLOSE]) {
3831 # Try to align branch symbols to be in
3832 # one # row
3833 push(@{$line}, " ");
3834 }
3835 push(@lines, $line);
3836 $line_len = 0;
3837 $line = [];
3838 }
3839 push(@{$line}, $branch);
3840 $line_len += $branch->[$BR_LEN];
3841 }
3842 }
3843 push(@lines, $line);
3844
3845 # Convert to HTML
3846 foreach $line (@lines) {
3847 my $current = "";
3848 my $current_len = 0;
3849
3850 foreach $branch (@$line) {
3851 # Skip alignment space
3852 if ($branch eq " ") {
3853 $current .= " ";
3854 $current_len++;
3855 next;
3856 }
3857
3858 my ($block_num, $br_num, $taken, $len, $open, $close) =
3859 @{$branch};
3860 my $class;
3861 my $title;
3862 my $text;
3863
3864 if ($taken eq '-') {
3865 $class = "branchNoExec";
3866 $text = " # ";
3867 $title = "Branch $br_num was not executed";
3868 } elsif ($taken == 0) {
3869 $class = "branchNoCov";
3870 $text = " - ";
3871 $title = "Branch $br_num was not taken";
3872 } else {
3873 $class = "branchCov";
3874 $text = " + ";
3875 $title = "Branch $br_num was taken $taken ".
3876 "time";
3877 $title .= "s" if ($taken > 1);
3878 }
3879 $current .= "[" if ($open);
3880 $current .= "<span class=\"$class\" title=\"$title\">";
3881 $current .= $text."</span>";
3882 $current .= "]" if ($close);
3883 $current_len += $len;
3884 }
3885
3886 # Right-align result text
3887 if ($current_len < $br_field_width) {
3888 $current = (" "x($br_field_width - $current_len)).
3889 $current;
3890 }
3891 push(@result, $current);
3892 }
3893
3894 return @result;
3895 }
3896
3897
3898 #
3899 # format_count(count, width)
3900 #
3901 # Return a right-aligned representation of count that fits in width characters.
3902 #
3903
3904 sub format_count($$)
3905 {
3906 my ($count, $width) = @_;
3907 my $result;
3908 my $exp;
3909
3910 $result = sprintf("%*.0f", $width, $count);
3911 while (length($result) > $width) {
3912 last if ($count < 10);
3913 $exp++;
3914 $count = int($count/10);
3915 $result = sprintf("%*s", $width, ">$count*10^$exp");
3916 }
3917 return $result;
3918 }
3919
3920 #
3350 # write_source_line(filehandle, line_num, source, hit_count, converted, 3921 # write_source_line(filehandle, line_num, source, hit_count, converted,
3351 # add_anchor) 3922 # brdata, add_anchor)
3352 # 3923 #
3353 # Write formatted source code line. Return a line in a format as needed 3924 # Write formatted source code line. Return a line in a format as needed
3354 # by gen_png() 3925 # by gen_png()
3355 # 3926 #
3356 3927
3357 sub write_source_line(*$$$$$) 3928 sub write_source_line(*$$$$$$)
3358 { 3929 {
3930 » my ($handle, $line, $source, $count, $converted, $brdata,
3931 » $add_anchor) = @_;
3359 my $source_format; 3932 my $source_format;
3360 » my $count; 3933 » my $count_format;
3361 my $result; 3934 my $result;
3362 my $anchor_start = ""; 3935 my $anchor_start = "";
3363 my $anchor_end = ""; 3936 my $anchor_end = "";
3364 3937 » my $count_field_width = $line_field_width - 1;
3365 » if (!(defined$_[3])) 3938 » my @br_html;
3366 » { 3939 » my $html;
3940
3941 » # Get branch HTML data for this line
3942 » @br_html = get_branch_html($brdata) if ($br_coverage);
3943
3944 » if (!defined($count)) {
3367 $result = ""; 3945 $result = "";
3368 $source_format = ""; 3946 $source_format = "";
3369 » » $count» » = " "x15; 3947 » » $count_format» = " "x$count_field_width;
3370 » } 3948 » }
3371 » elsif ($_[3] == 0) 3949 » elsif ($count == 0) {
3372 » { 3950 » » $result»» = $count;
3373 » » $result»» = $_[3];
3374 $source_format = '<span class="lineNoCov">'; 3951 $source_format = '<span class="lineNoCov">';
3375 » » $count» » = sprintf("%15d", $_[3]); 3952 » » $count_format» = format_count($count, $count_field_width);
3376 » } 3953 » }
3377 » elsif ($_[4] && defined($highlight)) 3954 » elsif ($converted && defined($highlight)) {
3378 » { 3955 » » $result»» = "*".$count;
3379 » » $result»» = "*".$_[3];
3380 $source_format = '<span class="lineDiffCov">'; 3956 $source_format = '<span class="lineDiffCov">';
3381 » » $count» » = sprintf("%15d", $_[3]); 3957 » » $count_format» = format_count($count, $count_field_width);
3382 » } 3958 » }
3383 » else 3959 » else {
3384 » { 3960 » » $result»» = $count;
3385 » » $result»» = $_[3];
3386 $source_format = '<span class="lineCov">'; 3961 $source_format = '<span class="lineCov">';
3387 » » $count» » = sprintf("%15d", $_[3]); 3962 » » $count_format» = format_count($count, $count_field_width);
3388 » } 3963 » }
3389 3964 » $result .= ":".$source;
3390 » $result .= ":".$_[2];
3391 3965
3392 # Write out a line number navigation anchor every $nav_resolution 3966 # Write out a line number navigation anchor every $nav_resolution
3393 # lines if necessary 3967 # lines if necessary
3394 » if ($_[5]) 3968 » if ($add_anchor)
3395 { 3969 {
3396 $anchor_start = "<a name=\"$_[1]\">"; 3970 $anchor_start = "<a name=\"$_[1]\">";
3397 $anchor_end = "</a>"; 3971 $anchor_end = "</a>";
3398 } 3972 }
3399 3973
3400 3974
3401 # ************************************************************* 3975 # *************************************************************
3402 3976
3403 » write_html($_[0], 3977 » $html = $anchor_start;
3404 » » $anchor_start. 3978 » $html .= "<span class=\"lineNum\">".sprintf("%8d", $line)." </span>";
3405 » » '<span class="lineNum">'.sprintf("%8d", $_[1]). 3979 » $html .= shift(@br_html).":" if ($br_coverage);
3406 » » " </span>$source_format$count : ". 3980 » $html .= "$source_format$count_format : ";
3407 » » escape_html($_[2]).($source_format?"</span>":""). 3981 » $html .= escape_html($source);
3408 » » $anchor_end."\n"); 3982 » $html .= "</span>" if ($source_format);
3983 » $html .= $anchor_end."\n";
3409 3984
3985 write_html($handle, $html);
3986
3987 if ($br_coverage) {
3988 # Add lines for overlong branch information
3989 foreach (@br_html) {
3990 write_html($handle, "<span class=\"lineNum\">".
3991 " </span>$_\n");
3992 }
3993 }
3410 # ************************************************************* 3994 # *************************************************************
3411 3995
3412 return($result); 3996 return($result);
3413 } 3997 }
3414 3998
3415 3999
3416 # 4000 #
3417 # write_source_epilog(filehandle) 4001 # write_source_epilog(filehandle)
3418 # 4002 #
3419 # Write end of source code table. 4003 # Write end of source code table.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3453 4037
3454 if (defined($_[2])) 4038 if (defined($_[2]))
3455 { 4039 {
3456 $break_code = " target=\"_parent\""; 4040 $break_code = " target=\"_parent\"";
3457 } 4041 }
3458 4042
3459 # ************************************************************* 4043 # *************************************************************
3460 4044
3461 write_html($_[0], <<END_OF_HTML) 4045 write_html($_[0], <<END_OF_HTML)
3462 <table width="100%" border=0 cellspacing=0 cellpadding=0> 4046 <table width="100%" border=0 cellspacing=0 cellpadding=0>
3463 » <tr><td class="ruler"><img src="$_[1]glass.png" width=3 height=3 alt=" "></td></tr> 4047 » <tr><td class="ruler"><img src="$_[1]glass.png" width=3 height=3 alt =""></td></tr>
3464 » <tr><td class="versionInfo">Generated by: <a href="$lcov_url"$break_co de>$lcov_version</a></td></tr> 4048 » <tr><td class="versionInfo">Generated by: <a href="$lcov_url"$break_ code>$lcov_version</a></td></tr>
3465 </table> 4049 </table>
3466 <br> 4050 <br>
3467 END_OF_HTML 4051 END_OF_HTML
3468 ; 4052 ;
3469 4053
3470 $epilog = $html_epilog; 4054 $epilog = $html_epilog;
3471 $epilog =~ s/\@basedir\@/$basedir/g; 4055 $epilog =~ s/\@basedir\@/$basedir/g;
3472 4056
3473 write_html($_[0], $epilog); 4057 write_html($_[0], $epilog);
3474 } 4058 }
3475 4059
3476 4060
3477 # 4061 #
3478 # write_frameset(filehandle, basedir, basename, pagetitle) 4062 # write_frameset(filehandle, basedir, basename, pagetitle)
3479 # 4063 #
3480 # 4064 #
3481 4065
3482 sub write_frameset(*$$$) 4066 sub write_frameset(*$$$)
3483 { 4067 {
3484 my $frame_width = $overview_width + 40; 4068 my $frame_width = $overview_width + 40;
3485 4069
3486 # ************************************************************* 4070 # *************************************************************
3487 4071
3488 write_html($_[0], <<END_OF_HTML) 4072 write_html($_[0], <<END_OF_HTML)
3489 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"> 4073 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN">
3490 4074
3491 <html lang="en"> 4075 <html lang="en">
3492 4076
3493 <head> 4077 <head>
3494 » <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1 "> 4078 » <meta http-equiv="Content-Type" content="text/html; charset=$charset">
3495 <title>$_[3]</title> 4079 <title>$_[3]</title>
3496 <link rel="stylesheet" type="text/css" href="$_[1]gcov.css"> 4080 <link rel="stylesheet" type="text/css" href="$_[1]gcov.css">
3497 </head> 4081 </head>
3498 4082
3499 <frameset cols="$frame_width,*"> 4083 <frameset cols="$frame_width,*">
3500 <frame src="$_[2].gcov.overview.$html_ext" name="overview"> 4084 <frame src="$_[2].gcov.overview.$html_ext" name="overview">
3501 <frame src="$_[2].gcov.$html_ext" name="source"> 4085 <frame src="$_[2].gcov.$html_ext" name="source">
3502 <noframes> 4086 <noframes>
3503 <center>Frames not supported by your browser!<br></center> 4087 <center>Frames not supported by your browser!<br></center>
3504 </noframes> 4088 </noframes>
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3547 4131
3548 # ************************************************************* 4132 # *************************************************************
3549 4133
3550 write_html($_[0], <<END_OF_HTML) 4134 write_html($_[0], <<END_OF_HTML)
3551 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 4135 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
3552 4136
3553 <html lang="en"> 4137 <html lang="en">
3554 4138
3555 <head> 4139 <head>
3556 <title>$_[3]</title> 4140 <title>$_[3]</title>
3557 » <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1 "> 4141 » <meta http-equiv="Content-Type" content="text/html; charset=$charset">
3558 <link rel="stylesheet" type="text/css" href="$_[1]gcov.css"> 4142 <link rel="stylesheet" type="text/css" href="$_[1]gcov.css">
3559 </head> 4143 </head>
3560 4144
3561 <body> 4145 <body>
3562 <map name="overview"> 4146 <map name="overview">
3563 END_OF_HTML 4147 END_OF_HTML
3564 ; 4148 ;
3565 4149
3566 # ************************************************************* 4150 # *************************************************************
3567 4151
(...skipping 26 matching lines...) Expand all
3594 </center> 4178 </center>
3595 </body> 4179 </body>
3596 </html> 4180 </html>
3597 END_OF_HTML 4181 END_OF_HTML
3598 ; 4182 ;
3599 4183
3600 # ************************************************************* 4184 # *************************************************************
3601 } 4185 }
3602 4186
3603 4187
3604 # rate_to_col(found, hit) 4188 sub max($$)
3605 # 4189 {
3606 # Return Lo, Med or Hi, depending on the coverage rate. 4190 » my ($a, $b) = @_;
3607 #
3608 4191
3609 sub rate_to_col($$) 4192 » return $a if ($a > $b);
3610 { 4193 » return $b;
3611 » my ($found, $hit) = @_;
3612 » my $rate;
3613
3614 » if ($found == 0) {
3615 » » return "Hi";
3616 » }
3617 » $rate = 100 * $hit / $found;
3618 » if ($rate < $med_limit) {
3619 » » return "Lo";
3620 » } elsif ($rate < $hi_limit) {
3621 » » return "Med";
3622 » }
3623 » return "Hi";
3624 } 4194 }
3625 4195
3626 # format_rate(found, hit)
3627 #
3628 # Return formatted percent string for coverage rate.
3629 #
3630
3631 sub format_rate($$)
3632 {
3633 return $_[0] == 0 ? "-" : sprintf("%.1f", $_[1] * 100 / $_[0])." %";
3634 }
3635
3636 sub get_legend_code($$$)
3637 {
3638 my ($text, $med, $hi) = @_;
3639 my $result;
3640
3641 $result = <<EOF;
3642 $text<br>
3643 <span class="coverLegendLo">0% to $med%</span>
3644 <span class="coverLegendMed">$med% to $hi%</span>
3645 <span class="coverLegendHi">$hi% to 100%</span>
3646 EOF
3647 return $result;
3648 }
3649 4196
3650 # 4197 #
3651 # write_header(filehandle, type, trunc_file_name, rel_file_name, lines_found, 4198 # write_header(filehandle, type, trunc_file_name, rel_file_name, lines_found,
3652 # lines_hit, funcs_found, funcs_hit, sort_type) 4199 # lines_hit, funcs_found, funcs_hit, sort_type)
3653 # 4200 #
3654 # Write a complete standard page header. TYPE may be (0, 1, 2, 3, 4) 4201 # Write a complete standard page header. TYPE may be (0, 1, 2, 3, 4)
3655 # corresponding to (directory view header, file view header, source view 4202 # corresponding to (directory view header, file view header, source view
3656 # header, test case description header, function view header) 4203 # header, test case description header, function view header)
3657 # 4204 #
3658 4205
3659 sub write_header(*$$$$$$$$) 4206 sub write_header(*$$$$$$$$$$)
3660 { 4207 {
3661 local *HTML_HANDLE = $_[0]; 4208 local *HTML_HANDLE = $_[0];
3662 my $type = $_[1]; 4209 my $type = $_[1];
3663 my $trunc_name = $_[2]; 4210 my $trunc_name = $_[2];
3664 my $rel_filename = $_[3]; 4211 my $rel_filename = $_[3];
3665 my $lines_found = $_[4]; 4212 my $lines_found = $_[4];
3666 my $lines_hit = $_[5]; 4213 my $lines_hit = $_[5];
3667 my $fn_found = $_[6]; 4214 my $fn_found = $_[6];
3668 my $fn_hit = $_[7]; 4215 my $fn_hit = $_[7];
3669 » my $sort_type = $_[8]; 4216 » my $br_found = $_[8];
4217 » my $br_hit = $_[9];
4218 » my $sort_type = $_[10];
3670 my $base_dir; 4219 my $base_dir;
3671 my $view; 4220 my $view;
3672 my $test; 4221 my $test;
3673 my $base_name; 4222 my $base_name;
4223 my $style;
4224 my $rate;
4225 my @row_left;
4226 my @row_right;
4227 my $num_rows;
4228 my $i;
4229 my $esc_trunc_name = escape_html($trunc_name);
3674 4230
3675 $base_name = basename($rel_filename); 4231 $base_name = basename($rel_filename);
3676 4232
3677 # Prepare text for "current view" field 4233 # Prepare text for "current view" field
3678 » if ($type == 0) 4234 » if ($type == $HDR_DIR)
3679 { 4235 {
3680 # Main overview 4236 # Main overview
3681 $base_dir = ""; 4237 $base_dir = "";
3682 $view = $overview_title; 4238 $view = $overview_title;
3683 } 4239 }
3684 » elsif ($type == 1) 4240 » elsif ($type == $HDR_FILE)
3685 { 4241 {
3686 # Directory overview 4242 # Directory overview
3687 $base_dir = get_relative_base_path($rel_filename); 4243 $base_dir = get_relative_base_path($rel_filename);
3688 $view = "<a href=\"$base_dir"."index.$html_ext\">". 4244 $view = "<a href=\"$base_dir"."index.$html_ext\">".
3689 » » » "$overview_title</a> - $trunc_name"; 4245 » » » "$overview_title</a> - $esc_trunc_name";
3690 } 4246 }
3691 » elsif ($type == 2 || $type == 4) 4247 » elsif ($type == $HDR_SOURCE || $type == $HDR_FUNC)
3692 { 4248 {
3693 # File view 4249 # File view
3694 my $dir_name = dirname($rel_filename); 4250 my $dir_name = dirname($rel_filename);
4251 my $esc_base_name = escape_html($base_name);
4252 my $esc_dir_name = escape_html($dir_name);
3695 4253
3696 $base_dir = get_relative_base_path($dir_name); 4254 $base_dir = get_relative_base_path($dir_name);
3697 if ($frames) 4255 if ($frames)
3698 { 4256 {
3699 # Need to break frameset when clicking any of these 4257 # Need to break frameset when clicking any of these
3700 # links 4258 # links
3701 $view = "<a href=\"$base_dir"."index.$html_ext\" ". 4259 $view = "<a href=\"$base_dir"."index.$html_ext\" ".
3702 "target=\"_parent\">$overview_title</a> - ". 4260 "target=\"_parent\">$overview_title</a> - ".
3703 "<a href=\"index.$html_ext\" target=\"_parent\"> ". 4261 "<a href=\"index.$html_ext\" target=\"_parent\"> ".
3704 » » » » "$dir_name</a> - $base_name"; 4262 » » » » "$esc_dir_name</a> - $esc_base_name";
3705 } 4263 }
3706 else 4264 else
3707 { 4265 {
3708 $view = "<a href=\"$base_dir"."index.$html_ext\">". 4266 $view = "<a href=\"$base_dir"."index.$html_ext\">".
3709 "$overview_title</a> - ". 4267 "$overview_title</a> - ".
3710 "<a href=\"index.$html_ext\">". 4268 "<a href=\"index.$html_ext\">".
3711 » » » » "$dir_name</a> - $base_name"; 4269 » » » » "$esc_dir_name</a> - $esc_base_name";
3712 } 4270 }
3713 4271
3714 # Add function suffix 4272 # Add function suffix
3715 if ($func_coverage) { 4273 if ($func_coverage) {
3716 » » » if ($type == 2) { 4274 » » » $view .= "<span style=\"font-size: 80%;\">";
4275 » » » if ($type == $HDR_SOURCE) {
3717 $view .= " (source / <a href=\"$base_name.func.$ html_ext\">functions</a>)"; 4276 $view .= " (source / <a href=\"$base_name.func.$ html_ext\">functions</a>)";
3718 » » » } elsif ($type == 4) { 4277 » » » } elsif ($type == $HDR_FUNC) {
3719 $view .= " (<a href=\"$base_name.gcov.$html_ext\ ">source</a> / functions)"; 4278 $view .= " (<a href=\"$base_name.gcov.$html_ext\ ">source</a> / functions)";
3720 } 4279 }
4280 $view .= "</span>";
3721 } 4281 }
3722 } 4282 }
3723 » elsif ($type == 3) 4283 » elsif ($type == $HDR_TESTDESC)
3724 { 4284 {
3725 # Test description header 4285 # Test description header
3726 $base_dir = ""; 4286 $base_dir = "";
3727 $view = "<a href=\"$base_dir"."index.$html_ext\">". 4287 $view = "<a href=\"$base_dir"."index.$html_ext\">".
3728 "$overview_title</a> - test case descriptions"; 4288 "$overview_title</a> - test case descriptions";
3729 } 4289 }
3730 4290
3731 # Prepare text for "test" field 4291 # Prepare text for "test" field
3732 $test = escape_html($test_title); 4292 $test = escape_html($test_title);
3733 4293
3734 # Append link to test description page if available 4294 # Append link to test description page if available
3735 » if (%test_description && ($type != 3)) 4295 » if (%test_description && ($type != $HDR_TESTDESC))
3736 { 4296 {
3737 » » if ($frames && ($type == 2 || $type == 4)) 4297 » » if ($frames && ($type == $HDR_SOURCE || $type == $HDR_FUNC))
3738 { 4298 {
3739 # Need to break frameset when clicking this link 4299 # Need to break frameset when clicking this link
3740 » » » $test .= " ( <a href=\"$base_dir". 4300 » » » $test .= " ( <span style=\"font-size:80%;\">".
4301 » » » » "<a href=\"$base_dir".
3741 "descriptions.$html_ext\" target=\"_parent\">". 4302 "descriptions.$html_ext\" target=\"_parent\">".
3742 » » » » "view descriptions</a> )"; 4303 » » » » "view descriptions</a></span> )";
3743 } 4304 }
3744 else 4305 else
3745 { 4306 {
3746 » » » $test .= " ( <a href=\"$base_dir". 4307 » » » $test .= " ( <span style=\"font-size:80%;\">".
4308 » » » » "<a href=\"$base_dir".
3747 "descriptions.$html_ext\">". 4309 "descriptions.$html_ext\">".
3748 » » » » "view descriptions</a> )"; 4310 » » » » "view descriptions</a></span> )";
3749 } 4311 }
3750 } 4312 }
3751 4313
3752 # Write header 4314 # Write header
3753 write_header_prolog(*HTML_HANDLE, $base_dir); 4315 write_header_prolog(*HTML_HANDLE, $base_dir);
3754 » write_header_line(*HTML_HANDLE, 0, "Current view:", $view, 4316
3755 » » » "Found", "Hit", "Coverage"); 4317 » # Left row
3756 » write_header_line(*HTML_HANDLE, 1, "Test:", $test, "Lines:", 4318 » push(@row_left, [[ "10%", "headerItem", "Current view:" ],
3757 » » » $lines_found, $lines_hit, 4319 » » » [ "35%", "headerValue", $view ]]);
3758 » » » $rate_name[classify_rate($lines_found, $lines_hit, 4320 » push(@row_left, [[undef, "headerItem", "Test:"],
3759 » » » » » » $med_limit, $hi_limit)], 4321 » » » [undef, "headerValue", $test]]);
3760 » » » format_rate($lines_found, $lines_hit)); 4322 » push(@row_left, [[undef, "headerItem", "Date:"],
4323 » » » [undef, "headerValue", $date]]);
4324
4325 » # Right row
4326 » if ($legend && ($type == $HDR_SOURCE || $type == $HDR_FUNC)) {
4327 » » my $text = <<END_OF_HTML;
4328 Lines:
4329 <span class="coverLegendCov">hit</span>
4330 <span class="coverLegendNoCov">not hit</span>
4331 END_OF_HTML
4332 » » if ($br_coverage) {
4333 » » » $text .= <<END_OF_HTML;
4334 | Branches:
4335 <span class="coverLegendCov">+</span> taken
4336 <span class="coverLegendNoCov">-</span> not taken
4337 <span class="coverLegendNoCov">#</span> not executed
4338 END_OF_HTML
4339 » » }
4340 » » push(@row_left, [[undef, "headerItem", "Legend:"],
4341 » » » » [undef, "headerValueLeg", $text]]);
4342 » } elsif ($legend && ($type != $HDR_TESTDESC)) {
4343 » » my $text = <<END_OF_HTML;
4344 » Rating:
4345 <span class="coverLegendCovLo" title="Coverage rates below $med_limi t % are classified as low">low: &lt; $med_limit %</span>
4346 <span class="coverLegendCovMed" title="Coverage rates between $med_l imit % and $hi_limit % are classified as medium">medium: &gt;= $med_limit %</spa n>
4347 <span class="coverLegendCovHi" title="Coverage rates of $hi_limit % and more are classified as high">high: &gt;= $hi_limit %</span>
4348 END_OF_HTML
4349 » » push(@row_left, [[undef, "headerItem", "Legend:"],
4350 » » » » [undef, "headerValueLeg", $text]]);
4351 » }
4352 » if ($type == $HDR_TESTDESC) {
4353 » » push(@row_right, [[ "55%" ]]);
4354 » } else {
4355 » » push(@row_right, [["15%", undef, undef ],
4356 » » » » ["10%", "headerCovTableHead", "Hit" ],
4357 » » » » ["10%", "headerCovTableHead", "Total" ],
4358 » » » » ["15%", "headerCovTableHead", "Coverage"]]);
4359 » }
4360 » # Line coverage
4361 » $style = $rate_name[classify_rate($lines_found, $lines_hit,
4362 » » » » » $med_limit, $hi_limit)];
4363 » $rate = rate($lines_hit, $lines_found, " %");
4364 » push(@row_right, [[undef, "headerItem", "Lines:"],
4365 » » » [undef, "headerCovTableEntry", $lines_hit],
4366 » » » [undef, "headerCovTableEntry", $lines_found],
4367 » » » [undef, "headerCovTableEntry$style", $rate]])
4368 » » » if ($type != $HDR_TESTDESC);
4369 » # Function coverage
3761 if ($func_coverage) { 4370 if ($func_coverage) {
3762 » » write_header_line(*HTML_HANDLE, 1, "Date:", $date, "Functions:", 4371 » » $style = $rate_name[classify_rate($fn_found, $fn_hit,
3763 » » » » $fn_found, $fn_hit, 4372 » » » » » » $fn_med_limit, $fn_hi_limit)];
3764 » » » » $rate_name[classify_rate($fn_found, 4373 » » $rate = rate($fn_hit, $fn_found, " %");
3765 » » » » » » » $fn_hit, 4374 » » push(@row_right, [[undef, "headerItem", "Functions:"],
3766 » » » » » » » $fn_med_limit, 4375 » » » » [undef, "headerCovTableEntry", $fn_hit],
3767 » » » » » » » $fn_hi_limit)], 4376 » » » » [undef, "headerCovTableEntry", $fn_found],
3768 » » » » format_rate($fn_found, $fn_hit)); 4377 » » » » [undef, "headerCovTableEntry$style", $rate]])
3769 » } else { 4378 » » » if ($type != $HDR_TESTDESC);
3770 » » write_header_line(*HTML_HANDLE, 4, "Date:", $date);
3771 } 4379 }
3772 » if ($legend) { 4380 » # Branch coverage
3773 » » if ($type == 0 || $type == 1) { 4381 » if ($br_coverage) {
3774 » » » my $line_code = get_legend_code("Line coverage:", 4382 » » $style = $rate_name[classify_rate($br_found, $br_hit,
3775 » » » » » » $med_limit, $hi_limit); 4383 » » » » » » $br_med_limit, $br_hi_limit)];
3776 » » » my $func_code = ""; 4384 » » $rate = rate($br_hit, $br_found, " %");
4385 » » push(@row_right, [[undef, "headerItem", "Branches:"],
4386 » » » » [undef, "headerCovTableEntry", $br_hit],
4387 » » » » [undef, "headerCovTableEntry", $br_found],
4388 » » » » [undef, "headerCovTableEntry$style", $rate]])
4389 » » » if ($type != $HDR_TESTDESC);
4390 » }
3777 4391
3778 » » » if ($func_coverage) { 4392 » # Print rows
3779 » » » » $func_code = get_legend_code( 4393 » $num_rows = max(scalar(@row_left), scalar(@row_right));
3780 » » » » » » "Function coverage:", 4394 » for ($i = 0; $i < $num_rows; $i++) {
3781 » » » » » » $fn_med_limit, 4395 » » my $left = $row_left[$i];
3782 » » » » » » $fn_hi_limit); 4396 » » my $right = $row_right[$i];
3783 » » » } 4397
3784 » » » write_header_line(*HTML_HANDLE, 2, "Colors:", 4398 » » if (!defined($left)) {
3785 » » » » $line_code, $func_code); 4399 » » » $left = [[undef, undef, undef], [undef, undef, undef]];
3786 » » } elsif ($type == 2 || $type == 4) {
3787 » » » write_header_line(*HTML_HANDLE, 3, "Colors:",
3788 » » » » » "not hit", "hit");
3789 } 4400 }
4401 if (!defined($right)) {
4402 $right = [];
4403 }
4404 write_header_line(*HTML_HANDLE, @{$left},
4405 [ $i == 0 ? "5%" : undef, undef, undef],
4406 @{$right});
3790 } 4407 }
4408
4409 # Fourth line
3791 write_header_epilog(*HTML_HANDLE, $base_dir); 4410 write_header_epilog(*HTML_HANDLE, $base_dir);
3792 } 4411 }
3793 4412
3794 4413
3795 # 4414 #
3796 # split_filename(filename)
3797 #
3798 # Return (path, filename, extension) for a given FILENAME.
3799 #
3800
3801 sub split_filename($)
3802 {
3803 if (!$_[0]) { return(); }
3804 my @path_components = split('/', $_[0]);
3805 my @file_components = split('\.', pop(@path_components));
3806 my $extension = pop(@file_components);
3807
3808 return (join("/",@path_components), join(".",@file_components),
3809 $extension);
3810 }
3811
3812 #
3813 # get_sorted_keys(hash_ref, sort_type) 4415 # get_sorted_keys(hash_ref, sort_type)
3814 # 4416 #
3815 4417
3816 sub get_sorted_keys($$) 4418 sub get_sorted_keys($$)
3817 { 4419 {
3818 my ($hash, $type) = @_; 4420 my ($hash, $type) = @_;
3819 4421
3820 » if ($type == 0) { 4422 » if ($type == $SORT_FILE) {
3821 # Sort by name 4423 # Sort by name
3822 return sort(keys(%{$hash})); 4424 return sort(keys(%{$hash}));
3823 » } elsif ($type == 1) { 4425 » } elsif ($type == $SORT_LINE) {
3824 # Sort by line coverage 4426 # Sort by line coverage
3825 » » return sort({$hash->{$a}[5] <=> $hash->{$b}[5]} keys(%{$hash})); 4427 » » return sort({$hash->{$a}[7] <=> $hash->{$b}[7]} keys(%{$hash}));
3826 » } elsif ($type == 2) { 4428 » } elsif ($type == $SORT_FUNC) {
3827 # Sort by function coverage; 4429 # Sort by function coverage;
3828 » » return sort({$hash->{$a}[6] <=> $hash->{$b}[6]}»keys(%{$hash})); 4430 » » return sort({$hash->{$a}[8] <=> $hash->{$b}[8]}»keys(%{$hash}));
4431 » } elsif ($type == $SORT_BRANCH) {
4432 » » # Sort by br coverage;
4433 » » return sort({$hash->{$a}[9] <=> $hash->{$b}[9]}»keys(%{$hash}));
3829 } 4434 }
3830 } 4435 }
3831 4436
3832 sub get_sort_code($$$) 4437 sub get_sort_code($$$)
3833 { 4438 {
3834 my ($link, $alt, $base) = @_; 4439 my ($link, $alt, $base) = @_;
3835 my $png; 4440 my $png;
3836 my $link_start; 4441 my $link_start;
3837 my $link_end; 4442 my $link_end;
3838 4443
(...skipping 12 matching lines...) Expand all
3851 'alt="'.$alt.'" title="'.$alt.'" border=0>'.$link_end.'</span>'; 4456 'alt="'.$alt.'" title="'.$alt.'" border=0>'.$link_end.'</span>';
3852 } 4457 }
3853 4458
3854 sub get_file_code($$$$) 4459 sub get_file_code($$$$)
3855 { 4460 {
3856 my ($type, $text, $sort_button, $base) = @_; 4461 my ($type, $text, $sort_button, $base) = @_;
3857 my $result = $text; 4462 my $result = $text;
3858 my $link; 4463 my $link;
3859 4464
3860 if ($sort_button) { 4465 if ($sort_button) {
3861 » » if ($type == 1) { 4466 » » if ($type == $HEAD_NO_DETAIL) {
3862 $link = "index.$html_ext"; 4467 $link = "index.$html_ext";
3863 } else { 4468 } else {
3864 $link = "index-detail.$html_ext"; 4469 $link = "index-detail.$html_ext";
3865 } 4470 }
3866 } 4471 }
3867 $result .= get_sort_code($link, "Sort by name", $base); 4472 $result .= get_sort_code($link, "Sort by name", $base);
3868 4473
3869 return $result; 4474 return $result;
3870 } 4475 }
3871 4476
3872 sub get_line_code($$$$$) 4477 sub get_line_code($$$$$)
3873 { 4478 {
3874 my ($type, $sort_type, $text, $sort_button, $base) = @_; 4479 my ($type, $sort_type, $text, $sort_button, $base) = @_;
3875 my $result = $text; 4480 my $result = $text;
3876 my $sort_link; 4481 my $sort_link;
3877 4482
3878 » if ($type == 1) { 4483 » if ($type == $HEAD_NO_DETAIL) {
3879 # Just text 4484 # Just text
3880 if ($sort_button) { 4485 if ($sort_button) {
3881 $sort_link = "index-sort-l.$html_ext"; 4486 $sort_link = "index-sort-l.$html_ext";
3882 } 4487 }
3883 » } elsif ($type == 2) { 4488 » } elsif ($type == $HEAD_DETAIL_HIDDEN) {
3884 # Text + link to detail view 4489 # Text + link to detail view
3885 $result .= ' ( <a class="detail" href="index-detail'. 4490 $result .= ' ( <a class="detail" href="index-detail'.
3886 $fileview_sortname[$sort_type].'.'.$html_ext. 4491 $fileview_sortname[$sort_type].'.'.$html_ext.
3887 '">show details</a> )'; 4492 '">show details</a> )';
3888 if ($sort_button) { 4493 if ($sort_button) {
3889 $sort_link = "index-sort-l.$html_ext"; 4494 $sort_link = "index-sort-l.$html_ext";
3890 } 4495 }
3891 } else { 4496 } else {
3892 # Text + link to standard view 4497 # Text + link to standard view
3893 $result .= ' ( <a class="detail" href="index'. 4498 $result .= ' ( <a class="detail" href="index'.
3894 $fileview_sortname[$sort_type].'.'.$html_ext. 4499 $fileview_sortname[$sort_type].'.'.$html_ext.
3895 '">hide details</a> )'; 4500 '">hide details</a> )';
3896 if ($sort_button) { 4501 if ($sort_button) {
3897 $sort_link = "index-detail-sort-l.$html_ext"; 4502 $sort_link = "index-detail-sort-l.$html_ext";
3898 } 4503 }
3899 } 4504 }
3900 # Add sort button 4505 # Add sort button
3901 $result .= get_sort_code($sort_link, "Sort by line coverage", $base); 4506 $result .= get_sort_code($sort_link, "Sort by line coverage", $base);
3902 4507
3903 return $result; 4508 return $result;
3904 } 4509 }
3905 4510
3906 sub get_func_code($$$$) 4511 sub get_func_code($$$$)
3907 { 4512 {
3908 my ($type, $text, $sort_button, $base) = @_; 4513 my ($type, $text, $sort_button, $base) = @_;
3909 my $result = $text; 4514 my $result = $text;
3910 my $link; 4515 my $link;
3911 4516
3912 if ($sort_button) { 4517 if ($sort_button) {
3913 » » if ($type == 1) { 4518 » » if ($type == $HEAD_NO_DETAIL) {
3914 $link = "index-sort-f.$html_ext"; 4519 $link = "index-sort-f.$html_ext";
3915 } else { 4520 } else {
3916 $link = "index-detail-sort-f.$html_ext"; 4521 $link = "index-detail-sort-f.$html_ext";
3917 } 4522 }
3918 } 4523 }
3919 $result .= get_sort_code($link, "Sort by function coverage", $base); 4524 $result .= get_sort_code($link, "Sort by function coverage", $base);
3920 return $result; 4525 return $result;
3921 } 4526 }
3922 4527
4528 sub get_br_code($$$$)
4529 {
4530 my ($type, $text, $sort_button, $base) = @_;
4531 my $result = $text;
4532 my $link;
4533
4534 if ($sort_button) {
4535 if ($type == $HEAD_NO_DETAIL) {
4536 $link = "index-sort-b.$html_ext";
4537 } else {
4538 $link = "index-detail-sort-b.$html_ext";
4539 }
4540 }
4541 $result .= get_sort_code($link, "Sort by branch coverage", $base);
4542 return $result;
4543 }
4544
3923 # 4545 #
3924 # write_file_table(filehandle, base_dir, overview, testhash, testfnchash, 4546 # write_file_table(filehandle, base_dir, overview, testhash, testfnchash,
3925 # fileview, sort_type) 4547 # testbrhash, fileview, sort_type)
3926 # 4548 #
3927 # Write a complete file table. OVERVIEW is a reference to a hash containing 4549 # Write a complete file table. OVERVIEW is a reference to a hash containing
3928 # the following mapping: 4550 # the following mapping:
3929 # 4551 #
3930 # filename -> "lines_found,lines_hit,funcs_found,funcs_hit,page_link, 4552 # filename -> "lines_found,lines_hit,funcs_found,funcs_hit,page_link,
3931 # func_link" 4553 # func_link"
3932 # 4554 #
3933 # TESTHASH is a reference to the following hash: 4555 # TESTHASH is a reference to the following hash:
3934 # 4556 #
3935 # filename -> \%testdata 4557 # filename -> \%testdata
3936 # %testdata: name of test affecting this file -> \%testcount 4558 # %testdata: name of test affecting this file -> \%testcount
3937 # %testcount: line number -> execution count for a single test 4559 # %testcount: line number -> execution count for a single test
3938 # 4560 #
3939 # Heading of first column is "Filename" if FILEVIEW is true, "Directory name" 4561 # Heading of first column is "Filename" if FILEVIEW is true, "Directory name"
3940 # otherwise. 4562 # otherwise.
3941 # 4563 #
3942 4564
3943 sub write_file_table(*$$$$$$) 4565 sub write_file_table(*$$$$$$$)
3944 { 4566 {
3945 local *HTML_HANDLE = $_[0]; 4567 local *HTML_HANDLE = $_[0];
3946 my $base_dir = $_[1]; 4568 my $base_dir = $_[1];
3947 my $overview = $_[2]; 4569 my $overview = $_[2];
3948 my $testhash = $_[3]; 4570 my $testhash = $_[3];
3949 my $testfnchash = $_[4]; 4571 my $testfnchash = $_[4];
3950 » my $fileview = $_[5]; 4572 » my $testbrhash = $_[5];
3951 » my $sort_type = $_[6]; 4573 » my $fileview = $_[6];
4574 » my $sort_type = $_[7];
3952 my $filename; 4575 my $filename;
3953 my $bar_graph; 4576 my $bar_graph;
3954 my $hit; 4577 my $hit;
3955 my $found; 4578 my $found;
3956 my $fn_found; 4579 my $fn_found;
3957 my $fn_hit; 4580 my $fn_hit;
4581 my $br_found;
4582 my $br_hit;
3958 my $page_link; 4583 my $page_link;
3959 my $testname; 4584 my $testname;
3960 my $testdata; 4585 my $testdata;
3961 my $testfncdata; 4586 my $testfncdata;
3962 » my $testcount; 4587 » my $testbrdata;
3963 » my $testfnccount;
3964 my %affecting_tests; 4588 my %affecting_tests;
3965 my $line_code = ""; 4589 my $line_code = "";
3966 my $func_code; 4590 my $func_code;
4591 my $br_code;
3967 my $file_code; 4592 my $file_code;
4593 my @head_columns;
3968 4594
3969 # Determine HTML code for column headings 4595 # Determine HTML code for column headings
3970 if (($base_dir ne "") && $show_details) 4596 if (($base_dir ne "") && $show_details)
3971 { 4597 {
3972 my $detailed = keys(%{$testhash}); 4598 my $detailed = keys(%{$testhash});
3973 4599
3974 » » $file_code = get_file_code($detailed ? 2 : 1, 4600 » » $file_code = get_file_code($detailed ? $HEAD_DETAIL_HIDDEN :
4601 » » » » » $HEAD_NO_DETAIL,
3975 $fileview ? "Filename" : "Directory", 4602 $fileview ? "Filename" : "Directory",
3976 » » » » » $sort && $sort_type != 0, $base_dir); 4603 » » » » » $sort && $sort_type != $SORT_FILE,
3977 » » $line_code = get_line_code($detailed ? 3 : 2, $sort_type, 4604 » » » » » $base_dir);
4605 » » $line_code = get_line_code($detailed ? $HEAD_DETAIL_SHOWN :
4606 » » » » » $HEAD_DETAIL_HIDDEN,
4607 » » » » » $sort_type,
3978 "Line Coverage", 4608 "Line Coverage",
3979 » » » » » $sort && $sort_type != 1, $base_dir); 4609 » » » » » $sort && $sort_type != $SORT_LINE,
3980 » » $func_code = get_func_code($detailed ? 2 : 1, "Functions", 4610 » » » » » $base_dir);
3981 » » » » » $sort && $sort_type != 2, $base_dir); 4611 » » $func_code = get_func_code($detailed ? $HEAD_DETAIL_HIDDEN :
4612 » » » » » $HEAD_NO_DETAIL,
4613 » » » » » "Functions",
4614 » » » » » $sort && $sort_type != $SORT_FUNC,
4615 » » » » » $base_dir);
4616 » » $br_code = get_br_code($detailed ? $HEAD_DETAIL_HIDDEN :
4617 » » » » » $HEAD_NO_DETAIL,
4618 » » » » » "Branches",
4619 » » » » » $sort && $sort_type != $SORT_BRANCH,
4620 » » » » » $base_dir);
3982 } else { 4621 } else {
3983 » » $file_code = get_file_code(1, 4622 » » $file_code = get_file_code($HEAD_NO_DETAIL,
3984 $fileview ? "Filename" : "Directory", 4623 $fileview ? "Filename" : "Directory",
3985 » » » » » $sort && $sort_type != 0, $base_dir); 4624 » » » » » $sort && $sort_type != $SORT_FILE,
3986 » » $line_code = get_line_code(1, $sort_type, "Line Coverage", 4625 » » » » » $base_dir);
3987 » » » » » $sort && $sort_type != 1, $base_dir); 4626 » » $line_code = get_line_code($HEAD_NO_DETAIL, $sort_type, "Line Co verage",
3988 » » $func_code = get_func_code(1, "Functions", 4627 » » » » » $sort && $sort_type != $SORT_LINE,
3989 » » » » » $sort && $sort_type != 2, $base_dir); 4628 » » » » » $base_dir);
4629 » » $func_code = get_func_code($HEAD_NO_DETAIL, "Functions",
4630 » » » » » $sort && $sort_type != $SORT_FUNC,
4631 » » » » » $base_dir);
4632 » » $br_code = get_br_code($HEAD_NO_DETAIL, "Branches",
4633 » » » » » $sort && $sort_type != $SORT_BRANCH,
4634 » » » » » $base_dir);
3990 } 4635 }
4636 push(@head_columns, [ $line_code, 3 ]);
4637 push(@head_columns, [ $func_code, 2]) if ($func_coverage);
4638 push(@head_columns, [ $br_code, 2]) if ($br_coverage);
3991 4639
3992 » write_file_table_prolog(*HTML_HANDLE, $file_code, $line_code, 4640 » write_file_table_prolog(*HTML_HANDLE, $file_code, @head_columns);
3993 » » » » $func_code);
3994 4641
3995 foreach $filename (get_sorted_keys($overview, $sort_type)) 4642 foreach $filename (get_sorted_keys($overview, $sort_type))
3996 { 4643 {
3997 » » ($found, $hit, $fn_found, $fn_hit, $page_link) 4644 » » my @columns;
3998 » » » = @{$overview->{$filename}}; 4645 » » ($found, $hit, $fn_found, $fn_hit, $br_found, $br_hit,
3999 » » $bar_graph = get_bar_graph_code($base_dir, $found, $hit); 4646 » » $page_link) = @{$overview->{$filename}};
4647
4648 » » # Line coverage
4649 » » push(@columns, [$found, $hit, $med_limit, $hi_limit, 1]);
4650 » » # Function coverage
4651 » » if ($func_coverage) {
4652 » » » push(@columns, [$fn_found, $fn_hit, $fn_med_limit,
4653 » » » » » $fn_hi_limit, 0]);
4654 » » }
4655 » » # Branch coverage
4656 » » if ($br_coverage) {
4657 » » » push(@columns, [$br_found, $br_hit, $br_med_limit,
4658 » » » » » $br_hi_limit, 0]);
4659 » » }
4660 » » write_file_table_entry(*HTML_HANDLE, $base_dir, $filename,
4661 » » » » $page_link, @columns);
4000 4662
4001 $testdata = $testhash->{$filename}; 4663 $testdata = $testhash->{$filename};
4002 $testfncdata = $testfnchash->{$filename}; 4664 $testfncdata = $testfnchash->{$filename};
4003 4665 » » $testbrdata = $testbrhash->{$filename};
4004 » » write_file_table_entry(*HTML_HANDLE, $filename, $bar_graph,
4005 » » » » $found, $hit, $fn_found, $fn_hit,
4006 » » » » $page_link);
4007 4666
4008 # Check whether we should write test specific coverage 4667 # Check whether we should write test specific coverage
4009 # as well 4668 # as well
4010 if (!($show_details && $testdata)) { next; } 4669 if (!($show_details && $testdata)) { next; }
4011 4670
4012 # Filter out those tests that actually affect this file 4671 # Filter out those tests that actually affect this file
4013 %affecting_tests = %{ get_affecting_tests($testdata, 4672 %affecting_tests = %{ get_affecting_tests($testdata,
4014 » » » » » $testfncdata) }; 4673 » » » » » $testfncdata, $testbrdata) };
4015 4674
4016 # Does any of the tests affect this file at all? 4675 # Does any of the tests affect this file at all?
4017 if (!%affecting_tests) { next; } 4676 if (!%affecting_tests) { next; }
4018 4677
4019 # Write test details for this entry
4020 write_file_table_detail_heading(*HTML_HANDLE, "Test name",
4021 "Lines hit", "Functions hit");
4022
4023 foreach $testname (keys(%affecting_tests)) 4678 foreach $testname (keys(%affecting_tests))
4024 { 4679 {
4025 » » » ($found, $hit, $fn_found, $fn_hit) = 4680 » » » my @results;
4681 » » » ($found, $hit, $fn_found, $fn_hit, $br_found, $br_hit) =
4026 split(",", $affecting_tests{$testname}); 4682 split(",", $affecting_tests{$testname});
4027 4683
4028 # Insert link to description of available 4684 # Insert link to description of available
4029 if ($test_description{$testname}) 4685 if ($test_description{$testname})
4030 { 4686 {
4031 $testname = "<a href=\"$base_dir". 4687 $testname = "<a href=\"$base_dir".
4032 "descriptions.$html_ext#$testname\"> ". 4688 "descriptions.$html_ext#$testname\"> ".
4033 "$testname</a>"; 4689 "$testname</a>";
4034 } 4690 }
4035 4691
4692 push(@results, [$found, $hit]);
4693 push(@results, [$fn_found, $fn_hit]) if ($func_coverage) ;
4694 push(@results, [$br_found, $br_hit]) if ($br_coverage);
4036 write_file_table_detail_entry(*HTML_HANDLE, $testname, 4695 write_file_table_detail_entry(*HTML_HANDLE, $testname,
4037 » » » » $found, $hit, $fn_found, $fn_hit); 4696 » » » » @results);
4038 } 4697 }
4039 } 4698 }
4040 4699
4041 write_file_table_epilog(*HTML_HANDLE); 4700 write_file_table_epilog(*HTML_HANDLE);
4042 } 4701 }
4043 4702
4044 4703
4045 # 4704 #
4046 # get_found_and_hit(hash) 4705 # get_found_and_hit(hash)
4047 # 4706 #
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
4088 foreach $function (keys(%{$sumfnccount})) { 4747 foreach $function (keys(%{$sumfnccount})) {
4089 if ($sumfnccount->{$function} > 0) { 4748 if ($sumfnccount->{$function} > 0) {
4090 $fn_hit++; 4749 $fn_hit++;
4091 } 4750 }
4092 } 4751 }
4093 return ($fn_found, $fn_hit); 4752 return ($fn_found, $fn_hit);
4094 } 4753 }
4095 4754
4096 4755
4097 # 4756 #
4098 # get_affecting_tests(testdata, testfncdata) 4757 # br_taken_to_num(taken)
4758 #
4759 # Convert a branch taken value .info format to number format.
4760 #
4761
4762 sub br_taken_to_num($)
4763 {
4764 » my ($taken) = @_;
4765
4766 » return 0 if ($taken eq '-');
4767 » return $taken + 1;
4768 }
4769
4770
4771 #
4772 # br_num_to_taken(taken)
4773 #
4774 # Convert a branch taken value in number format to .info format.
4775 #
4776
4777 sub br_num_to_taken($)
4778 {
4779 » my ($taken) = @_;
4780
4781 » return '-' if ($taken == 0);
4782 » return $taken - 1;
4783 }
4784
4785
4786 #
4787 # br_taken_add(taken1, taken2)
4788 #
4789 # Return the result of taken1 + taken2 for 'branch taken' values.
4790 #
4791
4792 sub br_taken_add($$)
4793 {
4794 » my ($t1, $t2) = @_;
4795
4796 » return $t1 if (!defined($t2));
4797 » return $t2 if (!defined($t1));
4798 » return $t1 if ($t2 eq '-');
4799 » return $t2 if ($t1 eq '-');
4800 » return $t1 + $t2;
4801 }
4802
4803
4804 #
4805 # br_taken_sub(taken1, taken2)
4806 #
4807 # Return the result of taken1 - taken2 for 'branch taken' values. Return 0
4808 # if the result would become negative.
4809 #
4810
4811 sub br_taken_sub($$)
4812 {
4813 » my ($t1, $t2) = @_;
4814
4815 » return $t1 if (!defined($t2));
4816 » return undef if (!defined($t1));
4817 » return $t1 if ($t1 eq '-');
4818 » return $t1 if ($t2 eq '-');
4819 » return 0 if $t2 > $t1;
4820 » return $t1 - $t2;
4821 }
4822
4823
4824 #
4825 # br_ivec_len(vector)
4826 #
4827 # Return the number of entries in the branch coverage vector.
4828 #
4829
4830 sub br_ivec_len($)
4831 {
4832 » my ($vec) = @_;
4833
4834 » return 0 if (!defined($vec));
4835 » return (length($vec) * 8 / $BR_VEC_WIDTH) / $BR_VEC_ENTRIES;
4836 }
4837
4838
4839 #
4840 # br_ivec_get(vector, number)
4841 #
4842 # Return an entry from the branch coverage vector.
4843 #
4844
4845 sub br_ivec_get($$)
4846 {
4847 » my ($vec, $num) = @_;
4848 » my $block;
4849 » my $branch;
4850 » my $taken;
4851 » my $offset = $num * $BR_VEC_ENTRIES;
4852
4853 » # Retrieve data from vector
4854 » $block» = vec($vec, $offset + $BR_BLOCK, $BR_VEC_WIDTH);
4855 » $branch = vec($vec, $offset + $BR_BRANCH, $BR_VEC_WIDTH);
4856 » $taken» = vec($vec, $offset + $BR_TAKEN, $BR_VEC_WIDTH);
4857
4858 » # Decode taken value from an integer
4859 » $taken = br_num_to_taken($taken);
4860
4861 » return ($block, $branch, $taken);
4862 }
4863
4864
4865 #
4866 # br_ivec_push(vector, block, branch, taken)
4867 #
4868 # Add an entry to the branch coverage vector. If an entry with the same
4869 # branch ID already exists, add the corresponding taken values.
4870 #
4871
4872 sub br_ivec_push($$$$)
4873 {
4874 » my ($vec, $block, $branch, $taken) = @_;
4875 » my $offset;
4876 » my $num = br_ivec_len($vec);
4877 » my $i;
4878
4879 » $vec = "" if (!defined($vec));
4880
4881 » # Check if branch already exists in vector
4882 » for ($i = 0; $i < $num; $i++) {
4883 » » my ($v_block, $v_branch, $v_taken) = br_ivec_get($vec, $i);
4884
4885 » » next if ($v_block != $block || $v_branch != $branch);
4886
4887 » » # Add taken counts
4888 » » $taken = br_taken_add($taken, $v_taken);
4889 » » last;
4890 » }
4891
4892 » $offset = $i * $BR_VEC_ENTRIES;
4893 » $taken = br_taken_to_num($taken);
4894
4895 » # Add to vector
4896 » vec($vec, $offset + $BR_BLOCK, $BR_VEC_WIDTH) = $block;
4897 » vec($vec, $offset + $BR_BRANCH, $BR_VEC_WIDTH) = $branch;
4898 » vec($vec, $offset + $BR_TAKEN, $BR_VEC_WIDTH) = $taken;
4899
4900 » return $vec;
4901 }
4902
4903
4904 #
4905 # get_br_found_and_hit(sumbrcount)
4906 #
4907 # Return (br_found, br_hit) for sumbrcount
4908 #
4909
4910 sub get_br_found_and_hit($)
4911 {
4912 » my ($sumbrcount) = @_;
4913 » my $line;
4914 » my $br_found = 0;
4915 » my $br_hit = 0;
4916
4917 » foreach $line (keys(%{$sumbrcount})) {
4918 » » my $brdata = $sumbrcount->{$line};
4919 » » my $i;
4920 » » my $num = br_ivec_len($brdata);
4921
4922 » » for ($i = 0; $i < $num; $i++) {
4923 » » » my $taken;
4924
4925 » » » (undef, undef, $taken) = br_ivec_get($brdata, $i);
4926
4927 » » » $br_found++;
4928 » » » $br_hit++ if ($taken ne "-" && $taken > 0);
4929 » » }
4930 » }
4931
4932 » return ($br_found, $br_hit);
4933 }
4934
4935
4936 #
4937 # get_affecting_tests(testdata, testfncdata, testbrdata)
4099 # 4938 #
4100 # HASHREF contains a mapping filename -> (linenumber -> exec count). Return 4939 # HASHREF contains a mapping filename -> (linenumber -> exec count). Return
4101 # a hash containing mapping filename -> "lines found, lines hit" for each 4940 # a hash containing mapping filename -> "lines found, lines hit" for each
4102 # filename which has a nonzero hit count. 4941 # filename which has a nonzero hit count.
4103 # 4942 #
4104 4943
4105 sub get_affecting_tests($$) 4944 sub get_affecting_tests($$$)
4106 { 4945 {
4107 » my $testdata = $_[0]; 4946 » my ($testdata, $testfncdata, $testbrdata) = @_;
4108 » my $testfncdata = $_[1];
4109 my $testname; 4947 my $testname;
4110 my $testcount; 4948 my $testcount;
4111 my $testfnccount; 4949 my $testfnccount;
4950 my $testbrcount;
4112 my %result; 4951 my %result;
4113 my $found; 4952 my $found;
4114 my $hit; 4953 my $hit;
4115 my $fn_found; 4954 my $fn_found;
4116 my $fn_hit; 4955 my $fn_hit;
4956 my $br_found;
4957 my $br_hit;
4117 4958
4118 foreach $testname (keys(%{$testdata})) 4959 foreach $testname (keys(%{$testdata}))
4119 { 4960 {
4120 # Get (line number -> count) hash for this test case 4961 # Get (line number -> count) hash for this test case
4121 $testcount = $testdata->{$testname}; 4962 $testcount = $testdata->{$testname};
4122 $testfnccount = $testfncdata->{$testname}; 4963 $testfnccount = $testfncdata->{$testname};
4964 $testbrcount = $testbrdata->{$testname};
4123 4965
4124 # Calculate sum 4966 # Calculate sum
4125 ($found, $hit) = get_found_and_hit($testcount); 4967 ($found, $hit) = get_found_and_hit($testcount);
4126 ($fn_found, $fn_hit) = get_func_found_and_hit($testfnccount); 4968 ($fn_found, $fn_hit) = get_func_found_and_hit($testfnccount);
4969 ($br_found, $br_hit) = get_br_found_and_hit($testbrcount);
4127 4970
4128 if ($hit>0) 4971 if ($hit>0)
4129 { 4972 {
4130 » » » $result{$testname} = "$found,$hit,$fn_found,$fn_hit"; 4973 » » » $result{$testname} = "$found,$hit,$fn_found,$fn_hit,".
4974 » » » » » "$br_found,$br_hit";
4131 } 4975 }
4132 } 4976 }
4133 4977
4134 return(\%result); 4978 return(\%result);
4135 } 4979 }
4136 4980
4137 4981
4138 sub get_hash_reverse($) 4982 sub get_hash_reverse($)
4139 { 4983 {
4140 my ($hash) = @_; 4984 my ($hash) = @_;
4141 my %result; 4985 my %result;
4142 4986
4143 foreach (keys(%{$hash})) { 4987 foreach (keys(%{$hash})) {
4144 $result{$hash->{$_}} = $_; 4988 $result{$hash->{$_}} = $_;
4145 } 4989 }
4146 4990
4147 return \%result; 4991 return \%result;
4148 } 4992 }
4149 4993
4150 # 4994 #
4151 # write_source(filehandle, source_filename, count_data, checksum_data, 4995 # write_source(filehandle, source_filename, count_data, checksum_data,
4152 # converted_data, func_data) 4996 # converted_data, func_data, sumbrcount)
4153 # 4997 #
4154 # Write an HTML view of a source code file. Returns a list containing 4998 # Write an HTML view of a source code file. Returns a list containing
4155 # data as needed by gen_png(). 4999 # data as needed by gen_png().
4156 # 5000 #
4157 # Die on error. 5001 # Die on error.
4158 # 5002 #
4159 5003
4160 sub write_source($$$$$$) 5004 sub write_source($$$$$$$)
4161 { 5005 {
4162 local *HTML_HANDLE = $_[0]; 5006 local *HTML_HANDLE = $_[0];
4163 local *SOURCE_HANDLE; 5007 local *SOURCE_HANDLE;
4164 my $source_filename = $_[1]; 5008 my $source_filename = $_[1];
4165 my %count_data; 5009 my %count_data;
4166 my $line_number; 5010 my $line_number;
4167 my @result; 5011 my @result;
4168 my $checkdata = $_[3]; 5012 my $checkdata = $_[3];
4169 my $converted = $_[4]; 5013 my $converted = $_[4];
4170 my $funcdata = $_[5]; 5014 my $funcdata = $_[5];
5015 my $sumbrcount = $_[6];
4171 my $datafunc = get_hash_reverse($funcdata); 5016 my $datafunc = get_hash_reverse($funcdata);
4172 my $add_anchor; 5017 my $add_anchor;
5018 my @file;
4173 5019
4174 if ($_[2]) 5020 if ($_[2])
4175 { 5021 {
4176 %count_data = %{$_[2]}; 5022 %count_data = %{$_[2]};
4177 } 5023 }
4178 5024
4179 » open(SOURCE_HANDLE, "<".$source_filename) 5025 » if (!open(SOURCE_HANDLE, "<", $source_filename)) {
4180 # or die("ERROR: cannot open $source_filename for reading!\n"); 5026 » » my @lines;
4181 or open(SOURCE_HANDLE, "</dev/null"); 5027 » » my $last_line = 0;
5028
5029 » » if (!$ignore[$ERROR_SOURCE]) {
5030 » » » die("ERROR: cannot read $source_filename\n");
5031 » » }
5032
5033 » » # Continue without source file
5034 » » warn("WARNING: cannot read $source_filename!\n");
5035
5036 » » @lines = sort( { $a <=> $b } keys(%count_data));
5037 » » if (@lines) {
5038 » » » $last_line = $lines[scalar(@lines) - 1];
5039 » » }
5040 » » return ( ":" ) if ($last_line < 1);
5041
5042 » » # Simulate gcov behavior
5043 » » for ($line_number = 1; $line_number <= $last_line;
5044 » » $line_number++) {
5045 » » » push(@file, "/* EOF */");
5046 » » }
5047 » } else {
5048 » » @file = <SOURCE_HANDLE>;
5049 » }
4182 5050
4183 write_source_prolog(*HTML_HANDLE); 5051 write_source_prolog(*HTML_HANDLE);
5052 $line_number = 0;
5053 foreach (@file) {
5054 $line_number++;
5055 chomp($_);
4184 5056
4185 » for ($line_number = 1; <SOURCE_HANDLE> ; $line_number++) 5057 » » # Also remove CR from line-end
4186 » { 5058 » » s/\015$//;
4187 » » chomp($_);
4188 5059
4189 # Source code matches coverage data? 5060 # Source code matches coverage data?
4190 if (defined($checkdata->{$line_number}) && 5061 if (defined($checkdata->{$line_number}) &&
4191 ($checkdata->{$line_number} ne md5_base64($_))) 5062 ($checkdata->{$line_number} ne md5_base64($_)))
4192 { 5063 {
4193 die("ERROR: checksum mismatch at $source_filename:". 5064 die("ERROR: checksum mismatch at $source_filename:".
4194 "$line_number\n"); 5065 "$line_number\n");
4195 } 5066 }
4196 5067
4197 $add_anchor = 0; 5068 $add_anchor = 0;
4198 if ($frames) { 5069 if ($frames) {
4199 if (($line_number - 1) % $nav_resolution == 0) { 5070 if (($line_number - 1) % $nav_resolution == 0) {
4200 $add_anchor = 1; 5071 $add_anchor = 1;
4201 } 5072 }
4202 } 5073 }
4203 if ($func_coverage) { 5074 if ($func_coverage) {
4204 if ($line_number == 1) { 5075 if ($line_number == 1) {
4205 $add_anchor = 1; 5076 $add_anchor = 1;
4206 } elsif (defined($datafunc->{$line_number + 5077 } elsif (defined($datafunc->{$line_number +
4207 $func_offset})) { 5078 $func_offset})) {
4208 $add_anchor = 1; 5079 $add_anchor = 1;
4209 } 5080 }
4210 } 5081 }
4211 push (@result, 5082 push (@result,
4212 write_source_line(HTML_HANDLE, $line_number, 5083 write_source_line(HTML_HANDLE, $line_number,
4213 $_, $count_data{$line_number}, 5084 $_, $count_data{$line_number},
4214 $converted->{$line_number}, 5085 $converted->{$line_number},
4215 » » » » » $add_anchor)); 5086 » » » » » $sumbrcount->{$line_number}, $add_anchor ));
4216 } 5087 }
4217 5088
4218 close(SOURCE_HANDLE); 5089 close(SOURCE_HANDLE);
4219 write_source_epilog(*HTML_HANDLE); 5090 write_source_epilog(*HTML_HANDLE);
4220 return(@result); 5091 return(@result);
4221 } 5092 }
4222 5093
4223 5094
4224 sub funcview_get_func_code($$$) 5095 sub funcview_get_func_code($$$)
4225 { 5096 {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
4264 5135
4265 if ($type == 0) { 5136 if ($type == 0) {
4266 return sort(keys(%{$funcdata})); 5137 return sort(keys(%{$funcdata}));
4267 } 5138 }
4268 return sort({$sumfncdata->{$b} <=> $sumfncdata->{$a}} 5139 return sort({$sumfncdata->{$b} <=> $sumfncdata->{$a}}
4269 keys(%{$sumfncdata})); 5140 keys(%{$sumfncdata}));
4270 } 5141 }
4271 5142
4272 # 5143 #
4273 # write_function_table(filehandle, source_file, sumcount, funcdata, 5144 # write_function_table(filehandle, source_file, sumcount, funcdata,
4274 #» » sumfnccount, testfncdata) 5145 #» » sumfnccount, testfncdata, sumbrcount, testbrdata,
5146 #» » base_name, base_dir, sort_type)
4275 # 5147 #
4276 # Write an HTML table listing all functions in a source file, including 5148 # Write an HTML table listing all functions in a source file, including
4277 # also function call counts and line coverages inside of each function. 5149 # also function call counts and line coverages inside of each function.
4278 # 5150 #
4279 # Die on error. 5151 # Die on error.
4280 # 5152 #
4281 5153
4282 sub write_function_table(*$$$$$$$$) 5154 sub write_function_table(*$$$$$$$$$$)
4283 { 5155 {
4284 local *HTML_HANDLE = $_[0]; 5156 local *HTML_HANDLE = $_[0];
4285 my $source = $_[1]; 5157 my $source = $_[1];
4286 my $sumcount = $_[2]; 5158 my $sumcount = $_[2];
4287 my $funcdata = $_[3]; 5159 my $funcdata = $_[3];
4288 my $sumfncdata = $_[4]; 5160 my $sumfncdata = $_[4];
4289 my $testfncdata = $_[5]; 5161 my $testfncdata = $_[5];
4290 » my $name = $_[6]; 5162 » my $sumbrcount = $_[6];
4291 » my $base = $_[7]; 5163 » my $testbrdata = $_[7];
4292 » my $type = $_[8]; 5164 » my $name = $_[8];
5165 » my $base = $_[9];
5166 » my $type = $_[10];
4293 my $func; 5167 my $func;
4294 my $func_code; 5168 my $func_code;
4295 my $count_code; 5169 my $count_code;
4296 5170
4297 # Get HTML code for headings 5171 # Get HTML code for headings
4298 $func_code = funcview_get_func_code($name, $base, $type); 5172 $func_code = funcview_get_func_code($name, $base, $type);
4299 $count_code = funcview_get_count_code($name, $base, $type); 5173 $count_code = funcview_get_count_code($name, $base, $type);
4300 write_html(*HTML_HANDLE, <<END_OF_HTML) 5174 write_html(*HTML_HANDLE, <<END_OF_HTML)
4301 <center> 5175 <center>
4302 <table width="60%" cellpadding=1 cellspacing=1 border=0> 5176 <table width="60%" cellpadding=1 cellspacing=1 border=0>
4303 <tr><td><br></td></tr> 5177 <tr><td><br></td></tr>
4304 <tr> 5178 <tr>
4305 <td width="80%" class="tableHead">$func_code</td> 5179 <td width="80%" class="tableHead">$func_code</td>
4306 <td width="20%" class="tableHead">$count_code</td> 5180 <td width="20%" class="tableHead">$count_code</td>
4307 </tr> 5181 </tr>
4308 END_OF_HTML 5182 END_OF_HTML
4309 ; 5183 ;
4310 5184
4311 # Get a sorted table 5185 # Get a sorted table
4312 foreach $func (funcview_get_sorted($funcdata, $sumfncdata, $type)) { 5186 foreach $func (funcview_get_sorted($funcdata, $sumfncdata, $type)) {
5187 if (!defined($funcdata->{$func}))
5188 {
5189 next;
5190 }
5191
4313 my $startline = $funcdata->{$func} - $func_offset; 5192 my $startline = $funcdata->{$func} - $func_offset;
4314 » » my $name = escape_html($func); 5193 » » my $name = $func;
4315 my $count = $sumfncdata->{$name}; 5194 my $count = $sumfncdata->{$name};
4316 my $countstyle; 5195 my $countstyle;
4317 5196
5197 # Demangle C++ function names if requested
5198 if ($demangle_cpp) {
5199 $name = `c++filt "$name"`;
5200 chomp($name);
5201 }
5202 # Escape any remaining special characters
5203 $name = escape_html($name);
4318 if ($startline < 1) { 5204 if ($startline < 1) {
4319 $startline = 1; 5205 $startline = 1;
4320 } 5206 }
4321 if ($count == 0) { 5207 if ($count == 0) {
4322 $countstyle = "coverFnLo"; 5208 $countstyle = "coverFnLo";
4323 } else { 5209 } else {
4324 $countstyle = "coverFnHi"; 5210 $countstyle = "coverFnHi";
4325 } 5211 }
4326 5212
4327 write_html(*HTML_HANDLE, <<END_OF_HTML) 5213 write_html(*HTML_HANDLE, <<END_OF_HTML)
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
4396 5282
4397 # 5283 #
4398 # subtract_fnccounts(data, base) 5284 # subtract_fnccounts(data, base)
4399 # 5285 #
4400 # Subtract function call counts found in base from those in data. 5286 # Subtract function call counts found in base from those in data.
4401 # Return (data, f_found, f_hit). 5287 # Return (data, f_found, f_hit).
4402 # 5288 #
4403 5289
4404 sub subtract_fnccounts($$) 5290 sub subtract_fnccounts($$)
4405 { 5291 {
4406 » my %data = %{$_[0]}; 5292 » my %data;
4407 » my %base = %{$_[1]}; 5293 » my %base;
4408 my $func; 5294 my $func;
4409 my $data_count; 5295 my $data_count;
4410 my $base_count; 5296 my $base_count;
4411 my $fn_hit = 0; 5297 my $fn_hit = 0;
4412 my $fn_found = 0; 5298 my $fn_found = 0;
4413 5299
5300 %data = %{$_[0]} if (defined($_[0]));
5301 %base = %{$_[1]} if (defined($_[1]));
4414 foreach $func (keys(%data)) { 5302 foreach $func (keys(%data)) {
4415 $fn_found++; 5303 $fn_found++;
4416 $data_count = $data{$func}; 5304 $data_count = $data{$func};
4417 $base_count = $base{$func}; 5305 $base_count = $base{$func};
4418 5306
4419 if (defined($base_count)) { 5307 if (defined($base_count)) {
4420 $data_count -= $base_count; 5308 $data_count -= $base_count;
4421 5309
4422 # Make sure we don't get negative numbers 5310 # Make sure we don't get negative numbers
4423 if ($data_count < 0) { 5311 if ($data_count < 0) {
(...skipping 22 matching lines...) Expand all
4446 { 5334 {
4447 my %data_hash = %{$_[0]}; 5335 my %data_hash = %{$_[0]};
4448 my %base_hash = %{$_[1]}; 5336 my %base_hash = %{$_[1]};
4449 my $filename; 5337 my $filename;
4450 my $testname; 5338 my $testname;
4451 my $data; 5339 my $data;
4452 my $data_testdata; 5340 my $data_testdata;
4453 my $data_funcdata; 5341 my $data_funcdata;
4454 my $data_checkdata; 5342 my $data_checkdata;
4455 my $data_testfncdata; 5343 my $data_testfncdata;
5344 my $data_testbrdata;
4456 my $data_count; 5345 my $data_count;
4457 my $data_testfnccount; 5346 my $data_testfnccount;
5347 my $data_testbrcount;
4458 my $base; 5348 my $base;
4459 my $base_checkdata; 5349 my $base_checkdata;
4460 my $base_sumfnccount; 5350 my $base_sumfnccount;
5351 my $base_sumbrcount;
4461 my $base_count; 5352 my $base_count;
4462 my $sumcount; 5353 my $sumcount;
4463 my $sumfnccount; 5354 my $sumfnccount;
5355 my $sumbrcount;
4464 my $found; 5356 my $found;
4465 my $hit; 5357 my $hit;
4466 my $fn_found; 5358 my $fn_found;
4467 my $fn_hit; 5359 my $fn_hit;
5360 my $br_found;
5361 my $br_hit;
4468 5362
4469 foreach $filename (keys(%data_hash)) 5363 foreach $filename (keys(%data_hash))
4470 { 5364 {
4471 # Get data set for data and baseline 5365 # Get data set for data and baseline
4472 $data = $data_hash{$filename}; 5366 $data = $data_hash{$filename};
4473 $base = $base_hash{$filename}; 5367 $base = $base_hash{$filename};
4474 5368
4475 # Skip data entries for which no base entry exists 5369 # Skip data entries for which no base entry exists
4476 if (!defined($base)) 5370 if (!defined($base))
4477 { 5371 {
4478 next; 5372 next;
4479 } 5373 }
4480 5374
4481 # Get set entries for data and baseline 5375 # Get set entries for data and baseline
4482 ($data_testdata, undef, $data_funcdata, $data_checkdata, 5376 ($data_testdata, undef, $data_funcdata, $data_checkdata,
4483 » » $data_testfncdata) = get_info_entry($data); 5377 » » $data_testfncdata, undef, $data_testbrdata) =
5378 » » » get_info_entry($data);
4484 (undef, $base_count, undef, $base_checkdata, undef, 5379 (undef, $base_count, undef, $base_checkdata, undef,
4485 » » $base_sumfnccount) = get_info_entry($base); 5380 » » $base_sumfnccount, undef, $base_sumbrcount) =
5381 » » » get_info_entry($base);
4486 5382
4487 # Check for compatible checksums 5383 # Check for compatible checksums
4488 merge_checksums($data_checkdata, $base_checkdata, $filename); 5384 merge_checksums($data_checkdata, $base_checkdata, $filename);
4489 5385
4490 # sumcount has to be calculated anew 5386 # sumcount has to be calculated anew
4491 $sumcount = {}; 5387 $sumcount = {};
4492 $sumfnccount = {}; 5388 $sumfnccount = {};
5389 $sumbrcount = {};
4493 5390
4494 # For each test case, subtract test specific counts 5391 # For each test case, subtract test specific counts
4495 foreach $testname (keys(%{$data_testdata})) 5392 foreach $testname (keys(%{$data_testdata}))
4496 { 5393 {
4497 # Get counts of both data and baseline 5394 # Get counts of both data and baseline
4498 $data_count = $data_testdata->{$testname}; 5395 $data_count = $data_testdata->{$testname};
4499 $data_testfnccount = $data_testfncdata->{$testname}; 5396 $data_testfnccount = $data_testfncdata->{$testname};
5397 $data_testbrcount = $data_testbrdata->{$testname};
4500 5398
4501 ($data_count, undef, $hit) = 5399 ($data_count, undef, $hit) =
4502 subtract_counts($data_count, $base_count); 5400 subtract_counts($data_count, $base_count);
4503 ($data_testfnccount) = 5401 ($data_testfnccount) =
4504 subtract_fnccounts($data_testfnccount, 5402 subtract_fnccounts($data_testfnccount,
4505 $base_sumfnccount); 5403 $base_sumfnccount);
5404 ($data_testbrcount) =
5405 combine_brcount($data_testbrcount,
5406 $base_sumbrcount, $BR_SUB);
5407
4506 5408
4507 # Check whether this test case did hit any line at all 5409 # Check whether this test case did hit any line at all
4508 if ($hit > 0) 5410 if ($hit > 0)
4509 { 5411 {
4510 # Write back resulting hash 5412 # Write back resulting hash
4511 $data_testdata->{$testname} = $data_count; 5413 $data_testdata->{$testname} = $data_count;
4512 $data_testfncdata->{$testname} = 5414 $data_testfncdata->{$testname} =
4513 $data_testfnccount; 5415 $data_testfnccount;
5416 $data_testbrdata->{$testname} =
5417 $data_testbrcount;
4514 } 5418 }
4515 else 5419 else
4516 { 5420 {
4517 # Delete test case which did not impact this 5421 # Delete test case which did not impact this
4518 # file 5422 # file
4519 delete($data_testdata->{$testname}); 5423 delete($data_testdata->{$testname});
4520 delete($data_testfncdata->{$testname}); 5424 delete($data_testfncdata->{$testname});
5425 delete($data_testbrdata->{$testname});
4521 } 5426 }
4522 5427
4523 # Add counts to sum of counts 5428 # Add counts to sum of counts
4524 ($sumcount, $found, $hit) = 5429 ($sumcount, $found, $hit) =
4525 add_counts($sumcount, $data_count); 5430 add_counts($sumcount, $data_count);
4526 ($sumfnccount, $fn_found, $fn_hit) = 5431 ($sumfnccount, $fn_found, $fn_hit) =
4527 » » » » add_fnccounts($sumfnccount, $data_testfnccount); 5432 » » » » add_fnccount($sumfnccount, $data_testfnccount);
5433 » » » ($sumbrcount, $br_found, $br_hit) =
5434 » » » » combine_brcount($sumbrcount, $data_testbrcount,
5435 » » » » » » $BR_ADD);
4528 } 5436 }
4529 5437
4530 # Write back resulting entry 5438 # Write back resulting entry
4531 set_info_entry($data, $data_testdata, $sumcount, $data_funcdata, 5439 set_info_entry($data, $data_testdata, $sumcount, $data_funcdata,
4532 $data_checkdata, $data_testfncdata, $sumfnccount, 5440 $data_checkdata, $data_testfncdata, $sumfnccount,
4533 » » » $found, $hit, $fn_found, $fn_hit); 5441 » » » $data_testbrdata, $sumbrcount, $found, $hit,
5442 » » » $fn_found, $fn_hit, $br_found, $br_hit);
4534 5443
4535 $data_hash{$filename} = $data; 5444 $data_hash{$filename} = $data;
4536 } 5445 }
4537 5446
4538 return (\%data_hash); 5447 return (\%data_hash);
4539 } 5448 }
4540 5449
4541 5450
4542 # 5451 #
4543 # remove_unused_descriptions() 5452 # remove_unused_descriptions()
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
4620 # 5529 #
4621 5530
4622 sub system_no_output($@) 5531 sub system_no_output($@)
4623 { 5532 {
4624 my $mode = shift; 5533 my $mode = shift;
4625 my $result; 5534 my $result;
4626 local *OLD_STDERR; 5535 local *OLD_STDERR;
4627 local *OLD_STDOUT; 5536 local *OLD_STDOUT;
4628 5537
4629 # Save old stdout and stderr handles 5538 # Save old stdout and stderr handles
4630 » ($mode & 1) && open(OLD_STDOUT, ">>&STDOUT"); 5539 » ($mode & 1) && open(OLD_STDOUT, ">>&", "STDOUT");
4631 » ($mode & 2) && open(OLD_STDERR, ">>&STDERR"); 5540 » ($mode & 2) && open(OLD_STDERR, ">>&", "STDERR");
4632 5541
4633 # Redirect to /dev/null 5542 # Redirect to /dev/null
4634 » ($mode & 1) && open(STDOUT, ">/dev/null"); 5543 » ($mode & 1) && open(STDOUT, ">", "/dev/null");
4635 » ($mode & 2) && open(STDERR, ">/dev/null"); 5544 » ($mode & 2) && open(STDERR, ">", "/dev/null");
4636 5545
4637 system(@_); 5546 system(@_);
4638 $result = $?; 5547 $result = $?;
4639 5548
4640 # Close redirected handles 5549 # Close redirected handles
4641 ($mode & 1) && close(STDOUT); 5550 ($mode & 1) && close(STDOUT);
4642 ($mode & 2) && close(STDERR); 5551 ($mode & 2) && close(STDERR);
4643 5552
4644 # Restore old handles 5553 # Restore old handles
4645 » ($mode & 1) && open(STDOUT, ">>&OLD_STDOUT"); 5554 » ($mode & 1) && open(STDOUT, ">>&", "OLD_STDOUT");
4646 » ($mode & 2) && open(STDERR, ">>&OLD_STDERR"); 5555 » ($mode & 2) && open(STDERR, ">>&", "OLD_STDERR");
4647 5556
4648 return $result; 5557 return $result;
4649 } 5558 }
4650 5559
4651 5560
4652 # 5561 #
4653 # read_config(filename) 5562 # read_config(filename)
4654 # 5563 #
4655 # Read configuration file FILENAME and return a reference to a hash containing 5564 # Read configuration file FILENAME and return a reference to a hash containing
4656 # all valid key=value pairs found. 5565 # all valid key=value pairs found.
4657 # 5566 #
4658 5567
4659 sub read_config($) 5568 sub read_config($)
4660 { 5569 {
4661 my $filename = $_[0]; 5570 my $filename = $_[0];
4662 my %result; 5571 my %result;
4663 my $key; 5572 my $key;
4664 my $value; 5573 my $value;
4665 local *HANDLE; 5574 local *HANDLE;
4666 5575
4667 » if (!open(HANDLE, "<$filename")) 5576 » if (!open(HANDLE, "<", $filename))
4668 { 5577 {
4669 warn("WARNING: cannot read configuration file $filename\n"); 5578 warn("WARNING: cannot read configuration file $filename\n");
4670 return undef; 5579 return undef;
4671 } 5580 }
4672 while (<HANDLE>) 5581 while (<HANDLE>)
4673 { 5582 {
4674 chomp; 5583 chomp;
4675 # Skip comments 5584 # Skip comments
4676 s/#.*//; 5585 s/#.*//;
4677 # Remove leading blanks 5586 # Remove leading blanks
(...skipping 18 matching lines...) Expand all
4696 5605
4697 5606
4698 # 5607 #
4699 # apply_config(REF) 5608 # apply_config(REF)
4700 # 5609 #
4701 # REF is a reference to a hash containing the following mapping: 5610 # REF is a reference to a hash containing the following mapping:
4702 # 5611 #
4703 # key_string => var_ref 5612 # key_string => var_ref
4704 # 5613 #
4705 # where KEY_STRING is a keyword and VAR_REF is a reference to an associated 5614 # where KEY_STRING is a keyword and VAR_REF is a reference to an associated
4706 # variable. If the global configuration hash CONFIG contains a value for 5615 # variable. If the global configuration hashes CONFIG or OPT_RC contain a value
4707 # keyword KEY_STRING, VAR_REF will be assigned the value for that keyword. 5616 # for keyword KEY_STRING, VAR_REF will be assigned the value for that keyword.
4708 # 5617 #
4709 5618
4710 sub apply_config($) 5619 sub apply_config($)
4711 { 5620 {
4712 my $ref = $_[0]; 5621 my $ref = $_[0];
4713 5622
4714 foreach (keys(%{$ref})) 5623 foreach (keys(%{$ref}))
4715 { 5624 {
4716 » » if (defined($config->{$_})) 5625 » » if (defined($opt_rc{$_})) {
4717 » » { 5626 » » » ${$ref->{$_}} = $opt_rc{$_};
5627 » » } elsif (defined($config->{$_})) {
4718 ${$ref->{$_}} = $config->{$_}; 5628 ${$ref->{$_}} = $config->{$_};
4719 } 5629 }
4720 } 5630 }
4721 } 5631 }
4722 5632
4723 5633
4724 # 5634 #
4725 # get_html_prolog(FILENAME) 5635 # get_html_prolog(FILENAME)
4726 # 5636 #
4727 # If FILENAME is defined, return contents of file. Otherwise return default 5637 # If FILENAME is defined, return contents of file. Otherwise return default
4728 # HTML prolog. Die on error. 5638 # HTML prolog. Die on error.
4729 # 5639 #
4730 5640
4731 sub get_html_prolog($) 5641 sub get_html_prolog($)
4732 { 5642 {
4733 my $filename = $_[0]; 5643 my $filename = $_[0];
4734 my $result = ""; 5644 my $result = "";
4735 5645
4736 if (defined($filename)) 5646 if (defined($filename))
4737 { 5647 {
4738 local *HANDLE; 5648 local *HANDLE;
4739 5649
4740 » » open(HANDLE, "<".$filename) 5650 » » open(HANDLE, "<", $filename)
4741 or die("ERROR: cannot open html prolog $filename!\n"); 5651 or die("ERROR: cannot open html prolog $filename!\n");
4742 while (<HANDLE>) 5652 while (<HANDLE>)
4743 { 5653 {
4744 $result .= $_; 5654 $result .= $_;
4745 } 5655 }
4746 close(HANDLE); 5656 close(HANDLE);
4747 } 5657 }
4748 else 5658 else
4749 { 5659 {
4750 $result = <<END_OF_HTML 5660 $result = <<END_OF_HTML
4751 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 5661 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4752 5662
4753 <html lang="en"> 5663 <html lang="en">
4754 5664
4755 <head> 5665 <head>
4756 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> 5666 <meta http-equiv="Content-Type" content="text/html; charset=$charset">
4757 <title>\@pagetitle\@</title> 5667 <title>\@pagetitle\@</title>
4758 <link rel="stylesheet" type="text/css" href="\@basedir\@gcov.css"> 5668 <link rel="stylesheet" type="text/css" href="\@basedir\@gcov.css">
4759 </head> 5669 </head>
4760 5670
4761 <body> 5671 <body>
4762 5672
4763 END_OF_HTML 5673 END_OF_HTML
4764 ; 5674 ;
4765 } 5675 }
4766 5676
4767 return $result; 5677 return $result;
4768 } 5678 }
4769 5679
4770 5680
4771 # 5681 #
4772 # get_html_epilog(FILENAME) 5682 # get_html_epilog(FILENAME)
4773 # 5683 #
4774 # If FILENAME is defined, return contents of file. Otherwise return default 5684 # If FILENAME is defined, return contents of file. Otherwise return default
4775 # HTML epilog. Die on error. 5685 # HTML epilog. Die on error.
4776 # 5686 #
4777 sub get_html_epilog($) 5687 sub get_html_epilog($)
4778 { 5688 {
4779 my $filename = $_[0]; 5689 my $filename = $_[0];
4780 my $result = ""; 5690 my $result = "";
4781 5691
4782 if (defined($filename)) 5692 if (defined($filename))
4783 { 5693 {
4784 local *HANDLE; 5694 local *HANDLE;
4785 5695
4786 » » open(HANDLE, "<".$filename) 5696 » » open(HANDLE, "<", $filename)
4787 or die("ERROR: cannot open html epilog $filename!\n"); 5697 or die("ERROR: cannot open html epilog $filename!\n");
4788 while (<HANDLE>) 5698 while (<HANDLE>)
4789 { 5699 {
4790 $result .= $_; 5700 $result .= $_;
4791 } 5701 }
4792 close(HANDLE); 5702 close(HANDLE);
4793 } 5703 }
4794 else 5704 else
4795 { 5705 {
4796 $result = <<END_OF_HTML 5706 $result = <<END_OF_HTML
(...skipping 14 matching lines...) Expand all
4811 5721
4812 warn("$tool_name: $msg"); 5722 warn("$tool_name: $msg");
4813 } 5723 }
4814 5724
4815 sub die_handler($) 5725 sub die_handler($)
4816 { 5726 {
4817 my ($msg) = @_; 5727 my ($msg) = @_;
4818 5728
4819 die("$tool_name: $msg"); 5729 die("$tool_name: $msg");
4820 } 5730 }
5731
5732 #
5733 # parse_ignore_errors(@ignore_errors)
5734 #
5735 # Parse user input about which errors to ignore.
5736 #
5737
5738 sub parse_ignore_errors(@)
5739 {
5740 my (@ignore_errors) = @_;
5741 my @items;
5742 my $item;
5743
5744 return if (!@ignore_errors);
5745
5746 foreach $item (@ignore_errors) {
5747 $item =~ s/\s//g;
5748 if ($item =~ /,/) {
5749 # Split and add comma-separated parameters
5750 push(@items, split(/,/, $item));
5751 } else {
5752 # Add single parameter
5753 push(@items, $item);
5754 }
5755 }
5756 foreach $item (@items) {
5757 my $item_id = $ERROR_ID{lc($item)};
5758
5759 if (!defined($item_id)) {
5760 die("ERROR: unknown argument for --ignore-errors: ".
5761 "$item\n");
5762 }
5763 $ignore[$item_id] = 1;
5764 }
5765 }
5766
5767 #
5768 # rate(hit, found[, suffix, precision, width])
5769 #
5770 # Return the coverage rate [0..100] for HIT and FOUND values. 0 is only
5771 # returned when HIT is 0. 100 is only returned when HIT equals FOUND.
5772 # PRECISION specifies the precision of the result. SUFFIX defines a
5773 # string that is appended to the result if FOUND is non-zero. Spaces
5774 # are added to the start of the resulting string until it is at least WIDTH
5775 # characters wide.
5776 #
5777
5778 sub rate($$;$$$)
5779 {
5780 my ($hit, $found, $suffix, $precision, $width) = @_;
5781 my $rate;
5782
5783 # Assign defaults if necessary
5784 $precision = 1 if (!defined($precision));
5785 $suffix = "" if (!defined($suffix));
5786 $width = 0 if (!defined($width));
5787
5788 return sprintf("%*s", $width, "-") if (!defined($found) || $found == 0);
5789 $rate = sprintf("%.*f", $precision, $hit * 100 / $found);
5790
5791 # Adjust rates if necessary
5792 if ($rate == 0 && $hit > 0) {
5793 $rate = sprintf("%.*f", $precision, 1 / 10 ** $precision);
5794 } elsif ($rate == 100 && $hit != $found) {
5795 $rate = sprintf("%.*f", $precision, 100 - 1 / 10 ** $precision);
5796 }
5797
5798 return sprintf("%*s", $width, $rate.$suffix);
5799 }
OLDNEW
« no previous file with comments | « third_party/lcov/bin/gendesc ('k') | third_party/lcov/bin/geninfo » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698