blob: 72d31b7a0d1fb6a535d256d9319b3cf23cbd65a3 [file] [log] [blame]
#!/usr/bin/perl -w
#
# $Id: gcov_filter.pl,v 1.4 2005-11-02 17:23:57 kz Exp $
#
# *************************************************************
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# *************************************************************
# GCOV_FILTER
#
# Helper to filter the gcov output.
# Handle a compare between the hole gcov output and a given select list of exported functions.
#
# Q: Why perl?
# A: regexp ;-)
#
use strict;
use File::Basename;
use Getopt::Long;
# Global constants
our $version_info = 'gcov helper $Revision: 1.4 $ ';
our $help; # Help option flag
our $version; # Version option flag
our $cwd = `pwd`; # current working directory
chomp($cwd);
# our $tool_dir = dirname($0);
# our $tool_file = basename($0);
# our $output_filename;
our $input_allfunc;
# our $input_filename;
our $allfuncinfo; # allfuncinfo option flag
our $showallfunc; # showallfunc option flag
our $no_percentage; # no_percentage option flag
our $donotfilter; # donotfilter option flag
our $objectdir;
# Prototypes
sub print_usage(*);
sub read_gcov_function_file($);
sub get_PRJ_from_makefile_mk();
# sub read_ExportedFunctionList();
sub read_List($);
# if (! ($tool_dir =~ /^\/(.*)$/))
# {
# $tool_dir = "$cwd/$tool_dir";
# }
# Parse command line options
if (!GetOptions( "input-allfunc=s" => \$input_allfunc,
"allfuncinfo" => \$allfuncinfo,
"showallfunc" => \$showallfunc,
"no-percentage" => \$no_percentage,
"do-not-filter" => \$donotfilter,
"objectdir=s" => \$objectdir,
"help" => \$help,
"version" => \$version
))
{
print_usage(*STDERR);
exit(1);
}
# Check for help option
if ($help)
{
print_usage(*STDOUT);
exit(0);
}
# Check for version option
if ($version)
{
print("$version_info\n");
exit(0);
}
# check if enough parameters
if ($#ARGV < 0)
{
print("No input filename specified\n");
print_usage(*STDERR);
exit(1);
}
# special case:
# the filename contains a . or '/' at the beginning
my $startdir = $ARGV[0];
if ( ($startdir =~ /^\.\./) ||
($startdir =~ /^\//) )
{
$startdir = dirname($startdir);
# print("start directory is $startdir\n");
# chdir $startdir;
}
else
{
$startdir = "";
}
# check for sal.map
if ( ! $input_allfunc )
{
# this is a try, to get the project directory form a found makefile.mk
# may work, but fails due to some disunderstandings may be problems in perl :-(
my $sDir = get_PRJ_from_makefile_mk();
# chomp($sDir);
# HDW: print("PRJ is $dir\n");
# $sDir2 = "../..";
my $sMapFile = "$sDir" . "/util/sal.map";
# $sMapFile = "$sDir2" . "/util/sal.map";
if ( -e $sMapFile)
{
$input_allfunc = $sMapFile;
}
else
{
print("No input-allfunc filename specified\n");
print_usage(*STDERR);
exit(1);
}
}
our @aDeprecatedList;
our @aExportedFunctionList;
# read_ExportedFunctionList();
@aExportedFunctionList = read_List($input_allfunc);
@aDeprecatedList = read_List("deprecated.txt");
if ($allfuncinfo)
{
print("Count of all functions: $#aExportedFunctionList\n");
exit(0);
}
if ($showallfunc)
{
my $func;
foreach $func (@aExportedFunctionList)
{
print("$func\n");
}
exit(0);
}
# back to current directory
# this chdir was for a before chdir (in $startdir creation) but due to the fact,
# that the get_PRJ_from_makefile_mk works but the after concat of strings not, this
# chdir is also remarked.
# chdir $cwd;
# HWD: print "count of param: \n";
# $input_filename = $ARGV[0];
my $nCount = $#ARGV + 1;
my $nIdx;
for ($nIdx = 0; $nIdx < $nCount ; ++$nIdx)
{
my $file = $ARGV[$nIdx];
# print("processing: $file\n");
# change directory, to the current file, due to the fact, that we may be need to call gcov
# and gcov will create some extra files, like *.gcov near the current file.
# if ( $startdir ne "" )
# {
# chdir $startdir;
# $file = basename($file);
# }
my $OBJECTS="";
if ($objectdir)
{
$OBJECTS = "-o " . $objectdir;
}
if (! ($file =~ /\.f$/ ))
{
my $filef = "$file.f";
# if (! -e $filef )
# {
# print "gcov $OBJECTS -l -f $file >$filef\n";
my $blah = `gcov $OBJECTS -n -f $file >$filef`;
# }
$file = $filef;
}
read_gcov_function_file($file);
# go back to old directory, because it's possible to change relative to an other directory.
if ( $startdir ne "" )
{
chdir $cwd;
}
}
# print "$tool_dir\n";
# print "all is right\n";
exit(0);
# --------------------------------------------------------------------------------
# Read the map file, which should contain all exported functions.
sub read_List($)
{
local *INPUT_HANDLE;
my $filename = $_[0];
my @list;
my $line = "";
open(INPUT_HANDLE, $filename);
# or die("ERROR: cannot open $filename!\n");
while ($line = <INPUT_HANDLE>)
{
chomp($line);
# reg exp: [spaces]functionname[semicolon][line end]
if ($line =~ /^\s+(\w*);$/)
{
# print("$1\n");
push(@list, $1);
}
}
close(INPUT_HANDLE);
return @list;
}
# --------------------------------------------------------------------------------
# Helper function, test is a given value is found in the global exported function list.
# the given value format could be a simple function name
# or a prototype
# e.g.
# osl_getSystemPathFromFileURL
# or
# void getSystemPathFromFileURL( const char* rtl_...)
#
sub contain_in_List($$)
{
my $func;
my $value = $_[0];
my $list = $_[1];
if ($donotfilter)
{
return $value;
}
foreach $func (@$list) # (@aExportedFunctionList)
{
# first try, direct check
if ($value eq $func)
{
# HWD: print("$value eq $func\n");
return $value;
}
# value not found, second try, may be we found it if we search word wise.
# helper, to insert a space after the word, before '('
$value =~ s/\(/ \(/g;
# may be here we should replace all white spaces by ' '
# split by 'space'
my @list = split(' ', $value);
for(@list)
{
# HWD: print "$list[$n]\n";
if ($_ eq $func)
{
# HWD: print ("found $func in $value\n");
return $_;
}
}
}
# not found
return "";
}
# --------------------------------------------------------------------------------
# Read the gcov function (gcov -f) file
# and compare line by line with the export function list
# so we get a list of functions, which are only exported, and not all stuff.
# sample of output
# new gcov gcc 3.4 format
sub read_gcov_function_file($)
{
local *INPUT_HANDLE;
my $file = $_[0];
my $line = "";
open(INPUT_HANDLE, $file)
or die("ERROR: cannot open $file!\n");
while ($line = <INPUT_HANDLE>)
{
chomp($line);
# sample line (for reg exp:)
# 100.00% of 3 source lines executed in function osl_thread_init_Impl
if ($line =~ /^Function \`(.*)\'$/ )
{
my $sFunctionName = $1;
my $sPercentage;
$line = <INPUT_HANDLE>;
if ($line =~ /^Lines executed:(.*)% of/ )
{
$sPercentage = $1;
}
my $value = contain_in_List( $sFunctionName, \@aExportedFunctionList );
if ($value)
{
my $isDeprecated = contain_in_List( $sFunctionName, \@aDeprecatedList );
if ($isDeprecated)
{
# Function is deprecated, do not export it.
}
else
{
if ($no_percentage)
{
print("$value\n");
}
else
{
print("$sPercentage $value\n");
}
}
}
# push(@aExportedFunctionList, $1);
}
}
close(INPUT_HANDLE);
}
# gcov format since gcc 3.3.6
# 100.00% von 3 Zeilen in function helloworld ausgeführt
# 100.00% von 5 Zeilen in function main ausgeführt
# 100.00% von 8 Zeilen in file tmp.c ausgeführt
sub read_gcov_function_file_old_gcc_3($)
{
local *INPUT_HANDLE;
my $file = $_[0];
my $line = "";
open(INPUT_HANDLE, $file)
or die("ERROR: cannot open $file!\n");
while ($line = <INPUT_HANDLE>)
{
chomp($line);
# sample line (for reg exp:)
# 100.00% of 3 source lines executed in function osl_thread_init_Impl
if ($line =~ /^(.*)% of \d+ source lines executed in function (.*)$/ )
{
my $value = contain_in_List( $2, \@aExportedFunctionList );
if ($value)
{
my $isDeprecated = contain_in_List( $2, \@aDeprecatedList );
if ($isDeprecated)
{
# Function is deprecated, do not export it.
}
else
{
if ($no_percentage)
{
print("$value\n");
}
else
{
print("$1 $value\n");
}
}
}
# push(@aExportedFunctionList, $1);
}
}
close(INPUT_HANDLE);
}
# ------------------------------------------------------------------------------
# helper, to read the PRJ value out of a makefile.mk file
sub get_PRJ_from_makefile_mk()
{
local *INPUT_HANDLE;
# my $startdir = @_[0];
my $line = "";
my $value = "";
open(INPUT_HANDLE, "makefile.mk")
or die("ERROR: cannot open makefile.mk\n");
while ($line = <INPUT_HANDLE>)
{
chomp($line);
# sample line
# PRJ=
# HWD: print("$line\n");
if ($line =~ /^PRJ\s*=(.*)\s*$/)
{
# HWD: print("FOUND #####\n");
$value = $1;
chomp($value);
$value =~ s/\$\//\//g;
}
}
close(INPUT_HANDLE);
return $value;
}
# ----------------------------------------------------------------------------
sub print_usage(*)
{
local *HANDLE = $_[0];
my $tool_name = basename($0);
print(HANDLE <<END_OF_USAGE);
Usage: $tool_name [OPTIONS] INPUTFILE
-h, --help Print this help, then exit
-v, --version Print version number, then exit
-i, --input-allfunc FILENAME Map file, which contain all exported functions
-s, --showallfunc Shows all exported functions then exit
-a, --allfuncinfo Shows the count of all exported functions then quit
-n, --no-percentage Suppress the output of the percent value for tested functions
-d, --do-not-filter Show all functions, which gcov -f produce
END_OF_USAGE
;
}