diff --git a/externals/lcov/CONTRIBUTING b/externals/lcov/CONTRIBUTING index 6890789bd140c4443e89b6d3412a362860ebffda..e8152d847ec21b51d1493f8345a69662d5aea3db 100644 --- a/externals/lcov/CONTRIBUTING +++ b/externals/lcov/CONTRIBUTING @@ -16,8 +16,8 @@ inclusion: 2. The contribution must follow a particular format. 3. The contribution must be signed. -Once you have made sure that your contribution follows these rules, send it via -e-mail to the LTP coverage mailing list [1]. +Once you have made sure that your contribution follows these rules, open a +pull request for the LCOV code repository [1]. Signing your work @@ -31,7 +31,7 @@ end of the explanation of a patch: By signing a patch, you certify the following: By making a contribution to the LTP GCOV extension (LCOV) on - http://ltp.sourceforge.net, I certify that: + https://github.com/linux-test-project/lcov, I certify that: a) The contribution was created by me and I have the right to submit it under the terms and conditions of the open source license @@ -56,8 +56,8 @@ collect, process and visualize code coverage data as produced by the gcov tool that is part of the GNU Compiler Collection (GCC) [2]. If you have an idea for a contribution but are unsure if it aligns with the -project goals, feel free to discuss the idea on the LTP coverage mailing -list [1]. +project goals, feel free to discuss the idea using the issue tracker on the +LCOV code repository site [1]. Contribution format @@ -89,5 +89,5 @@ With your Signed-off-by, you certify the rules stated in section -- -[1] ltp-coverage@lists.sourceforge.net -[2] http://gcc.gnu.org +[1] https://github.com/linux-test-project/lcov +[2] https://gcc.gnu.org diff --git a/externals/lcov/Makefile b/externals/lcov/Makefile index 1207cb19add633f0b5f99f2e7c0c4ce1b95bed95..62bf293bc211513b7694a5d12d66ddaea2feef41 100644 --- a/externals/lcov/Makefile +++ b/externals/lcov/Makefile @@ -9,6 +9,7 @@ # and RELEASE variables below - both version and date strings # will be updated in all necessary files. # - clean: remove all generated files +# - release: finalize release and create git tag for specified VERSION # VERSION := $(shell bin/get_version.sh --version) @@ -37,13 +38,14 @@ info: @echo " install : install binaries and man pages in DESTDIR (default /)" @echo " uninstall : delete binaries and man pages from DESTDIR (default /)" @echo " dist : create packages (RPM, tarball) ready for distribution" - @echo " test : perform self-tests" + @echo " check : perform self-tests" + @echo " release : finalize release and create git tag for specified VERSION" clean: rm -f lcov-*.tar.gz rm -f lcov-*.rpm make -C example clean - make -C test -s clean + make -C tests -s clean install: bin/install.sh bin/lcov $(DESTDIR)$(BIN_DIR)/lcov -m 755 @@ -95,7 +97,8 @@ lcov-$(VERSION).tar.gz: $(FILES) bin/updateversion.pl $(TMP_DIR)/lcov-$(VERSION) $(VERSION) $(RELEASE) $(FULL) bin/get_changes.sh > $(TMP_DIR)/lcov-$(VERSION)/CHANGES cd $(TMP_DIR) ; \ - tar cfz $(TMP_DIR)/lcov-$(VERSION).tar.gz lcov-$(VERSION) + tar cfz $(TMP_DIR)/lcov-$(VERSION).tar.gz lcov-$(VERSION) \ + --owner root --group root mv $(TMP_DIR)/lcov-$(VERSION).tar.gz . rm -rf $(TMP_DIR) @@ -112,11 +115,33 @@ rpms: lcov-$(VERSION).tar.gz cd $(TMP_DIR)/BUILD ; \ tar xfz $(TMP_DIR)/SOURCES/lcov-$(VERSION).tar.gz \ lcov-$(VERSION)/rpm/lcov.spec - rpmbuild --define '_topdir $(TMP_DIR)' \ + rpmbuild --define '_topdir $(TMP_DIR)' --define '_buildhost localhost' \ + --undefine vendor --undefine packager \ -ba $(TMP_DIR)/BUILD/lcov-$(VERSION)/rpm/lcov.spec mv $(TMP_DIR)/RPMS/noarch/lcov-$(VERSION)-$(RELEASE).noarch.rpm . mv $(TMP_DIR)/SRPMS/lcov-$(VERSION)-$(RELEASE).src.rpm . rm -rf $(TMP_DIR) -test: - @make -C test -s all +test: check + +check: + @make -s -C tests check + +release: + @if [ "$(origin VERSION)" != "command line" ] ; then echo "Please specify new version number, e.g. VERSION=1.16" >&2 ; exit 1 ; fi + @if [ -n "$$(git status --porcelain 2>&1)" ] ; then echo "The repository contains uncommited changes" >&2 ; exit 1 ; fi + @if [ -n "$$(git tag -l v$(VERSION))" ] ; then echo "A tag for the specified version already exists (v$(VERSION))" >&2 ; exit 1 ; fi + @echo "Preparing release tag for version $(VERSION)" + git checkout master + bin/copy_dates.sh . . + for FILE in README man/* rpm/* ; do \ + bin/updateversion.pl "$$FILE" $(VERSION) 1 $(VERSION) ; \ + done + git commit -a -s -m "lcov: Finalize release $(VERSION)" + git tag v$(VERSION) -m "LCOV version $(VERSION)" + @echo "**********************************************" + @echo "Release tag v$(VERSION) successfully created" + @echo "Next steps:" + @echo " - Review resulting commit and tag" + @echo " - Publish with: git push origin master v$(VERSION)" + @echo "**********************************************" diff --git a/externals/lcov/README b/externals/lcov/README index ad53c3cbcbf06c6cd326b2bac49cd973ebf6bb8b..e2e416c6882c3143b982e8209b129f4ce57dbd75 100644 --- a/externals/lcov/README +++ b/externals/lcov/README @@ -1,6 +1,6 @@ ------------------------------------------------- - README file for the LTP GCOV extension (LCOV) - -- Last changes: 2019-02-28 - +- Last changes: 2022-06-03 - ------------------------------------------------- Description @@ -53,7 +53,7 @@ Further README contents ------------------ The LCOV package is available as either RPM or tarball from: - http://ltp.sourceforge.net/coverage/lcov.php + https://github.com/linux-test-project/lcov/releases To install the tarball, unpack it to a directory and run: @@ -68,14 +68,13 @@ Change to the resulting lcov directory and type: make install -3. An example of how to access kernel coverage data ---------------------------------------------------- -Requirements: get and install the gcov-kernel package from +3. An example of how to access Linux kernel coverage data +--------------------------------------------------------- +Requirements: Follow the Linux kernel coverage setup instructions at: - http://sourceforge.net/projects/ltp + https://docs.kernel.org/dev-tools/gcov.html -Copy the resulting gcov kernel module file to either the system wide modules -directory or the same directory as the Perl scripts. As root, do the following: +As root, do the following: a) Resetting counters @@ -130,6 +129,7 @@ consult the gcov man page. ------------------------- See the included man pages for more information on how to use the LCOV tools. -Please email further questions or comments regarding this tool to the -LTP Mailing list at ltp-coverage@lists.sourceforge.net +In case of further questions, feel free to open a new issue using the issue +tracker on the LCOV code repository site at: + https://github.com/linux-test-project/lcov diff --git a/externals/lcov/bin/gendesc b/externals/lcov/bin/gendesc index 334ee7892372935d48dc349ce2fb3cc373af3080..9a4251b65ec1d43955788dd0f173a4fb995cb832 100755 --- a/externals/lcov/bin/gendesc +++ b/externals/lcov/bin/gendesc @@ -13,8 +13,8 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# along with this program; if not, see +# <http://www.gnu.org/licenses/>. # # # gendesc @@ -44,8 +44,8 @@ use Cwd qw/abs_path/; # Constants our $tool_dir = abs_path(dirname($0)); -our $lcov_version = "LCOV version 1.14"; -our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; +our $lcov_version = 'LCOV version '.`"$tool_dir"/get_version.sh --full`; +our $lcov_url = "https://github.com/linux-test-project/lcov"; our $tool_name = basename($0); diff --git a/externals/lcov/bin/genhtml b/externals/lcov/bin/genhtml index 2352300c11403acdc39f4b27582d68f6387ac685..d02c92c82228ccef9137bca73147e1e678eb5698 100755 --- a/externals/lcov/bin/genhtml +++ b/externals/lcov/bin/genhtml @@ -13,8 +13,8 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# along with this program; if not, see +# <http://www.gnu.org/licenses/>. # # # genhtml @@ -76,8 +76,8 @@ use Cwd qw/abs_path cwd/; # Global constants our $title = "LCOV - code coverage report"; our $tool_dir = abs_path(dirname($0)); -our $lcov_version = "LCOV version 1.14"; -our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; +our $lcov_version = 'LCOV version '.`"$tool_dir"/get_version.sh --full`; +our $lcov_url = "https://github.com/linux-test-project/lcov"; our $tool_name = basename($0); # Specify coverage rate default precision @@ -155,6 +155,9 @@ our $BR_CLOSE = 5; our $BR_SUB = 0; our $BR_ADD = 1; +# Block value used for unnamed blocks +our $UNNAMED_BLOCK = vec(pack('b*', 1 x 32), 0, 32); + # Error classes which users may specify to ignore during processing our $ERROR_SOURCE = 0; our %ERROR_ID = ( @@ -243,7 +246,7 @@ sub write_overview_line(*$$$); sub write_overview(*$$$$); # External prototype (defined in genpng) -sub gen_png($$$@); +sub gen_png($$$$@); # Global variables & initialization @@ -254,7 +257,9 @@ our %test_description; # Hash containing test descriptions if available our $date = get_date_string(); our @info_filenames; # List of .info files to use as data source -our $test_title; # Title for output as written to each page header +our $header_title; # Title at top of HTML report page (above table) +our $footer; # String at bottom of HTML report page +our $test_title; # Title shown in header table of each page our $output_directory; # Name of directory in which to store output our $base_filename; # Optional name of file containing baseline data our $desc_filename; # Name of file containing test descriptions @@ -284,11 +289,14 @@ our $html_epilog; # Actual HTML epilog our $html_ext = "html"; # Extension for generated HTML files our $html_gzip = 0; # Compress with gzip our $demangle_cpp = 0; # Demangle C++ function names +our $demangle_cpp_tool = "c++filt"; # Default demangler for C++ function names +our $demangle_cpp_params = ""; # Extra parameters for demangling our @opt_ignore_errors; # Ignore certain error classes during processing our @ignore; our $opt_config_file; # User-specified configuration file location our %opt_rc; our $opt_missed; # List/sort lines by missed counts +our $dark_mode; # Use dark mode palette or normal our $charset = "UTF-8"; # Default charset for HTML pages our @fileview_sortlist; our @fileview_sortname = ("", "-sort-l", "-sort-f", "-sort-b"); @@ -348,6 +356,8 @@ if ($config || %opt_rc) # Copy configuration file and --rc values to variables apply_config({ "genhtml_css_file" => \$css_filename, + "genhtml_header" => \$header_title, + "genhtml_footer" => \$footer, "genhtml_hi_limit" => \$hi_limit, "genhtml_med_limit" => \$med_limit, "genhtml_line_field_width" => \$line_field_width, @@ -376,6 +386,9 @@ if ($config || %opt_rc) "genhtml_charset" => \$charset, "genhtml_desc_html" => \$rc_desc_html, "genhtml_demangle_cpp" => \$demangle_cpp, + "genhtml_demangle_cpp_tool" => \$demangle_cpp_tool, + "genhtml_demangle_cpp_params" => \$demangle_cpp_params, + "genhtml_dark_mode" => \$dark_mode, "genhtml_missed" => \$opt_missed, "lcov_function_coverage" => \$lcov_func_coverage, "lcov_branch_coverage" => \$lcov_branch_coverage, @@ -392,6 +405,8 @@ $br_coverage = $lcov_branch_coverage if (!defined($br_coverage)); # Parse command line options if (!GetOptions("output-directory|o=s" => \$output_directory, + "header-title=s" => \$header_title, + "footer=s" => \$footer, "title|t=s" => \$test_title, "description-file|d=s" => \$desc_filename, "keep-descriptions|k" => \$keep_descriptions, @@ -424,6 +439,7 @@ if (!GetOptions("output-directory|o=s" => \$output_directory, "rc=s%" => \%opt_rc, "precision=i" => \$default_precision, "missed" => \$opt_missed, + "dark-mode" => \$dark_mode, )) { print(STDERR "Use $tool_name --help to get usage information\n"); @@ -441,6 +457,10 @@ if (!GetOptions("output-directory|o=s" => \$output_directory, if ($no_sort) { $sort = 0; } + + if (defined($header_title)) { + $title = $header_title; + } } @info_filenames = @ARGV; @@ -544,8 +564,8 @@ if ($frames) # Ensure that the c++filt tool is available when using --demangle-cpp if ($demangle_cpp) { - if (system_no_output(3, "c++filt", "--version")) { - die("ERROR: could not find c++filt tool needed for ". + if (system_no_output(3, $demangle_cpp_tool, "--version")) { + die("ERROR: could not find $demangle_cpp_tool tool needed for ". "--demangle-cpp\n"); } } @@ -612,8 +632,10 @@ Operation: HTML output: -f, --frames Use HTML frames for source code view - -t, --title TITLE Display TITLE in header of all pages + -t, --title TITLE Show TITLE in header table of each page -c, --css-file CSSFILE Use external style sheet file CSSFILE + --header-title BANNER Banner text at top of each HTML page + --footer FOOTER Footer text at bottom of each HTML page --no-source Do not create source code view --num-spaces NUM Replace tabs with NUM spaces in source view --highlight Highlight lines with converted-only data @@ -626,6 +648,7 @@ HTML output: --demangle-cpp Demangle C++ function names --precision NUM Set precision of coverage rate --missed Show miss counts as negative numbers + --dark-mode Use the dark-mode CSS For more information see: $lcov_url END_OF_USAGE @@ -1346,7 +1369,7 @@ sub process_file($$$) } # Create overview png file - gen_png("$rel_dir/$base_name.gcov.png", $overview_width, $tab_size, + gen_png("$rel_dir/$base_name.gcov.png", $dark_mode, $overview_width, $tab_size, @source); # Create frameset page @@ -1625,6 +1648,7 @@ sub read_info_file($) ($1, $2, $3, $4); last if (!$br_coverage); + $block = -1 if ($block == $UNNAMED_BLOCK); $sumbrcount->{$line} .= "$block,$branch,$taken:"; @@ -2725,70 +2749,131 @@ sub write_png_files() my %data; local *PNG_HANDLE; - $data{"ruby.png"} = - [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, - 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, - 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, - 0x45, 0x07, 0xd2, 0x07, 0x11, 0x0f, 0x18, 0x10, 0x5d, 0x57, - 0x34, 0x6e, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, - 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, - 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, - 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, - 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0xff, 0x35, 0x2f, - 0x00, 0x00, 0x00, 0xd0, 0x33, 0x9a, 0x9d, 0x00, 0x00, 0x00, - 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, - 0x82]; - $data{"amber.png"} = - [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, - 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, - 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, - 0x45, 0x07, 0xd2, 0x07, 0x11, 0x0f, 0x28, 0x04, 0x98, 0xcb, - 0xd6, 0xe0, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, - 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, - 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, - 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, - 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0xff, 0xe0, 0x50, - 0x00, 0x00, 0x00, 0xa2, 0x7a, 0xda, 0x7e, 0x00, 0x00, 0x00, - 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, - 0x82]; - $data{"emerald.png"} = - [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, - 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, - 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, - 0x45, 0x07, 0xd2, 0x07, 0x11, 0x0f, 0x22, 0x2b, 0xc9, 0xf5, - 0x03, 0x33, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, - 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, - 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, - 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, - 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0x1b, 0xea, 0x59, - 0x0a, 0x0a, 0x0a, 0x0f, 0xba, 0x50, 0x83, 0x00, 0x00, 0x00, - 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, - 0x82]; - $data{"snow.png"} = - [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, - 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, - 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, - 0x45, 0x07, 0xd2, 0x07, 0x11, 0x0f, 0x1e, 0x1d, 0x75, 0xbc, - 0xef, 0x55, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, - 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, - 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, - 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, - 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x55, 0xc2, 0xd3, 0x7e, 0x00, 0x00, 0x00, - 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, - 0x82]; + if ($dark_mode) { + $data{"ruby.png"} = + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, + 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, + 0x00, 0x00, 0x25, 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, + 0x06, 0x50, 0x4c, 0x54, 0x45, 0x80, 0x1b, 0x18, 0x00, + 0x00, 0x00, 0x39, 0x4a, 0x74, 0xf4, 0x00, 0x00, 0x00, + 0x0a, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x60, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe2, 0x21, 0xbc, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, + 0xae, 0x42, 0x60, 0x82]; + } else { + $data{"ruby.png"} = + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, + 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, + 0x00, 0x00, 0x25, 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, + 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd2, 0x07, 0x11, + 0x0f, 0x18, 0x10, 0x5d, 0x57, 0x34, 0x6e, 0x00, 0x00, + 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, + 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, + 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, + 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, + 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0xff, 0x35, + 0x2f, 0x00, 0x00, 0x00, 0xd0, 0x33, 0x9a, 0x9d, 0x00, + 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, + 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, + 0x27, 0xde, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, + 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82]; + } + if ($dark_mode) { + $data{"amber.png"} = + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, + 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, + 0x00, 0x00, 0x25, 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, + 0x06, 0x50, 0x4c, 0x54, 0x45, 0x99, 0x86, 0x30, 0x00, + 0x00, 0x00, 0x51, 0x83, 0x43, 0xd7, 0x00, 0x00, 0x00, + 0x0a, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x60, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe2, 0x21, 0xbc, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, + 0xae, 0x42, 0x60, 0x82]; + } else { + $data{"amber.png"} = + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, + 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, + 0x00, 0x00, 0x25, 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, + 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd2, 0x07, 0x11, + 0x0f, 0x28, 0x04, 0x98, 0xcb, 0xd6, 0xe0, 0x00, 0x00, + 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, + 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, + 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, + 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, + 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0xff, 0xe0, + 0x50, 0x00, 0x00, 0x00, 0xa2, 0x7a, 0xda, 0x7e, 0x00, + 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, + 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, + 0x27, 0xde, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, + 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82]; + } + if ($dark_mode) { + $data{"emerald.png"} = + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, + 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, + 0x00, 0x00, 0x25, 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, + 0x06, 0x50, 0x4c, 0x54, 0x45, 0x00, 0x66, 0x00, 0x0a, + 0x0a, 0x0a, 0xa4, 0xb8, 0xbf, 0x60, 0x00, 0x00, 0x00, + 0x0a, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x60, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe2, 0x21, 0xbc, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, + 0xae, 0x42, 0x60, 0x82]; + } else { + $data{"emerald.png"} = + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, + 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, + 0x00, 0x00, 0x25, 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, + 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd2, 0x07, 0x11, + 0x0f, 0x22, 0x2b, 0xc9, 0xf5, 0x03, 0x33, 0x00, 0x00, + 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, + 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, + 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, + 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, + 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0x1b, 0xea, + 0x59, 0x0a, 0x0a, 0x0a, 0x0f, 0xba, 0x50, 0x83, 0x00, + 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, + 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, + 0x27, 0xde, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, + 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82]; + } + if ($dark_mode) { + $data{"snow.png"} = + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, + 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, + 0x00, 0x00, 0x25, 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, + 0x06, 0x50, 0x4c, 0x54, 0x45, 0xdd, 0xdd, 0xdd, 0x00, + 0x00, 0x00, 0xae, 0x9c, 0x6c, 0x92, 0x00, 0x00, 0x00, + 0x0a, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x60, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe2, 0x21, 0xbc, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, + 0xae, 0x42, 0x60, 0x82]; + } else { + $data{"snow.png"} = + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, + 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, + 0x00, 0x00, 0x25, 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, + 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd2, 0x07, 0x11, + 0x0f, 0x1e, 0x1d, 0x75, 0xbc, 0xef, 0x55, 0x00, 0x00, + 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, + 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, + 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, + 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, + 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x55, 0xc2, 0xd3, 0x7e, 0x00, + 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, + 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, + 0x27, 0xde, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, + 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82]; + } + $data{"glass.png"} = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, @@ -2807,19 +2892,40 @@ sub write_png_files() 0x54, 0x78, 0x9c, 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x48, 0xaf, 0xa4, 0x71, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82]; - $data{"updown.png"} = - [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, - 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0a, - 0x00, 0x00, 0x00, 0x0e, 0x08, 0x06, 0x00, 0x00, 0x00, 0x16, - 0xa3, 0x8d, 0xab, 0x00, 0x00, 0x00, 0x3c, 0x49, 0x44, 0x41, - 0x54, 0x28, 0xcf, 0x63, 0x60, 0x40, 0x03, 0xff, 0xa1, 0x00, - 0x5d, 0x9c, 0x11, 0x5d, 0x11, 0x8a, 0x24, 0x23, 0x23, 0x23, - 0x86, 0x42, 0x6c, 0xa6, 0x20, 0x2b, 0x66, 0xc4, 0xa7, 0x08, - 0x59, 0x31, 0x23, 0x21, 0x45, 0x30, 0xc0, 0xc4, 0x30, 0x60, - 0x80, 0xfa, 0x6e, 0x24, 0x3e, 0x78, 0x48, 0x0a, 0x70, 0x62, - 0xa2, 0x90, 0x81, 0xd8, 0x44, 0x01, 0x00, 0xe9, 0x5c, 0x2f, - 0xf5, 0xe2, 0x9d, 0x0f, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82] if ($sort); + + if ($dark_mode) { + $data{"updown.png"} = + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, + 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, + 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x08, 0x06, 0x00, + 0x00, 0x00, 0x16, 0xa3, 0x8d, 0xab, 0x00, 0x00, 0x00, + 0x43, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, + 0x40, 0x03, 0x77, 0xef, 0xde, 0xfd, 0x7f, 0xf7, 0xee, + 0xdd, 0xff, 0xe8, 0xe2, 0x8c, 0xe8, 0x8a, 0x90, 0xf9, + 0xca, 0xca, 0xca, 0x8c, 0x18, 0x0a, 0xb1, 0x99, 0x82, + 0xac, 0x98, 0x11, 0x9f, 0x22, 0x64, 0xc5, 0x8c, 0x84, + 0x14, 0xc1, 0x00, 0x13, 0xc3, 0x80, 0x01, 0xea, 0xbb, + 0x91, 0xf8, 0xe0, 0x21, 0x29, 0xc0, 0x89, 0x89, 0x42, + 0x06, 0x62, 0x13, 0x05, 0x00, 0xe1, 0xd3, 0x2d, 0x91, + 0x93, 0x15, 0xa4, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82] if ($sort); + } else { + $data{"updown.png"} = + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, + 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, + 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x08, 0x06, 0x00, + 0x00, 0x00, 0x16, 0xa3, 0x8d, 0xab, 0x00, 0x00, 0x00, + 0x3c, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, + 0x40, 0x03, 0xff, 0xa1, 0x00, 0x5d, 0x9c, 0x11, 0x5d, + 0x11, 0x8a, 0x24, 0x23, 0x23, 0x23, 0x86, 0x42, 0x6c, + 0xa6, 0x20, 0x2b, 0x66, 0xc4, 0xa7, 0x08, 0x59, 0x31, + 0x23, 0x21, 0x45, 0x30, 0xc0, 0xc4, 0x30, 0x60, 0x80, + 0xfa, 0x6e, 0x24, 0x3e, 0x78, 0x48, 0x0a, 0x70, 0x62, + 0xa2, 0x90, 0x81, 0xd8, 0x44, 0x01, 0x00, 0xe9, 0x5c, + 0x2f, 0xf5, 0xe2, 0x9d, 0x0f, 0xf9, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82] + if ($sort); + } foreach (keys(%data)) { open(PNG_HANDLE, ">", $_) @@ -2883,28 +2989,28 @@ sub write_css_file() /* All views: initial background and text color */ body { - color: #000000; - background-color: #FFFFFF; + color: #COLOR_00; + background-color: #COLOR_14; } /* All views: standard link format*/ a:link { - color: #284FA8; + color: #COLOR_15; text-decoration: underline; } /* All views: standard link - visited format */ a:visited { - color: #00CB40; + color: #COLOR_01; text-decoration: underline; } /* All views: standard link - activated format */ a:active { - color: #FF0040; + color: #COLOR_11; text-decoration: underline; } @@ -2934,7 +3040,7 @@ sub write_css_file() td.headerValue { text-align: left; - color: #284FA8; + color: #COLOR_02; font-family: sans-serif; font-weight: bold; white-space: nowrap; @@ -2956,59 +3062,59 @@ sub write_css_file() td.headerCovTableEntry { text-align: right; - color: #284FA8; + color: #COLOR_02; font-family: sans-serif; font-weight: bold; white-space: nowrap; padding-left: 12px; padding-right: 4px; - background-color: #DAE7FE; + background-color: #COLOR_08; } /* All views: header item coverage table entry for high coverage rate */ td.headerCovTableEntryHi { text-align: right; - color: #000000; + color: #COLOR_00; font-family: sans-serif; font-weight: bold; white-space: nowrap; padding-left: 12px; padding-right: 4px; - background-color: #A7FC9D; + background-color: #COLOR_04; } /* All views: header item coverage table entry for medium coverage rate */ td.headerCovTableEntryMed { text-align: right; - color: #000000; + color: #COLOR_00; font-family: sans-serif; font-weight: bold; white-space: nowrap; padding-left: 12px; padding-right: 4px; - background-color: #FFEA20; + background-color: #COLOR_13; } /* All views: header item coverage table entry for ow coverage rate */ td.headerCovTableEntryLo { text-align: right; - color: #000000; + color: #COLOR_00; font-family: sans-serif; font-weight: bold; white-space: nowrap; padding-left: 12px; padding-right: 4px; - background-color: #FF0000; + background-color: #COLOR_10; } /* All views: header legend value for legend entry */ td.headerValueLeg { text-align: left; - color: #000000; + color: #COLOR_00; font-family: sans-serif; font-size: 80%; white-space: nowrap; @@ -3018,7 +3124,7 @@ sub write_css_file() /* All views: color of horizontal ruler */ td.ruler { - background-color: #6688D4; + background-color: #COLOR_03; } /* All views: version string format */ @@ -3035,8 +3141,8 @@ sub write_css_file() td.tableHead { text-align: center; - color: #FFFFFF; - background-color: #6688D4; + color: #COLOR_16; + background-color: #COLOR_03; font-family: sans-serif; font-size: 120%; font-weight: bold; @@ -3056,8 +3162,8 @@ sub write_css_file() text-align: left; padding-left: 10px; padding-right: 20px; - color: #284FA8; - background-color: #DAE7FE; + color: #COLOR_02; + background-color: #COLOR_08; font-family: monospace; } @@ -3066,13 +3172,13 @@ sub write_css_file() { padding-left: 10px; padding-right: 10px; - background-color: #DAE7FE; + background-color: #COLOR_08; } /* Directory view/File view (all): bar-graph outline color */ td.coverBarOutline { - background-color: #000000; + background-color: #COLOR_00; } /* Directory view/File view (all): percentage entry for files with @@ -3082,7 +3188,7 @@ sub write_css_file() text-align: right; padding-left: 10px; padding-right: 10px; - background-color: #A7FC9D; + background-color: #COLOR_04; font-weight: bold; font-family: sans-serif; } @@ -3094,7 +3200,7 @@ sub write_css_file() text-align: right; padding-left: 10px; padding-right: 10px; - background-color: #A7FC9D; + background-color: #COLOR_04; white-space: nowrap; font-family: sans-serif; } @@ -3106,7 +3212,7 @@ sub write_css_file() text-align: right; padding-left: 10px; padding-right: 10px; - background-color: #FFEA20; + background-color: #COLOR_13; font-weight: bold; font-family: sans-serif; } @@ -3118,7 +3224,7 @@ sub write_css_file() text-align: right; padding-left: 10px; padding-right: 10px; - background-color: #FFEA20; + background-color: #COLOR_13; white-space: nowrap; font-family: sans-serif; } @@ -3130,7 +3236,7 @@ sub write_css_file() text-align: right; padding-left: 10px; padding-right: 10px; - background-color: #FF0000; + background-color: #COLOR_10; font-weight: bold; font-family: sans-serif; } @@ -3142,7 +3248,7 @@ sub write_css_file() text-align: right; padding-left: 10px; padding-right: 10px; - background-color: #FF0000; + background-color: #COLOR_10; white-space: nowrap; font-family: sans-serif; } @@ -3164,7 +3270,7 @@ sub write_css_file() /* File view (all): "show/hide details" link - activated format */ a.detail:active { - color: #FFFFFF; + color: #COLOR_14; font-size:80%; } @@ -3173,7 +3279,7 @@ sub write_css_file() { text-align: right; padding-right: 10px; - background-color: #DAE7FE; + background-color: #COLOR_08; font-family: sans-serif; } @@ -3183,7 +3289,7 @@ sub write_css_file() text-align: right; padding-left: 10px; padding-right: 10px; - background-color: #DAE7FE; + background-color: #COLOR_08; font-family: sans-serif; } @@ -3193,7 +3299,7 @@ sub write_css_file() text-align: right; padding-left: 10px; padding-right: 10px; - background-color: #DAE7FE; + background-color: #COLOR_08; font-family: sans-serif; } @@ -3211,7 +3317,7 @@ sub write_css_file() padding-left: 30px; padding-bottom: 10px; padding-right: 30px; - background-color: #DAE7FE; + background-color: #COLOR_08; } /* Source code view: function entry */ @@ -3220,8 +3326,8 @@ sub write_css_file() text-align: left; padding-left: 10px; padding-right: 20px; - color: #284FA8; - background-color: #DAE7FE; + color: #COLOR_02; + background-color: #COLOR_08; font-family: monospace; } @@ -3231,7 +3337,7 @@ sub write_css_file() text-align: right; padding-left: 10px; padding-right: 10px; - background-color: #FF0000; + background-color: #COLOR_10; font-weight: bold; font-family: sans-serif; } @@ -3242,7 +3348,7 @@ sub write_css_file() text-align: right; padding-left: 10px; padding-right: 10px; - background-color: #DAE7FE; + background-color: #COLOR_08; font-weight: bold; font-family: sans-serif; } @@ -3258,14 +3364,14 @@ sub write_css_file() /* Source code view: line number format */ span.lineNum { - background-color: #EFE383; + background-color: #COLOR_09; } /* Source code view: format for lines which were executed */ td.lineCov, span.lineCov { - background-color: #CAD7FE; + background-color: #COLOR_07; } /* Source code view: format for Cov legend */ @@ -3274,14 +3380,14 @@ sub write_css_file() padding-left: 10px; padding-right: 10px; padding-bottom: 2px; - background-color: #CAD7FE; + background-color: #COLOR_07; } /* Source code view: format for lines which were not executed */ td.lineNoCov, span.lineNoCov { - background-color: #FF6230; + background-color: #COLOR_12; } /* Source code view: format for NoCov legend */ @@ -3290,14 +3396,14 @@ sub write_css_file() padding-left: 10px; padding-right: 10px; padding-bottom: 2px; - background-color: #FF6230; + background-color: #COLOR_12; } /* Source code view (function table): standard link - visited format */ td.lineNoCov > a:visited, td.lineCov > a:visited { - color: black; + color: #COLOR_00; text-decoration: underline; } @@ -3305,27 +3411,27 @@ sub write_css_file() previous version */ span.lineDiffCov { - background-color: #B5F7AF; + background-color: #COLOR_05; } /* Source code view: format for branches which were executed * and taken */ span.branchCov { - background-color: #CAD7FE; + background-color: #COLOR_07; } /* Source code view: format for branches which were executed * but not taken */ span.branchNoCov { - background-color: #FF6230; + background-color: #COLOR_12; } /* Source code view: format for branches which were not executed */ span.branchNoExec { - background-color: #FF6230; + background-color: #COLOR_12; } /* Source code view: format for the source code heading line */ @@ -3345,7 +3451,7 @@ sub write_css_file() white-space: nowrap; padding-left: 4px; padding-right: 2px; - background-color: #FF0000; + background-color: #COLOR_10; font-size: 80%; } @@ -3357,7 +3463,7 @@ sub write_css_file() white-space: nowrap; padding-left: 2px; padding-right: 2px; - background-color: #FFEA20; + background-color: #COLOR_13; font-size: 80%; } @@ -3369,7 +3475,7 @@ sub write_css_file() white-space: nowrap; padding-left: 2px; padding-right: 4px; - background-color: #A7FC9D; + background-color: #COLOR_04; font-size: 80%; } @@ -3379,7 +3485,7 @@ sub write_css_file() padding-left: 10px; padding-right: 10px; padding-top: 2px; - background-color: #FF0000; + background-color: #COLOR_10; } /* All views except source code view: legend format for med coverage */ @@ -3388,7 +3494,7 @@ sub write_css_file() padding-left: 10px; padding-right: 10px; padding-top: 2px; - background-color: #FFEA20; + background-color: #COLOR_13; } /* All views except source code view: legend format for hi coverage */ @@ -3397,7 +3503,7 @@ sub write_css_file() padding-left: 10px; padding-right: 10px; padding-top: 2px; - background-color: #A7FC9D; + background-color: #COLOR_04; } END_OF_CSS ; @@ -3407,6 +3513,48 @@ END_OF_CSS # Remove leading tab from all lines $css_data =~ s/^\t//gm; + my %palette = ( 'COLOR_00' => "000000", + 'COLOR_01' => "00cb40", + 'COLOR_02' => "284fa8", + 'COLOR_03' => "6688d4", + 'COLOR_04' => "a7fc9d", + 'COLOR_05' => "b5f7af", + 'COLOR_06' => "b8d0ff", + 'COLOR_07' => "cad7fe", + 'COLOR_08' => "dae7fe", + 'COLOR_09' => "efe383", + 'COLOR_10' => "ff0000", + 'COLOR_11' => "ff0040", + 'COLOR_12' => "ff6230", + 'COLOR_13' => "ffea20", + 'COLOR_14' => "ffffff", + 'COLOR_15' => "284fa8", + 'COLOR_16' => "ffffff"); + + if ($dark_mode) { + %palette = ( 'COLOR_00' => "e4e4e4", + 'COLOR_01' => "58a6ff", + 'COLOR_02' => "8b949e", + 'COLOR_03' => "3b4c71", + 'COLOR_04' => "006600", + 'COLOR_05' => "4b6648", + 'COLOR_06' => "495366", + 'COLOR_07' => "143e4f", + 'COLOR_08' => "1c1e23", + 'COLOR_09' => "202020", + 'COLOR_10' => "801b18", + 'COLOR_11' => "66001a", + 'COLOR_12' => "772d16", + 'COLOR_13' => "796a25", + 'COLOR_14' => "000000", + 'COLOR_15' => "58a6ff", + 'COLOR_16' => "eeeeee"); + } + + # Apply palette + for (keys %palette) { + $css_data =~ s/$_/$palette{$_}/gm; + } print(CSS_HANDLE $css_data); @@ -4271,13 +4419,14 @@ sub write_html_epilog(*$;$) { $break_code = " target=\"_parent\""; } + my $f = defined($main::footer) ? $footer : "Generated by: <a href=\"$lcov_url\"$break_code>$lcov_version</a>"; # ************************************************************* write_html($_[0], <<END_OF_HTML) <table width="100%" border=0 cellspacing=0 cellpadding=0> <tr><td class="ruler"><img src="$_[1]glass.png" width=3 height=3 alt=""></td></tr> - <tr><td class="versionInfo">Generated by: <a href="$lcov_url"$break_code>$lcov_version</a></td></tr> + <tr><td class="versionInfo">$f</td></tr> </table> <br> END_OF_HTML @@ -5242,7 +5391,7 @@ sub demangle_list($) my $tmpfile; my $handle; my %demangle; - my $demangle_arg = ""; + my $demangle_arg = $demangle_cpp_params; my %versions; # Write function names to file @@ -5253,12 +5402,12 @@ sub demangle_list($) # Extra flag necessary on OS X so that symbols listed by gcov get demangled # properly. - if ($^O eq "darwin") { - $demangle_arg = "--no-strip-underscores"; + if ($demangle_arg eq "" && $^O eq "darwin") { + $demangle_arg = "--no-strip-underscore"; } # Build translation hash from c++filt output - open($handle, "-|", "c++filt $demangle_arg < $tmpfile") or + open($handle, "-|", "$demangle_cpp_tool $demangle_arg < $tmpfile") or die("ERROR: could not run c++filt: $!\n"); foreach my $func (@$list) { my $translated = <$handle>; @@ -5656,6 +5805,10 @@ sub apply_prefix($@) { foreach my $prefix (@dir_prefix) { + if ($prefix eq $filename) + { + return "root"; + } if ($prefix ne "" && $filename =~ /^\Q$prefix\E\/(.*)$/) { return substr($filename, length($prefix) + 1); diff --git a/externals/lcov/bin/geninfo b/externals/lcov/bin/geninfo index f41eaec1cdfaadddecec3184eaeb4f7ff93c9890..31c0b574e7e0f961537c2c3df8d844526fc859f3 100755 --- a/externals/lcov/bin/geninfo +++ b/externals/lcov/bin/geninfo @@ -13,8 +13,8 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# along with this program; if not, see +# <http://www.gnu.org/licenses/>. # # # geninfo @@ -54,9 +54,15 @@ use warnings; use File::Basename; use File::Spec::Functions qw /abs2rel catdir file_name_is_absolute splitdir splitpath catpath/; +use File::Temp qw(tempfile tempdir); +use File::Copy qw(copy); use Getopt::Long; use Digest::MD5 qw(md5_base64); use Cwd qw/abs_path/; +use IO::Uncompress::Gunzip qw(gunzip $GunzipError); +use Module::Load; +use Module::Load::Conditional qw(check_install); + if( $^O eq "msys" ) { require File::Spec::Win32; @@ -64,8 +70,8 @@ if( $^O eq "msys" ) # Constants our $tool_dir = abs_path(dirname($0)); -our $lcov_version = "LCOV version 1.14"; -our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; +our $lcov_version = 'LCOV version '.`"$tool_dir"/get_version.sh --full`; +our $lcov_url = "https://github.com/linux-test-project/lcov"; our $gcov_tool = "gcov"; our $tool_name = basename($0); @@ -91,10 +97,14 @@ our %ERROR_ID = ( our $EXCL_START = "LCOV_EXCL_START"; our $EXCL_STOP = "LCOV_EXCL_STOP"; -# Marker to exclude branch coverage but keep function and line coveage +# Marker to exclude branch coverage but keep function and line coverage our $EXCL_BR_START = "LCOV_EXCL_BR_START"; our $EXCL_BR_STOP = "LCOV_EXCL_BR_STOP"; +# Marker to exclude exception branch coverage but keep function, line coverage and non-exception branch coverage +our $EXCL_EXCEPTION_BR_START = "LCOV_EXCL_EXCEPTION_BR_START"; +our $EXCL_EXCEPTION_BR_STOP = "LCOV_EXCL_EXCEPTION_BR_STOP"; + # Compatibility mode values our $COMPAT_VALUE_OFF = 0; our $COMPAT_VALUE_ON = 1; @@ -163,13 +173,13 @@ sub solve_relative_path($$); sub read_gcov_header($); sub read_gcov_file($); sub info(@); +sub process_intermediate($$$); sub map_llvm_version($); sub version_to_str($); sub get_gcov_version(); sub system_no_output($@); sub read_config($); sub apply_config($); -sub get_exclusion_data($); sub apply_exclusion_data($$); sub process_graphfile($$); sub filter_fn_name($); @@ -215,6 +225,7 @@ sub compat_name($); sub parse_compat_modes($); sub is_compat($); sub is_compat_auto($); +sub load_json_module($); # Global variables @@ -263,9 +274,14 @@ our %compat_value; our $gcno_split_crc; our $func_coverage = 1; our $br_coverage = 0; +our $no_exception_br = 0; our $rc_auto_base = 1; +our $rc_intermediate = "auto"; +our $rc_json_module = "auto"; +our $intermediate; our $excl_line = "LCOV_EXCL_LINE"; our $excl_br_line = "LCOV_EXCL_BR_LINE"; +our $excl_exception_br_line = "LCOV_EXCL_EXCEPTION_BR_LINE"; our $cwd = `pwd`; chomp($cwd); @@ -331,10 +347,14 @@ if ($config || %opt_rc) "geninfo_compat" => \$opt_compat, "geninfo_adjust_src_path" => \$rc_adjust_src_path, "geninfo_auto_base" => \$rc_auto_base, + "geninfo_intermediate" => \$rc_intermediate, + "lcov_json_module" => \$rc_json_module, + "geninfo_no_exception_branch" => \$no_exception_br, "lcov_function_coverage" => \$func_coverage, "lcov_branch_coverage" => \$br_coverage, "lcov_excl_line" => \$excl_line, "lcov_excl_br_line" => \$excl_br_line, + "lcov_excl_exception_br_line" => \$excl_exception_br_line, }); # Merge options @@ -364,7 +384,7 @@ if ($config || %opt_rc) $adjust_src_replace = $replace; } } - for my $regexp (($excl_line, $excl_br_line)) { + for my $regexp (($excl_line, $excl_br_line, $excl_exception_br_line)) { eval 'qr/'.$regexp.'/'; my $error = $@; chomp($error); @@ -460,15 +480,52 @@ if (system_no_output(3, $gcov_tool, "--help") == -1) } ($gcov_version, $gcov_version_string) = get_gcov_version(); +$gcov_caps = get_gcov_capabilities(); + +# Determine intermediate mode +if ($rc_intermediate eq "0") { + $intermediate = 0; +} elsif ($rc_intermediate eq "1") { + $intermediate = 1; +} elsif (lc($rc_intermediate) eq "auto") { + # Use intermediate format if supported by gcov and not conflicting with + # exception branch exclusion + $intermediate = (($gcov_caps->{'intermediate-format'} && !$no_exception_br) || + $gcov_caps->{'json-format'}) ? 1 : 0; +} else { + die("ERROR: invalid value for geninfo_intermediate: ". + "'$rc_intermediate'\n"); +} + +if ($intermediate) { + info("Using intermediate gcov format\n"); + if ($opt_derive_func_data) { + warn("WARNING: --derive-func-data is not compatible with ". + "intermediate format - ignoring\n"); + $opt_derive_func_data = 0; + } + if ($no_exception_br && !$gcov_caps->{'json-format'}) { + die("ERROR: excluding exception branches is not compatible with ". + "text intermediate format\n"); + } + if ($gcov_caps->{'json-format'}) { + load_json_module($rc_json_module); + } +} + +if ($no_exception_br && ($gcov_version < $GCOV_VERSION_3_3_0)) { + die("ERROR: excluding exception branches is not compatible with ". + "gcov versions older than 3.3\n"); +} # Determine gcov options -$gcov_caps = get_gcov_capabilities(); push(@gcov_options, "-b") if ($gcov_caps->{'branch-probabilities'} && ($br_coverage || $func_coverage)); push(@gcov_options, "-c") if ($gcov_caps->{'branch-counts'} && $br_coverage); push(@gcov_options, "-a") if ($gcov_caps->{'all-blocks'} && - $opt_gcov_all_blocks && $br_coverage); + $opt_gcov_all_blocks && $br_coverage && + !$intermediate); if ($gcov_caps->{'hash-filenames'}) { push(@gcov_options, "-x"); @@ -599,7 +656,7 @@ foreach my $entry (@data_directory) { gen_info($entry); } -if ($initial && $br_coverage) { +if ($initial && $br_coverage && !$intermediate) { warn("Note: --initial does not generate branch coverage ". "data\n"); } @@ -768,6 +825,7 @@ sub gen_info($) my $prefix; my $type; my $ext; + my $tempdir; if ($initial) { $type = "graph"; @@ -798,16 +856,22 @@ sub gen_info($) $prefix = ""; } + $tempdir = tempdir(CLEANUP => 1); + # Process all files in list foreach $file (@file_list) { # Process file - if ($initial) { + if ($intermediate) { + process_intermediate($file, $prefix, $tempdir); + } elsif ($initial) { process_graphfile($file, $prefix); } else { process_dafile($file, $prefix); } } + unlink($tempdir); + # Report whether files were excluded. if (%excluded_files) { info("Excluded data for %d files due to include/exclude options\n", @@ -1058,10 +1122,12 @@ sub process_dafile($$) # Try to find base directory automatically if requested by user if ($rc_auto_base) { - $base_dir = find_base_from_graph($base_dir, $instr, $graph); + $base_dir = find_base_from_source($base_dir, + [ keys(%{$instr}), keys(%{$graph}) ]); } - ($instr, $graph) = adjust_graph_filenames($base_dir, $instr, $graph); + adjust_source_filenames($instr, $base_dir); + adjust_source_filenames($graph, $base_dir); # Set $object_dir to real location of object files. This may differ # from $da_dir if the graph file is just a link to the "real" object @@ -1802,7 +1868,9 @@ sub read_gcov_file($) my $exclude_flag = 0; my $exclude_line = 0; my $exclude_br_flag = 0; + my $exclude_exception_br_flag = 0; my $exclude_branch = 0; + my $exclude_exception_branch = 0; my $last_block = $UNNAMED_BLOCK; my $last_line = 0; local *INPUT; @@ -1872,6 +1940,13 @@ sub read_gcov_file($) $exclude_branch = 0; } } + # Check for exclusion markers (exception branch exclude) + if (!$no_markers && + /($EXCL_EXCEPTION_BR_STOP|$EXCL_EXCEPTION_BR_START|$excl_exception_br_line)/) { + warn("WARNING: $1 found at $filename:$last_line but ". + "branch exceptions exclusion is not supported with ". + "gcov versions older than 3.3\n"); + } # Source code execution data if (/^\t\t(.*)$/) { @@ -1914,10 +1989,12 @@ sub read_gcov_file($) # branches $last_line = $2; $last_block = $3; - } elsif (/^branch\s+(\d+)\s+taken\s+(\d+)/) { + } elsif (/^branch\s+(\d+)\s+taken\s+(\d+)(?:\s+\(([^)]*)\))?/) { next if (!$br_coverage); next if ($exclude_line); next if ($exclude_branch); + next if (($exclude_exception_branch || $no_exception_br) && + defined($3) && ($3 eq "throw")); $branches = br_gvec_push($branches, $last_line, $last_block, $1, $2); } elsif (/^branch\s+(\d+)\s+never\s+executed/) { @@ -1974,6 +2051,19 @@ sub read_gcov_file($) $exclude_branch = 0; } } + # Check for exclusion markers (exception branch exclude) + if (!$no_markers) { + if (/$EXCL_EXCEPTION_BR_STOP/) { + $exclude_exception_br_flag = 0; + } elsif (/$EXCL_EXCEPTION_BR_START/) { + $exclude_exception_br_flag = 1; + } + if (/$excl_exception_br_line/ || $exclude_exception_br_flag) { + $exclude_exception_branch = 1; + } else { + $exclude_exception_branch = 0; + } + } # Strip unexecuted basic block marker $count =~ s/\*$//; @@ -2010,13 +2100,529 @@ sub read_gcov_file($) } close(INPUT); - if ($exclude_flag || $exclude_br_flag) { + if ($exclude_flag || $exclude_br_flag || $exclude_exception_br_flag) { warn("WARNING: unterminated exclusion section in $filename\n"); } return(\@result, $branches, \@functions); } +# +# read_intermediate_text(gcov_filename, data) +# +# Read gcov intermediate text format in GCOV_FILENAME and add the resulting +# data to DATA in the following format: +# +# data: source_filename -> file_data +# file_data: concatenated lines of intermediate text data +# + +sub read_intermediate_text($$) +{ + my ($gcov_filename, $data) = @_; + my $fd; + my $filename; + + open($fd, "<", $gcov_filename) or + die("ERROR: Could not read $gcov_filename: $!\n"); + while (my $line = <$fd>) { + if ($line =~ /^file:(.*)$/) { + $filename = $1; + $filename =~ s/[\r\n]$//g; + } elsif (defined($filename)) { + $data->{$filename} .= $line; + } + } + close($fd); +} + + +# +# read_intermediate_json(gcov_filename, data, basedir_ref) +# +# Read gcov intermediate JSON format in GCOV_FILENAME and add the resulting +# data to DATA in the following format: +# +# data: source_filename -> file_data +# file_data: GCOV JSON data for file +# +# Also store the value for current_working_directory to BASEDIR_REF. +# + +sub read_intermediate_json($$$) +{ + my ($gcov_filename, $data, $basedir_ref) = @_; + my $text; + my $json; + + gunzip($gcov_filename, \$text) or + die("ERROR: Could not read $gcov_filename: $GunzipError\n"); + + $json = decode_json($text); + if (!defined($json) || !exists($json->{"files"}) || + ref($json->{"files"} ne "ARRAY")) { + die("ERROR: Unrecognized JSON output format in ". + "$gcov_filename\n"); + } + + $$basedir_ref = $json->{"current_working_directory"}; + + # Workaround for bug in MSYS GCC 9.x that encodes \ as \n in gcov JSON + # output + if ($^O eq "msys" && $$basedir_ref =~ /\n/) { + $$basedir_ref =~ s#\n#/#g; + } + + for my $file (@{$json->{"files"}}) { + # decode_json() is decoding UTF-8 strings from the JSON file into + # Perl's internal encoding, but filenames on the filesystem are + # usually UTF-8 encoded, so the filename strings need to be + # converted back to UTF-8 so that they actually match the name + # on the filesystem. + utf8::encode($file->{"file"}); + + my $filename = $file->{"file"}; + + $data->{$filename} = $file; + } +} + + +# +# intermediate_text_to_info(fd, data, srcdata) +# +# Write DATA in info format to file descriptor FD. +# +# data: filename -> file_data: +# file_data: concatenated lines of intermediate text data +# +# srcdata: filename -> [ excl, brexcl, checksums ] +# excl: lineno -> 1 for all lines for which to exclude all data +# brexcl: lineno -> 1 for all lines for which to exclude branch data +# 2 for all lines for which to exclude exception branch data +# checksums: lineno -> source code checksum +# +# Note: To simplify processing, gcov data is not combined here, that is counts +# that appear multiple times for the same lines/branches are not added. +# This is done by lcov/genhtml when reading the data files. +# + +sub intermediate_text_to_info($$$) +{ + my ($fd, $data, $srcdata) = @_; + my $branch_num = 0; + my $c; + + return if (!%{$data}); + + print($fd "TN:$test_name\n"); + for my $filename (keys(%{$data})) { + my ($excl, $brexcl, $checksums); + my $lines_found = 0; + my $lines_hit = 0; + my $functions_found = 0; + my $functions_hit = 0; + my $branches_found = 0; + my $branches_hit = 0; + + if (defined($srcdata->{$filename})) { + ($excl, $brexcl, $checksums) = @{$srcdata->{$filename}}; + } + + print($fd "SF:$filename\n"); + for my $line (split(/\n/, $data->{$filename})) { + if ($line =~ /^lcount:(\d+),(\d+),?/) { + # lcount:<line>,<count> + # lcount:<line>,<count>,<has_unexecuted_blocks> + if ($checksum && exists($checksums->{$1})) { + $c = ",".$checksums->{$1}; + } else { + $c = ""; + } + print($fd "DA:$1,$2$c\n") if (!$excl->{$1}); + + # Intermediate text format does not provide + # branch numbers, and the same branch may appear + # multiple times on the same line (e.g. in + # template instances). Synthesize a branch + # number based on the assumptions: + # a) the order of branches is fixed across + # instances + # b) an instance starts with an lcount line + $branch_num = 0; + + $lines_found++; + $lines_hit++ if ($2 > 0); + } elsif ($line =~ /^function:(\d+),(\d+),([^,]+)$/) { + next if (!$func_coverage || $excl->{$1}); + + # function:<line>,<count>,<name> + print($fd "FN:$1,$3\n"); + print($fd "FNDA:$2,$3\n"); + + $functions_found++; + $functions_hit++ if ($2 > 0); + } elsif ($line =~ /^function:(\d+),\d+,(\d+),([^,]+)$/) { + next if (!$func_coverage || $excl->{$1}); + + # function:<start_line>,<end_line>,<count>, + # <name> + print($fd "FN:$1,$3\n"); + print($fd "FNDA:$2,$3\n"); + + $functions_found++; + $functions_hit++ if ($2 > 0); + } elsif ($line =~ /^branch:(\d+),(taken|nottaken|notexec)/) { + next if (!$br_coverage || $excl->{$1} || + (defined($brexcl->{$1}) && ($brexcl->{$1} == 1))); + + # branch:<line>,taken|nottaken|notexec + if ($2 eq "taken") { + $c = 1; + } elsif ($2 eq "nottaken") { + $c = 0; + } else { + $c = "-"; + } + print($fd "BRDA:$1,0,$branch_num,$c\n"); + $branch_num++; + + $branches_found++; + $branches_hit++ if ($2 eq "taken"); + } + } + + if ($functions_found > 0) { + printf($fd "FNF:%s\n", $functions_found); + printf($fd "FNH:%s\n", $functions_hit); + } + if ($branches_found > 0) { + printf($fd "BRF:%s\n", $branches_found); + printf($fd "BRH:%s\n", $branches_hit); + } + printf($fd "LF:%s\n", $lines_found); + printf($fd "LH:%s\n", $lines_hit); + print($fd "end_of_record\n"); + } +} + + +# +# intermediate_json_to_info(fd, data, srcdata) +# +# Write DATA in info format to file descriptor FD. +# +# data: filename -> file_data: +# file_data: GCOV JSON data for file +# +# srcdata: filename -> [ excl, brexcl, checksums ] +# excl: lineno -> 1 for all lines for which to exclude all data +# brexcl: lineno -> 1 for all lines for which to exclude branch data +# 2 for all lines for which to exclude exception branch data +# checksums: lineno -> source code checksum +# +# Note: To simplify processing, gcov data is not combined here, that is counts +# that appear multiple times for the same lines/branches are not added. +# This is done by lcov/genhtml when reading the data files. +# + +sub intermediate_json_to_info($$$) +{ + my ($fd, $data, $srcdata) = @_; + my $branch_num = 0; + + return if (!%{$data}); + + print($fd "TN:$test_name\n"); + for my $filename (keys(%{$data})) { + my ($excl, $brexcl, $checksums); + my $file_data = $data->{$filename}; + my $lines_found = 0; + my $lines_hit = 0; + my $functions_found = 0; + my $functions_hit = 0; + my $branches_found = 0; + my $branches_hit = 0; + + if (defined($srcdata->{$filename})) { + ($excl, $brexcl, $checksums) = @{$srcdata->{$filename}}; + } + + print($fd "SF:$filename\n"); + + # Function data + if ($func_coverage) { + for my $d (@{$file_data->{"functions"}}) { + my $line = $d->{"start_line"}; + my $count = $d->{"execution_count"}; + my $name = $d->{"name"}; + + next if (!defined($line) || !defined($count) || + !defined($name) || $excl->{$line}); + + print($fd "FN:$line,$name\n"); + print($fd "FNDA:$count,$name\n"); + + $functions_found++; + $functions_hit++ if ($count > 0); + } + } + + if ($functions_found > 0) { + printf($fd "FNF:%s\n", $functions_found); + printf($fd "FNH:%s\n", $functions_hit); + } + + # Line data + for my $d (@{$file_data->{"lines"}}) { + my $line = $d->{"line_number"}; + my $count = $d->{"count"}; + my $c; + my $branches = $d->{"branches"}; + my $unexec = $d->{"unexecuted_block"}; + + next if (!defined($line) || !defined($count) || + $excl->{$line}); + + if (defined($unexec) && $unexec && $count == 0) { + $unexec = 1; + } else { + $unexec = 0; + } + + if ($checksum && exists($checksums->{$line})) { + $c = ",".$checksums->{$line}; + } else { + $c = ""; + } + print($fd "DA:$line,$count$c\n"); + + $lines_found++; + $lines_hit++ if ($count > 0); + + $branch_num = 0; + # Branch data + if ($br_coverage && (!defined($brexcl->{$line}) || + ($brexcl->{$line} != 1))) { + for my $b (@$branches) { + my $brcount = $b->{"count"}; + my $is_exception = $b->{"throw"}; + + if (!$is_exception || ((!defined($brexcl->{$line}) || + ($brexcl->{$line} != 2)) && !$no_exception_br)) { + if (!defined($brcount) || $unexec) { + $brcount = "-"; + } + print($fd "BRDA:$line,0,$branch_num,". + "$brcount\n"); + } + + $branches_found++; + $branches_hit++ if ($brcount ne "-" && $brcount > 0); + $branch_num++; + } + } + } + + if ($branches_found > 0) { + printf($fd "BRF:%s\n", $branches_found); + printf($fd "BRH:%s\n", $branches_hit); + } + printf($fd "LF:%s\n", $lines_found); + printf($fd "LH:%s\n", $lines_hit); + print($fd "end_of_record\n"); + } +} + + +sub get_output_fd($$) +{ + my ($outfile, $file) = @_; + my $fd; + + if (!defined($outfile)) { + open($fd, ">", "$file.info") or + die("ERROR: Cannot create file $file.info: $!\n"); + } elsif ($outfile eq "-") { + open($fd, ">&STDOUT") or + die("ERROR: Cannot duplicate stdout: $!\n"); + } else { + open($fd, ">>", $outfile) or + die("ERROR: Cannot write to file $outfile: $!\n"); + } + + return $fd; +} + + +# +# print_gcov_warnings(stderr_file, is_graph, map) +# +# Print GCOV warnings in file STDERR_FILE to STDERR. If IS_GRAPH is non-zero, +# suppress warnings about missing as these are expected. Replace keys found +# in MAP with their values. +# + +sub print_gcov_warnings($$$) +{ + my ($stderr_file, $is_graph, $map) = @_; + my $fd; + + if (!open($fd, "<", $stderr_file)) { + warn("WARNING: Could not open GCOV stderr file ". + "$stderr_file: $!\n"); + return; + } + while (my $line = <$fd>) { + next if ($is_graph && $line =~ /cannot open data file/); + + for my $key (keys(%{$map})) { + $line =~ s/\Q$key\E/$map->{$key}/g; + } + + print(STDERR $line); + } + close($fd); +} + + +# +# process_intermediate(file, dir, tempdir) +# +# Create output for a single file (either a data file or a graph file) using +# gcov's intermediate option. +# + +sub process_intermediate($$$) +{ + my ($file, $dir, $tempdir) = @_; + my ($fdir, $fbase, $fext); + my $data_file; + my $errmsg; + my %data; + my $fd; + my $base; + my $srcdata; + my $is_graph = 0; + my ($out, $err, $rc); + my $json_basedir; + my $json_format; + + info("Processing %s\n", abs2rel($file, $dir)); + + $file = solve_relative_path($cwd, $file); + ($fdir, $fbase, $fext) = split_filename($file); + + $is_graph = 1 if (".$fext" eq $graph_file_extension); + + if ($is_graph) { + # Process graph file - copy to temp directory to prevent + # accidental processing of associated data file + $data_file = "$tempdir/$fbase$graph_file_extension"; + if (!copy($file, $data_file)) { + $errmsg = "ERROR: Could not copy file $file"; + goto err; + } + } else { + # Process data file in place + $data_file = $file; + } + + # Change directory + if (!chdir($tempdir)) { + $errmsg = "Could not change to directory $tempdir: $!"; + goto err; + } + + # Run gcov on data file + ($out, $err, $rc) = system_no_output(1 + 2 + 4, $gcov_tool, + $data_file, @gcov_options, "-i"); + defined($out) && unlink($out); + if (defined($err)) { + print_gcov_warnings($err, $is_graph, { + $data_file => $file, + }); + unlink($err); + } + if ($rc) { + $errmsg = "GCOV failed for $file"; + goto err; + } + + if ($is_graph) { + # Remove graph file copy + unlink($data_file); + } + + # Parse resulting file(s) + for my $gcov_filename (glob("*.gcov")) { + read_intermediate_text($gcov_filename, \%data); + unlink($gcov_filename); + } + + for my $gcov_filename (glob("*.gcov.json.gz")) { + read_intermediate_json($gcov_filename, \%data, \$json_basedir); + unlink($gcov_filename); + $json_format = 1; + } + + if (!%data) { + warn("WARNING: GCOV did not produce any data for $file\n"); + return; + } + + # Determine base directory + if (defined($base_directory)) { + $base = $base_directory; + } elsif (defined($json_basedir)) { + $base = $json_basedir; + } else { + $base = $fdir; + + if (is_compat($COMPAT_MODE_LIBTOOL)) { + # Avoid files from .libs dirs + $base =~ s/\.libs$//; + } + + # Try to find base directory automatically if requested by user + if ($rc_auto_base) { + $base = find_base_from_source($base, [ keys(%data) ]); + } + } + + # Apply base file name to relative source files + adjust_source_filenames(\%data, $base); + + # Remove excluded source files + filter_source_files(\%data); + + # Get data on exclusion markers and checksums if requested + if (!$no_markers || $checksum) { + $srcdata = get_all_source_data(keys(%data)); + } + + # Generate output + $fd = get_output_fd($output_filename, $file); + if ($json_format) { + intermediate_json_to_info($fd, \%data, $srcdata); + } else { + intermediate_text_to_info($fd, \%data, $srcdata); + } + close($fd); + + chdir($cwd); + + return; + +err: + if ($ignore[$ERROR_GCOV]) { + warn("WARNING: $errmsg!\n"); + } else { + die("ERROR: $errmsg!\n") + } +} + + # Map LLVM versions to the version of GCC gcov which they emulate. sub map_llvm_version($) @@ -2074,7 +2680,7 @@ sub get_gcov_version() # Default target: x86_64-apple-darwin16.0.0 # Host CPU: haswell - open(GCOV_PIPE, "-|", "$gcov_tool --version") + open(GCOV_PIPE, "-|", "\"$gcov_tool\" --version") or die("ERROR: cannot retrieve gcov version!\n"); local $/; $version_string = <GCOV_PIPE>; @@ -2151,8 +2757,12 @@ sub int_handler() # # MODE & 1: suppress STDOUT # MODE & 2: suppress STDERR +# MODE & 4: redirect to temporary files instead of suppressing # -# Return 0 on success, non-zero otherwise. +# Return (stdout, stderr, rc): +# stdout: path to tempfile containing stdout or undef +# stderr: path to tempfile containing stderr or undef +# 0 on success, non-zero otherwise # sub system_no_output($@) @@ -2161,14 +2771,31 @@ sub system_no_output($@) my $result; local *OLD_STDERR; local *OLD_STDOUT; + my $stdout_file; + my $stderr_file; + my $fd; # Save old stdout and stderr handles ($mode & 1) && open(OLD_STDOUT, ">>&", "STDOUT"); ($mode & 2) && open(OLD_STDERR, ">>&", "STDERR"); - # Redirect to /dev/null - ($mode & 1) && open(STDOUT, ">", "/dev/null"); - ($mode & 2) && open(STDERR, ">", "/dev/null"); + if ($mode & 4) { + # Redirect to temporary files + if ($mode & 1) { + ($fd, $stdout_file) = tempfile(UNLINK => 1); + open(STDOUT, ">", $stdout_file) || warn("$!\n"); + close($fd); + } + if ($mode & 2) { + ($fd, $stderr_file) = tempfile(UNLINK => 1); + open(STDERR, ">", $stderr_file) || warn("$!\n"); + close($fd); + } + } else { + # Redirect to /dev/null + ($mode & 1) && open(STDOUT, ">", "/dev/null"); + ($mode & 2) && open(STDERR, ">", "/dev/null"); + } debug("system(".join(' ', @_).")\n"); system(@_); @@ -2181,8 +2808,18 @@ sub system_no_output($@) # Restore old handles ($mode & 1) && open(STDOUT, ">>&", "OLD_STDOUT"); ($mode & 2) && open(STDERR, ">>&", "OLD_STDERR"); + + # Remove empty output files + if (defined($stdout_file) && -z $stdout_file) { + unlink($stdout_file); + $stdout_file = undef; + } + if (defined($stderr_file) && -z $stderr_file) { + unlink($stderr_file); + $stderr_file = undef; + } - return $result; + return ($stdout_file, $stderr_file, $result); } @@ -2260,23 +2897,29 @@ sub apply_config($) # -# get_exclusion_data(filename) +# get_source_data(filename) # -# Scan specified source code file for exclusion markers and return -# linenumber -> 1 -# for all lines which should be excluded. +# Scan specified source code file for exclusion markers and checksums. Return +# ( excl, brexcl, checksums ) where +# excl: lineno -> 1 for all lines for which to exclude all data +# brexcl: lineno -> 1 for all lines for which to exclude branch data +# checksums: lineno -> source code checksum # -sub get_exclusion_data($) +sub get_source_data($) { my ($filename) = @_; my %list; my $flag = 0; + my %brdata; + my $brflag = 0; + my $exceptionbrflag = 0; + my %checksums; local *HANDLE; if (!open(HANDLE, "<", $filename)) { warn("WARNING: could not open $filename\n"); - return undef; + return; } while (<HANDLE>) { if (/$EXCL_STOP/) { @@ -2287,14 +2930,75 @@ sub get_exclusion_data($) if (/$excl_line/ || $flag) { $list{$.} = 1; } + if (/$EXCL_BR_STOP/) { + $brflag = 0; + } elsif (/$EXCL_BR_START/) { + $brflag = 1; + } + if (/$EXCL_EXCEPTION_BR_STOP/) { + $exceptionbrflag = 0; + } elsif (/$EXCL_EXCEPTION_BR_START/) { + $exceptionbrflag = 1; + } + if (/$excl_br_line/ || $brflag) { + $brdata{$.} = 1; + } elsif (/$excl_exception_br_line/ || $exceptionbrflag) { + $brdata{$.} = 2; + } + if ($checksum) { + chomp(); + $checksums{$.} = md5_base64($_); + } + if ($intermediate && !$gcov_caps->{'json-format'} && + /($EXCL_EXCEPTION_BR_STOP|$EXCL_EXCEPTION_BR_START|$excl_exception_br_line)/) { + warn("WARNING: $1 found at $filename:$. but branch exceptions ". + "exclusion is not supported when using text intermediate ". + "format\n"); + } } close(HANDLE); - if ($flag) { + if ($flag || $brflag || $exceptionbrflag) { warn("WARNING: unterminated exclusion section in $filename\n"); } - return \%list; + return (\%list, \%brdata, \%checksums); +} + + +# +# get_all_source_data(filenames) +# +# Scan specified source code files for exclusion markers and return +# filename -> [ excl, brexcl, checksums ] +# excl: lineno -> 1 for all lines for which to exclude all data +# brexcl: lineno -> 1 for all lines for which to exclude branch data +# checksums: lineno -> source code checksum +# + +sub get_all_source_data(@) +{ + my @filenames = @_; + my %data; + my $failed = 0; + + for my $filename (@filenames) { + my @d; + next if (exists($data{$filename})); + + @d = get_source_data($filename); + if (@d) { + $data{$filename} = [ @d ]; + } else { + $failed = 1; + } + } + + if ($failed) { + warn("WARNING: some exclusion markers may be ignored\n"); + } + + return \%data; } @@ -2318,35 +3022,17 @@ sub apply_exclusion_data($$) { my ($instr, $graph) = @_; my $filename; - my %excl_data; - my $excl_read_failed = 0; - - # Collect exclusion marker data - foreach $filename (sort_uniq_lex(keys(%{$graph}), keys(%{$instr}))) { - my $excl = get_exclusion_data($filename); - - # Skip and note if file could not be read - if (!defined($excl)) { - $excl_read_failed = 1; - next; - } - - # Add to collection if there are markers - $excl_data{$filename} = $excl if (keys(%{$excl}) > 0); - } + my $excl_data; - # Warn if not all source files could be read - if ($excl_read_failed) { - warn("WARNING: some exclusion markers may be ignored\n"); - } + ($excl_data) = get_all_source_data(keys(%{$graph}), keys(%{$instr})); # Skip if no markers were found - return ($instr, $graph) if (keys(%excl_data) == 0); + return ($instr, $graph) if (!%$excl_data); # Apply exclusion marker data to graph - foreach $filename (keys(%excl_data)) { + foreach $filename (keys(%$excl_data)) { my $function_data = $graph->{$filename}; - my $excl = $excl_data{$filename}; + my $excl = $excl_data->{$filename}->[0]; my $function; next if (!defined($function_data)); @@ -2384,9 +3070,9 @@ sub apply_exclusion_data($$) } # Apply exclusion marker data to instr - foreach $filename (keys(%excl_data)) { + foreach $filename (keys(%$excl_data)) { my $line_data = $instr->{$filename}; - my $excl = $excl_data{$filename}; + my $excl = $excl_data->{$filename}->[0]; my $line; my @new_data; @@ -2468,10 +3154,12 @@ sub process_graphfile($$) # Try to find base directory automatically if requested by user if ($rc_auto_base) { - $base_dir = find_base_from_graph($base_dir, $instr, $graph); + $base_dir = find_base_from_source($base_dir, + [ keys(%{$instr}), keys(%{$graph}) ]); } - ($instr, $graph) = adjust_graph_filenames($base_dir, $instr, $graph); + adjust_source_filenames($instr, $base_dir); + adjust_source_filenames($graph, $base_dir); if (!$no_markers) { # Apply exclusion marker data to graph file data @@ -2767,11 +3455,11 @@ sub parent_dir($) } # -# find_base_from_graph(base_dir, instr, graph) +# find_base_from_source(base_dir, source_files) # -# Try to determine the base directory of the graph file specified by INSTR -# and GRAPH. The base directory is the base for all relative filenames in -# the graph file. It is defined by the current working directory at time +# Try to determine the base directory of the object file built from +# SOURCE_FILES. The base directory is the base for all relative filenames in +# the gcov data. It is defined by the current working directory at time # of compiling the source file. # # This function implements a heuristic which relies on the following @@ -2781,16 +3469,16 @@ sub parent_dir($) # - files by the same name are not present in multiple parent directories # -sub find_base_from_graph($$$) +sub find_base_from_source($$) { - my ($base_dir, $instr, $graph) = @_; + my ($base_dir, $source_files) = @_; my $old_base; my $best_miss; my $best_base; my %rel_files; # Determine list of relative paths - foreach my $filename (keys(%{$instr}), keys(%{$graph})) { + foreach my $filename (@$source_files) { next if (file_name_is_absolute($filename)); $rel_files{$filename} = 1; @@ -2829,17 +3517,17 @@ sub find_base_from_graph($$$) } # -# adjust_graph_filenames(base_dir, instr, graph) +# adjust_source_filenames(hash, base_dir) # -# Make relative paths in INSTR and GRAPH absolute and apply -# geninfo_adjust_src_path setting to graph file data. +# Transform all keys of HASH to absolute form and apply requested +# transformations. # -sub adjust_graph_filenames($$$) +sub adjust_source_filenames($$$) { - my ($base_dir, $instr, $graph) = @_; + my ($hash, $base_dir) = @_; - foreach my $filename (keys(%{$instr})) { + foreach my $filename (keys(%{$hash})) { my $old_filename = $filename; # Convert to absolute canonical form @@ -2851,28 +3539,50 @@ sub adjust_graph_filenames($$$) } if ($filename ne $old_filename) { - $instr->{$filename} = delete($instr->{$old_filename}); + $hash->{$filename} = delete($hash->{$old_filename}); } } +} - foreach my $filename (keys(%{$graph})) { - my $old_filename = $filename; - # Make absolute - # Convert to absolute canonical form - $filename = solve_relative_path($base_dir, $filename); +# +# filter_source_files(hash) +# +# Remove unwanted source file data from HASH. +# - # Apply adjustment - if (defined($adjust_src_pattern)) { - $filename =~ s/$adjust_src_pattern/$adjust_src_replace/g; +sub filter_source_files($) +{ + my ($hash) = @_; + + foreach my $filename (keys(%{$hash})) { + # Skip external files if requested + goto del if (!$opt_external && is_external($filename)); + + # Apply include patterns + if (@include_patterns) { + my $keep; + + foreach my $pattern (@include_patterns) { + if ($filename =~ (/^$pattern$/)) { + $keep = 1; + last; + } + } + goto del if (!$keep); } - if ($filename ne $old_filename) { - $graph->{$filename} = delete($graph->{$old_filename}); + # Apply exclude patterns + foreach my $pattern (@exclude_patterns) { + goto del if ($filename =~ (/^$pattern$/)); } - } + next; - return ($instr, $graph); +del: + # Remove file data + delete($hash->{$filename}); + $excluded_files{$filename} = 1; + } } # @@ -3776,7 +4486,7 @@ sub debug($) sub get_gcov_capabilities() { - my $help = `$gcov_tool --help`; + my $help = `"$gcov_tool" --help`; my %capabilities; my %short_option_translations = ( 'a' => 'all-blocks', @@ -3784,6 +4494,7 @@ sub get_gcov_capabilities() 'c' => 'branch-counts', 'f' => 'function-summaries', 'h' => 'help', + 'i' => 'intermediate-format', 'l' => 'long-file-names', 'n' => 'no-output', 'o' => 'object-directory', @@ -4012,3 +4723,45 @@ sub is_compat_auto($) return 1 if ($compat_value{$mode} == $COMPAT_VALUE_AUTO); return 0; } + +# +# load_json_module(rc) +# +# If RC is "auto", load best available JSON module from a list of alternatives, +# otherwise load the module specified by RC. +# +sub load_json_module($) +{ + my ($rc) = @_; + # List of alternative JSON modules to try + my @alternatives = ( + "JSON::XS", # Fast, but not always installed + "Cpanel::JSON::XS", # Fast, a more recent fork + "JSON::PP", # Slow, part of core-modules + "JSON", # Not available in all distributions + ); + my $mod; + + # Determine JSON module + if (lc($rc) eq "auto") { + for my $m (@alternatives) { + if (check_install(module => $m)) { + $mod = $m; + last; + } + } + + if (!defined($mod)) { + die("No JSON module found (tried ". + join(" ", @alternatives).")\n"); + } + } else { + $mod = $rc; + } + + eval "load '$mod', 'decode_json'"; + if ($@) { + die("Module is not installed: ". "'$mod'\n"); + } + info("Using JSON module $mod\n"); +} diff --git a/externals/lcov/bin/genpng b/externals/lcov/bin/genpng index 943a49d5f0454e01aa12430fbc97a44805ac404e..5049f1f571d7634d9ef61c91a033ea5d5c0fcec2 100755 --- a/externals/lcov/bin/genpng +++ b/externals/lcov/bin/genpng @@ -13,8 +13,8 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# along with this program; if not, see +# <http://www.gnu.org/licenses/>. # # # genpng @@ -38,16 +38,16 @@ use Cwd qw/abs_path/; # Constants our $tool_dir = abs_path(dirname($0)); -our $lcov_version = "LCOV version 1.14"; -our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; +our $lcov_version = 'LCOV version '.`"$tool_dir"/get_version.sh --full`; +our $lcov_url = "https://github.com/linux-test-project/lcov"; our $tool_name = basename($0); # Prototypes -sub gen_png($$$@); +sub gen_png($$$$@); sub check_and_load_module($); sub genpng_print_usage(*); -sub genpng_process_file($$$$); +sub genpng_process_file($$$$$); sub genpng_warn_handler($); sub genpng_die_handler($); @@ -74,6 +74,7 @@ if (!caller) my $filename; my $tab_size = 4; my $width = 80; + my $dark = 0; my $out_filename; my $help; my $version; @@ -85,6 +86,7 @@ if (!caller) if (!GetOptions("tab-size=i" => \$tab_size, "width=i" => \$width, "output-filename=s" => \$out_filename, + "dark-mode" => \$dark, "help" => \$help, "version" => \$version)) { @@ -121,7 +123,7 @@ if (!caller) $out_filename = "$filename.png"; } - genpng_process_file($filename, $out_filename, $width, $tab_size); + genpng_process_file($filename, $out_filename, $width, $tab_size, $dark); exit(0); } @@ -146,6 +148,7 @@ or .gcov file format. -v, --version Print version number, then exit -t, --tab-size TABSIZE Use TABSIZE spaces in place of tab -w, --width WIDTH Set width of output image to WIDTH pixel + -d, --dark-mode Use a light-on-dark color scheme -o, --output-filename FILENAME Write image to FILENAME For more information see: $lcov_url @@ -170,15 +173,16 @@ sub check_and_load_module($) # -# genpng_process_file(filename, out_filename, width, tab_size) +# genpng_process_file(filename, out_filename, width, tab_size, dark) # -sub genpng_process_file($$$$) +sub genpng_process_file($$$$$) { my $filename = $_[0]; my $out_filename = $_[1]; my $width = $_[2]; my $tab_size = $_[3]; + my $dark = $_[4]; local *HANDLE; my @source; @@ -215,12 +219,12 @@ sub genpng_process_file($$$$) } close(HANDLE); - gen_png($out_filename, $width, $tab_size, @source); + gen_png($out_filename, $dark, $width, $tab_size, @source); } # -# gen_png(filename, width, tab_size, source) +# gen_png(filename, dark, width, tab_size, source) # # Write an overview PNG file to FILENAME. Source code is defined by SOURCE # which is a list of lines <count>:<source code> per source code line. @@ -232,9 +236,10 @@ sub genpng_process_file($$$$) # Die on error. # -sub gen_png($$$@) +sub gen_png($$$$@) { my $filename = shift(@_); # Filename for PNG file + my $dark_mode = shift(@_); # dark-on-light, if set my $overview_width = shift(@_); # Imagewidth for image my $tab_size = shift(@_); # Replacement string for tab signs my @source = @_; # Source code as passed via argument 2 @@ -271,14 +276,28 @@ sub gen_png($$$@) or die("ERROR: cannot allocate overview image!\n"); # Define colors - $col_plain_back = $overview->colorAllocate(0xff, 0xff, 0xff); - $col_plain_text = $overview->colorAllocate(0xaa, 0xaa, 0xaa); - $col_cov_back = $overview->colorAllocate(0xaa, 0xa7, 0xef); - $col_cov_text = $overview->colorAllocate(0x5d, 0x5d, 0xea); - $col_nocov_back = $overview->colorAllocate(0xff, 0x00, 0x00); - $col_nocov_text = $overview->colorAllocate(0xaa, 0x00, 0x00); - $col_hi_back = $overview->colorAllocate(0x00, 0xff, 0x00); - $col_hi_text = $overview->colorAllocate(0x00, 0xaa, 0x00); + # overview->colorAllocate(red, green, blue) + if ($dark_mode) { + # just reverse foregrond and background + # there is probably a better color scheme than this. + $col_plain_text = $overview->colorAllocate(0xaa, 0xaa, 0xaa); # light grey + $col_plain_back = $overview->colorAllocate(0x00, 0x00, 0x00); + $col_cov_text = $overview->colorAllocate(0xaa, 0xa7, 0xef); + $col_cov_back = $overview->colorAllocate(0x5d, 0x5d, 0xea); + $col_nocov_text = $overview->colorAllocate(0xff, 0x00, 0x00); + $col_nocov_back = $overview->colorAllocate(0xaa, 0x00, 0x00); + $col_hi_text = $overview->colorAllocate(0x00, 0xff, 0x00); + $col_hi_back = $overview->colorAllocate(0x00, 0xaa, 0x00); + } else { + $col_plain_back = $overview->colorAllocate(0xff, 0xff, 0xff); + $col_plain_text = $overview->colorAllocate(0xaa, 0xaa, 0xaa); + $col_cov_back = $overview->colorAllocate(0xaa, 0xa7, 0xef); + $col_cov_text = $overview->colorAllocate(0x5d, 0x5d, 0xea); + $col_nocov_back = $overview->colorAllocate(0xff, 0x00, 0x00); + $col_nocov_text = $overview->colorAllocate(0xaa, 0x00, 0x00); + $col_hi_back = $overview->colorAllocate(0x00, 0xff, 0x00); + $col_hi_text = $overview->colorAllocate(0x00, 0xaa, 0x00); + } # Visualize each line foreach $line (@source) diff --git a/externals/lcov/bin/get_version.sh b/externals/lcov/bin/get_version.sh index ac5a36314699c7ccfa374d14a1c6e5ab68a62270..62b493314194d6a5efd9a559649d9ea79f6104b7 100755 --- a/externals/lcov/bin/get_version.sh +++ b/externals/lcov/bin/get_version.sh @@ -4,9 +4,9 @@ # # Print lcov version or release information as provided by Git, .version # or a fallback. - -TOOLDIR=$(cd $(dirname $0) >/dev/null ; pwd) -GITVER=$(cd $TOOLDIR ; git describe --tags 2>/dev/null) +DIRPATH=$(dirname "$0") +TOOLDIR=$(cd "$DIRPATH" >/dev/null ; pwd) +GITVER=$(cd "$TOOLDIR" ; git describe --tags 2>/dev/null) if [ -z "$GITVER" ] ; then # Get version information from file diff --git a/externals/lcov/bin/lcov b/externals/lcov/bin/lcov index 33c9f4d16e718f2f76e83d090b2ed2beeec4435f..7c73ab3d23397f76aaaa40a6d2832bcae279fbf8 100755 --- a/externals/lcov/bin/lcov +++ b/externals/lcov/bin/lcov @@ -13,8 +13,8 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# along with this program; if not, see +# <http://www.gnu.org/licenses/>. # # # lcov @@ -73,8 +73,8 @@ use Cwd qw /abs_path getcwd/; # Global constants our $tool_dir = abs_path(dirname($0)); -our $lcov_version = "LCOV version 1.14"; -our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php"; +our $lcov_version = 'LCOV version '.`"$tool_dir"/get_version.sh --full`; +our $lcov_url = "https://github.com/linux-test-project/lcov"; our $tool_name = basename($0); # Directory containing gcov kernel files @@ -131,6 +131,7 @@ sub temp_cleanup(); sub setup_gkv(); sub get_overall_line($$$$); sub print_overall_rate($$$$$$$$$); +sub check_rates($$); sub lcov_geninfo(@); sub create_package($$$;$); sub get_func_found_and_hit($); @@ -159,6 +160,7 @@ our $cwd = `pwd`; # Current working directory our $data_stdout; # If set, indicates that data is written to stdout our $follow; # If set, indicates that find shall follow links our $diff_path = ""; # Path removed from tracefile when applying diff +our $opt_fail_under_lines = 0; our $base_directory; # Base directory (cwd of gcc during compilation) our $checksum; # If set, calculate a checksum for each line our $no_checksum; # If set, don't calculate a checksum for each line @@ -254,6 +256,7 @@ if ($config || %opt_rc) "lcov_list_truncate_max"=> \$opt_list_truncate_max, "lcov_branch_coverage" => \$br_coverage, "lcov_function_coverage"=> \$func_coverage, + "lcov_fail_under_lines" => \$opt_fail_under_lines, }); } @@ -300,6 +303,7 @@ if (!GetOptions("directory|d|di=s" => \@directory, "compat=s" => \$opt_compat, "config-file=s" => \$opt_config_file, "rc=s%" => \%opt_rc, + "fail-under-lines=s" => \$opt_fail_under_lines, )) { print(STDERR "Use $tool_name --help to get usage information\n"); @@ -400,6 +404,7 @@ if (!$from_package && !@directory && ($capture || $reset)) { ($gcov_gkv, $gcov_dir) = setup_gkv(); } +our $exit_code = 0; # Check for requested functionality if ($reset) { @@ -473,6 +478,7 @@ elsif (@opt_summary) ($ln_overall_found, $ln_overall_hit, $fn_overall_found, $fn_overall_hit, $br_overall_found, $br_overall_hit) = summary(); + $exit_code = check_rates($ln_overall_found, $ln_overall_hit); } temp_cleanup(); @@ -484,7 +490,7 @@ if (defined($ln_overall_found)) { } else { info("Done.\n") if (!$list && !$capture); } -exit(0); +exit($exit_code); # # print_usage(handle) @@ -545,6 +551,8 @@ Options: --compat MODE=on|off|auto Set compat MODE (libtool, hammer, split_crc) --include PATTERN Include files matching PATTERN --exclude PATTERN Exclude files matching PATTERN + --fail-under-lines MIN Exit with a status of 1 if the total line + coverage is less than MIN (summary option). For more information see: $lcov_url END_OF_USAGE @@ -4293,6 +4301,33 @@ sub print_overall_rate($$$$$$$$$) if ($br_do); } +# +# check_rates(ln_found, ln_hit) +# +# Check line coverage if it meets a specified threshold. +# + +sub check_rates($$) +{ + my ($ln_found, $ln_hit) = @_; + + if ($opt_fail_under_lines <= 0) { + return 0; + } + + if ($ln_found == 0) { + return 1; + } + + my $actual_rate = ($ln_hit / $ln_found); + my $expected_rate = $opt_fail_under_lines / 100; + if ($actual_rate >= $expected_rate) { + return 0; + } else { + return 1; + } +} + # # rate(hit, found[, suffix, precision, width]) diff --git a/externals/lcov/bin/updateversion.pl b/externals/lcov/bin/updateversion.pl index 19db81ecd3e3228e0f5115dada99755eae2f611d..d39918a6c9ce29abbdbb428d5fe647f867322a08 100755 --- a/externals/lcov/bin/updateversion.pl +++ b/externals/lcov/bin/updateversion.pl @@ -84,7 +84,9 @@ sub get_file_info($) return (0, 0, 0) if (!-e $filename); @stat = stat($filename); - ($sec, $min, $hour, $day, $month, $year) = gmtime($stat[9]); + my $epoch = int($ENV{SOURCE_DATE_EPOCH} || $stat[9]); + $epoch = $stat[9] if $stat[9] < $epoch; + ($sec, $min, $hour, $day, $month, $year) = gmtime($epoch); $year += 1900; $month += 1; diff --git a/externals/lcov/example/methods/iterate.c b/externals/lcov/example/methods/iterate.c index 023d1801c9364f71c994e8c0dbe04b93f3992f34..3dac70d7cf63ec19b689d986300394d2e80abfec 100644 --- a/externals/lcov/example/methods/iterate.c +++ b/externals/lcov/example/methods/iterate.c @@ -13,6 +13,7 @@ #include <stdio.h> #include <stdlib.h> +#include <limits.h> #include "iterate.h" @@ -28,9 +29,9 @@ int iterate_get_sum (int min, int max) for (i = min; i <= max; i++) { /* We can detect an overflow by checking whether the new - sum would become negative. */ + sum would exceed the maximum integer value. */ - if (total + i < total) + if (total > INT_MAX - i) { printf ("Error: sum too large!\n"); exit (1); diff --git a/externals/lcov/lcovrc b/externals/lcov/lcovrc index 40f364f17aa6497f4ccd8af98145367f4b8341ae..4112b8f70f56d1c818522aa2548e50dcbdeda492 100644 --- a/externals/lcov/lcovrc +++ b/externals/lcov/lcovrc @@ -8,6 +8,18 @@ # Specify an external style sheet file (same as --css-file option of genhtml) #genhtml_css_file = gcov.css +# use 'dark' mode display (light foreground, dark background) instead of default +# same as 'genhtml --dark-mode ....' +#genhtml_dark_mode = 1 + +# Header text to use at top of each page +# Default is "LCOV - coverage report" +#genhtml_header = Coverage report for my project + +# Footer text to use at the bottom of each page +# Default is LCOV tool version +#genhtml_footer = My footer text + # Specify coverage rate limits (in %) for classifying file entries # HI: hi_limit <= rate <= 100 graph color: green # MED: med_limit <= rate < hi_limit graph color: orange @@ -102,6 +114,12 @@ genhtml_desc_html=0 # Demangle C++ symbols #genhtml_demangle_cpp=1 +# Name of the tool used for demangling C++ function names +#genhtml_demangle_cpp_tool = c++filt + +# Specify extra parameters to be passed to the demangling tool +#genhtml_demangle_cpp_params = "" + # Location of the gcov tool (same as --gcov-info option of geninfo) #geninfo_gcov_tool = gcov @@ -134,6 +152,12 @@ genhtml_desc_html=0 # when collecting coverage data. geninfo_auto_base = 1 +# Use gcov intermediate format? Valid values are 0, 1, auto +geninfo_intermediate = auto + +# Specify if exception branches should be excluded from branch coverage. +geninfo_no_exception_branch = 0 + # Directory containing gcov kernel files # lcov_gcov_dir = /proc/gcov @@ -167,3 +191,10 @@ lcov_function_coverage = 1 # Specify if branch coverage data should be collected and processed. lcov_branch_coverage = 0 + +# Ask LCOV to return non-zero exit code if line coverage is below threshold +# Default is 0.0 - i.e., do not check threshold. +#lcov_fail_under_lines = 97.5 + +# Specify JSON module to use, or choose best available if set to auto +lcov_json_module = auto diff --git a/externals/lcov/man/gendesc.1 b/externals/lcov/man/gendesc.1 index 9c9a7084db2f39c8245a19c2a08db3e610acf5b8..3d965ad4c5733eb7aedf5688ada6b76a6f957c4a 100644 --- a/externals/lcov/man/gendesc.1 +++ b/externals/lcov/man/gendesc.1 @@ -1,4 +1,4 @@ -.TH gendesc 1 "LCOV 1.14" 2019\-02\-28 "User Manuals" +.TH gendesc 1 "LCOV 1.16" 2020\-08\-12 "User Manuals" .SH NAME gendesc \- Generate a test case description file .SH SYNOPSIS diff --git a/externals/lcov/man/genhtml.1 b/externals/lcov/man/genhtml.1 index 949bd4c574b977f1824150751763e2c81a45bb95..e03f06bc17bbd5805a75a946205d234f1c751f76 100644 --- a/externals/lcov/man/genhtml.1 +++ b/externals/lcov/man/genhtml.1 @@ -1,4 +1,4 @@ -.TH genhtml 1 "LCOV 1.14" 2019\-02\-28 "User Manuals" +.TH genhtml 1 "LCOV 1.16" 2022\-06\-02 "User Manuals" .SH NAME genhtml \- Generate HTML view from LCOV coverage data files .SH SYNOPSIS @@ -17,6 +17,12 @@ genhtml \- Generate HTML view from LCOV coverage data files .RB [ \-o | \-\-output\-directory .IR output\-directory ] .br +.RB [ \-\-header-title +.IR banner ] +.br +.RB [ \-\-footer +.IR string ] +.br .RB [ \-t | \-\-title .IR title ] .br @@ -65,8 +71,11 @@ genhtml \- Generate HTML view from LCOV coverage data files .IR keyword = value ] .br .RB [ \-\-precision +.IR num ] .RB [ \-\-missed ] .br +.RB [ \-\-dark\-mode ] +.br .IR tracefile(s) .RE .SH DESCRIPTION @@ -201,13 +210,41 @@ project size, a lot of files and subdirectories may be created. .RS Display .I title -in header of all pages. +in header table of all pages. .I title -is written to the header portion of each generated HTML page to -identify the context in which a particular output +is written to the "Test:"-field in the header table at the top of each +generated HTML page to identify the context in which a particular output was created. By default this is the name of the tracefile. +A potential use is to specify a test run name, or a version control system +identifier that indicates the code level that was tested. + +.RE +.BI "\-\-header\-title " BANNER +.RS +Display +.I BANNER +in header of all pages. + +.I BANNER +is written to the header portion of each generated HTML page. By default this +simply identifies this as an LCOV coverage report. + +A potential use is to specify the name of the project or project branch and +build ID. + +.RE +.BI "\-\-footer " FOOTER +.RS +Display +.I FOOTER +in footer of all pages. + +.I FOOTER +is written to the footer portion of each generated HTML page. +The default simply identifies the LCOV tool version used to generate the report. + .RE .BI "\-d " description\-file .br @@ -576,6 +613,13 @@ option .IR genhtml_missed . .RE +.B \-\-dark\-mode +.RS +Use a light-display-on-dark-background color scheme rather than the default dark-display-on-light-background. + +The idea is to reduce eye strain due to viewing dark text on a bright screen - particularly at night. + + .SH FILES .I /etc/lcovrc diff --git a/externals/lcov/man/geninfo.1 b/externals/lcov/man/geninfo.1 index 2ce917126c413c54919907147202b18141062b2f..b805591db6e47cff071af0496920ba3844cdc892 100644 --- a/externals/lcov/man/geninfo.1 +++ b/externals/lcov/man/geninfo.1 @@ -1,4 +1,4 @@ -.TH geninfo 1 "LCOV 1.14" 2019\-02\-28 "User Manuals" +.TH geninfo 1 "LCOV 1.16" 2020\-08\-12 "User Manuals" .SH NAME geninfo \- Generate tracefiles from .da files .SH SYNOPSIS @@ -123,6 +123,25 @@ Marks the end of a section which is excluded from branch coverage. The current line not part of this section. .RE .br +LCOV_EXCL_EXCEPTION_BR_LINE +.RS +Lines containing this marker will be excluded from exception branch coverage: +Exception branches will be ignored, but non-exception branches will not be +affected. +.br +.RE +LCOV_EXCL_EXCEPTION_BR_START +.RS +Marks the beginning of a section which is excluded from exception branch +coverage. The current line is part of this section. +.br +.RE +LCOV_EXCL_EXCEPTION_BR_STOP +.RS +Marks the end of a section which is excluded from exception branch coverage. +The current line not part of this section. +.RE +.br .SH OPTIONS @@ -307,6 +326,10 @@ command line switches. The will be interpreted as shell wildcard patterns (note that they may need to be escaped accordingly to prevent the shell from expanding them first). +Note: The pattern must be specified to match the +.B absolute +path of each source file. + Can be combined with the .B --include command line switch. If a given file matches both the include pattern and the @@ -366,6 +389,10 @@ command line switches. The .I patterns will be interpreted as shell wildcard patterns (note that they may need to be escaped accordingly to prevent the shell from expanding them first). + +Note: The pattern must be specified to match the +.B absolute +path of each source file. .RE .B \-\-ignore\-errors diff --git a/externals/lcov/man/genpng.1 b/externals/lcov/man/genpng.1 index f6a49b8a5d48af9f9b0c10b151592fd703ca01d4..2d1d8206ac0d442660187a9e33f6eefcf6697079 100644 --- a/externals/lcov/man/genpng.1 +++ b/externals/lcov/man/genpng.1 @@ -1,4 +1,4 @@ -.TH genpng 1 "LCOV 1.14" 2019\-02\-28 "User Manuals" +.TH genpng 1 "LCOV 1.16" 2022\-06\-01 "User Manuals" .SH NAME genpng \- Generate an overview image from a source file .SH SYNOPSIS @@ -11,6 +11,7 @@ genpng \- Generate an overview image from a source file .IR tabsize ] .RB [ \-w | \-\-width .IR width ] +.RB [ \-d | \-\-dark\-mode ] .br .RB [ \-o | \-\-output\-filename .IR output\-filename ] @@ -79,6 +80,12 @@ Note that source code lines which are longer than will be truncated. .RE +.B \-d +.br +.B \-\-dark\-mode +.RS +Use a light-display-on-dark-background color scheme rather than the default dark-display-on-light-background. +.RE .BI "\-o " filename .br diff --git a/externals/lcov/man/lcov.1 b/externals/lcov/man/lcov.1 index e86eb3aa7624a76d122d791eaca2666dd41362de..22e4639520ddd7968426d7df7adb7b21d2e512f3 100644 --- a/externals/lcov/man/lcov.1 +++ b/externals/lcov/man/lcov.1 @@ -1,4 +1,4 @@ -.TH lcov 1 "LCOV 1.14" 2019\-02\-28 "User Manuals" +.TH lcov 1 "LCOV 1.16" 2022\-06\-03 "User Manuals" .SH NAME lcov \- a graphical GCOV front\-end .SH SYNOPSIS @@ -170,6 +170,8 @@ lcov \- a graphical GCOV front\-end .RS 5 .br .RB [ \-q | \-\-quiet ] +.RB [ \-\-fail-under-lines +.IR percentage ] .br .RE @@ -198,7 +200,7 @@ you have to complete the following preparation steps: For Linux kernel coverage: .RS Follow the setup instructions for the gcov\-kernel infrastructure: -.I http://ltp.sourceforge.net/coverage/gcov.php +.I https://docs.kernel.org/dev-tools/gcov.html .br @@ -497,6 +499,10 @@ command line switches. The will be interpreted as shell wildcard patterns (note that they may need to be escaped accordingly to prevent the shell from expanding them first). +Note: The pattern must be specified to match the +.B absolute +path of each source file. + Can be combined with the .B --include command line switch. If a given file matches both the include pattern and the @@ -540,6 +546,10 @@ Every file entry in .I tracefile which matches at least one of those patterns will be extracted. +Note: The pattern must be specified to match the +.B absolute +path of each source file. + The result of the extract operation will be written to stdout or the tracefile specified with \-o. @@ -598,6 +608,10 @@ command line switches. The .I patterns will be interpreted as shell wildcard patterns (note that they may need to be escaped accordingly to prevent the shell from expanding them first). + +Note: The pattern must be specified to match the +.B absolute +path of each source file. .RE .B \-\-ignore\-errors @@ -799,6 +813,10 @@ Every file entry in .I tracefile which matches at least one of those patterns will be removed. +Note: The pattern must be specified to match the +.B absolute +path of each source file. + The result of the remove operation will be written to stdout or the tracefile specified with \-o. @@ -828,6 +846,14 @@ Only one of \-z, \-c, \-a, \-e, \-r, \-l, \-\-diff or \-\-summary may be specified at a time. .RE +.B \-\-fail-under-lines +.I percentage +.br +.RS +Use this option together with \-\-summary to tell lcov to exit with a status of 1 if the total +line coverage is less than percentage. +.RE + .B \-t .I testname .br diff --git a/externals/lcov/man/lcovrc.5 b/externals/lcov/man/lcovrc.5 index f20d273a92c8ebd48ac8a9f68498024124ef0a8f..61a5a3ce9d2614e88eb414ed054d22ba99093957 100644 --- a/externals/lcov/man/lcovrc.5 +++ b/externals/lcov/man/lcovrc.5 @@ -1,4 +1,4 @@ -.TH lcovrc 5 "LCOV 1.14" 2019\-02\-28 "User Manuals" +.TH lcovrc 5 "LCOV 1.16" 2022\-06\-02 "User Manuals" .SH NAME lcovrc \- lcov configuration file @@ -47,6 +47,23 @@ section 'OPTIONS' below. #genhtml_css_file = gcov.css .br +# Use 'dark' mode display (light foreground/dark background) +.br +# rather than default +.br +#genhtml_dark_mode = 1 +.br + +# Alternate header text to use at top of each page +.br +#genhtml_header = Coverage report for my project +.br + +# Alternate footer text to use at the bottom of each page +.br +#genhtml_footer = My footer text +.br + # Coverage rate limits .br genhtml_hi_limit = 90 @@ -169,6 +186,16 @@ genhtml_desc_html=0 #genhtml_demangle_cpp=1 .br +# Name of the tool used for demangling C++ function names +.br +#genhtml_demangle_cpp_tool = c++filt +.br + +# Specify extra parameters to be passed to the demangling tool +.br +#genhtml_demangle_cpp_params = "" +.br + # Location of the gcov tool .br #geninfo_gcov_tool = gcov @@ -223,6 +250,11 @@ geninfo_compat_libtool = 0 geninfo_auto_base = 1 .br +# Use gcov intermediate format? Valid values are 0, 1, auto +.br +geninfo_intermediate = auto +.br + # Directory containing gcov kernel files .br lcov_gcov_dir = /proc/gcov @@ -266,6 +298,21 @@ lcov_function_coverage = 1 .br lcov_branch_coverage = 0 .br + +# Ask LCOV to return non-zero exit code if line coverage is +.br +# below specified threshold percentage. +.br +lcov_fail_under_lines = 97.5 +.br + +# Specify JSON module to use, or choose best available if +.br +# set to auto +.br +lcov_json_module = auto +.br + .PP .SH OPTIONS @@ -286,6 +333,45 @@ This option corresponds to the \-\-css\-file command line option of By default, a standard CSS file is generated. .PP +.BR genhtml_header " =" +.I string +.IP +Specify header text to use at top of each HTML page. +.br + +This option corresponds to the \-\-header\-title command line option of +.BR genhtml . +.br + +Default is "LCOV - coverage report". +.PP + +.BR genhtml_footer " =" +.I string +.IP +Specify footer text to use at bottom of each HTML page. +.br + +This option corresponds to the \-\-footer command line option of +.BR genhtml . +.br + +Default is LCOV tool version string. +.PP + +.BR genhtml_dark_mode " =" +.IR 0 | 1 +.IP +If non-zero, display using light text on dark background rather than dark text on light background. +.br + +This option corresponds to the \-\-dark\-mode command line option of +.BR genhtml . +.br + +By default, a 'light' palette is used. +.PP + .BR genhtml_hi_limit " =" .I hi_limit .br @@ -586,6 +672,32 @@ This option corresponds to the \-\-demangle\-cpp command line option of Default is 0. .PP +.BR genhtml_demangle_cpp_tool " =" +.I path_to_c++filt +.IP +Specify the location of the demangle tool (see +.BR c++filt (1)) +used to convert C++ internal function names to human readable format +for display on the HTML function overview page. +.br + +Default is 'c++filt'. +.PP + +.BR genhtml_demangle_cpp_params " =" +.I parameters +.IP +Specify extra parameters to be passed to the demangling tool + +Use this option if your environment requires additional parameters such +as --no-strip-underscore for correctly demangling C++ internal function +names. See also +.BR c++filt (1)). +.br + +Default is "". +.PP + .BR genhtml_desc_html " =" .IR 0 | 1 .IP @@ -789,6 +901,34 @@ located, and in addition, is different between files of the same project. Default is 1. .PP +.BR geninfo_intermediate " =" +.IR 0 | 1 | auto +.IP +Specify whether to use gcov intermediate format +.br + +Use this option to control whether geninfo should use the gcov intermediate +format while collecting coverage data. The use of the gcov intermediate format +should increase processing speed. It also provides branch coverage data when +using the \-\-initial command line option. +.br + +Valid values are 0 for off, 1 for on, and "auto" to let geninfo automatically +use immediate format when supported by gcov. +.br + +Default is "auto". +.PP + +.BR geninfo_no_exception_branch " =" +.IR 0 | 1 +.IP +Specify whether to exclude exception branches from branch coverage. +.br + +Default is 0. +.PP + .BR lcov_gcov_dir " =" .I path_to_kernel_coverage_data .IP @@ -893,6 +1033,39 @@ Specify the regular expression of lines to exclude from branch coverage. Default is 'LCOV_EXCL_BR_LINE'. .PP +.BR lcov_excl_exception_br_line " =" +.I expression +.IP +Specify the regular expression of lines to exclude from exception branch coverage. +.br + +Default is 'LCOV_EXCL_EXCEPTION_BR_LINE'. +.PP + +.BR lcov_fail_under_lines " =" +.I percentage +.IP +Specify line coverage threshold to lcov. If the line coverage is below this threshold, lcov will generate all the normal result files and messages, but will return a non-zero exit code. +.br + +This option is equivalent to the \-\-fail\-under\-lines lcov command line option. + +.br +The default is 0 (no threshold). +.PP + +.BR lcov_json_module " =" +.IR module | auto +.IP +Specify the JSON module to use, or choose best available from a set of +alternatives if set to 'auto'. Note that some JSON modules are slower than +others (notably JSON::PP can be very slow compared to JSON::XS). +.br + +Default is 'auto'. +.PP + + .SH FILES .TP diff --git a/externals/lcov/rpm/lcov.spec b/externals/lcov/rpm/lcov.spec index e96c8d47bd08ce9c2c185c0ac417f88b1e25e77f..06e62d8c41602a87e95fe555eff5cb31805aa675 100644 --- a/externals/lcov/rpm/lcov.spec +++ b/externals/lcov/rpm/lcov.spec @@ -1,11 +1,11 @@ Summary: A graphical GCOV front-end Name: lcov -Version: 1.14 +Version: 1.16 Release: 1 License: GPLv2+ Group: Development/Tools -URL: http://ltp.sourceforge.net/coverage/lcov.php -Source0: http://downloads.sourceforge.net/ltp/%{name}-%{version}.tar.gz +URL: https://github.com/linux-test-project/lcov +Source0: https://github.com/linux-test-project/%{name}/releases/download/v%{version}/%{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-root BuildArch: noarch Requires: perl >= 5.8.8