xref: /aoo4110/main/sal/qa/helper/gcov/gcov_filter.pl (revision b1cdbd2c)
1#!/usr/bin/perl -w
2#
3# $Id: gcov_filter.pl,v 1.4 2005-11-02 17:23:57 kz Exp $
4#
5# *************************************************************
6#
7#  Licensed to the Apache Software Foundation (ASF) under one
8#  or more contributor license agreements.  See the NOTICE file
9#  distributed with this work for additional information
10#  regarding copyright ownership.  The ASF licenses this file
11#  to you under the Apache License, Version 2.0 (the
12#  "License"); you may not use this file except in compliance
13#  with the License.  You may obtain a copy of the License at
14#
15#    http://www.apache.org/licenses/LICENSE-2.0
16#
17#  Unless required by applicable law or agreed to in writing,
18#  software distributed under the License is distributed on an
19#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20#  KIND, either express or implied.  See the License for the
21#  specific language governing permissions and limitations
22#  under the License.
23#
24# *************************************************************
25
26# GCOV_FILTER
27#
28# Helper to filter the gcov output.
29# Handle a compare between the hole gcov output and a given select list of exported functions.
30#
31# Q: Why perl?
32# A: regexp ;-)
33#
34
35
36use strict;
37use File::Basename;
38use Getopt::Long;
39
40# Global constants
41our $version_info = 'gcov helper $Revision: 1.4 $ ';
42our $help;                    # Help option flag
43our $version;                 # Version option flag
44our $cwd = `pwd`;             # current working directory
45chomp($cwd);
46# our $tool_dir = dirname($0);
47# our $tool_file = basename($0);
48
49# our $output_filename;
50our $input_allfunc;
51# our $input_filename;
52
53our $allfuncinfo;             # allfuncinfo option flag
54our $showallfunc;             # showallfunc option flag
55our $no_percentage;           # no_percentage option flag
56our $donotfilter;             # donotfilter option flag
57our $objectdir;
58
59# Prototypes
60sub print_usage(*);
61sub read_gcov_function_file($);
62sub get_PRJ_from_makefile_mk();
63# sub read_ExportedFunctionList();
64sub read_List($);
65
66# if (! ($tool_dir =~ /^\/(.*)$/))
67# {
68#     $tool_dir = "$cwd/$tool_dir";
69# }
70
71# Parse command line options
72if (!GetOptions( "input-allfunc=s" => \$input_allfunc,
73                 "allfuncinfo" => \$allfuncinfo,
74                 "showallfunc" => \$showallfunc,
75                 "no-percentage" => \$no_percentage,
76                 "do-not-filter" => \$donotfilter,
77                 "objectdir=s" => \$objectdir,
78                 "help"   => \$help,
79                 "version" => \$version
80                 ))
81{
82    print_usage(*STDERR);
83    exit(1);
84}
85
86# Check for help option
87if ($help)
88{
89    print_usage(*STDOUT);
90    exit(0);
91}
92
93# Check for version option
94if ($version)
95{
96    print("$version_info\n");
97    exit(0);
98}
99
100# check if enough parameters
101if ($#ARGV < 0)
102{
103    print("No input filename specified\n");
104    print_usage(*STDERR);
105    exit(1);
106}
107
108# special case:
109# the filename contains a . or '/' at the beginning
110my $startdir = $ARGV[0];
111if ( ($startdir =~ /^\.\./) ||
112     ($startdir =~ /^\//) )
113{
114    $startdir = dirname($startdir);
115    # print("start directory is $startdir\n");
116    # chdir $startdir;
117}
118else
119{
120    $startdir = "";
121}
122
123# check for sal.map
124if ( ! $input_allfunc )
125{
126    # this is a try, to get the project directory form a found makefile.mk
127    # may work, but fails due to some disunderstandings may be problems in perl :-(
128    my $sDir = get_PRJ_from_makefile_mk();
129    # chomp($sDir);
130    # HDW: print("PRJ is $dir\n");
131
132    # $sDir2 = "../..";
133    my $sMapFile = "$sDir" . "/util/sal.map";
134    # $sMapFile = "$sDir2" . "/util/sal.map";
135
136    if ( -e $sMapFile)
137    {
138        $input_allfunc = $sMapFile;
139    }
140    else
141    {
142        print("No input-allfunc filename specified\n");
143        print_usage(*STDERR);
144        exit(1);
145    }
146}
147our @aDeprecatedList;
148our @aExportedFunctionList;
149# read_ExportedFunctionList();
150@aExportedFunctionList = read_List($input_allfunc);
151@aDeprecatedList = read_List("deprecated.txt");
152
153if ($allfuncinfo)
154{
155    print("Count of all functions: $#aExportedFunctionList\n");
156    exit(0);
157}
158
159if ($showallfunc)
160{
161    my $func;
162    foreach $func (@aExportedFunctionList)
163    {
164        print("$func\n");
165    }
166    exit(0);
167}
168
169# back to current directory
170# this chdir was for a before chdir (in $startdir creation) but due to the fact,
171# that the get_PRJ_from_makefile_mk works but the after concat of strings not, this
172# chdir is also remarked.
173# chdir $cwd;
174
175# HWD: print "count of param: \n";
176# $input_filename = $ARGV[0];
177
178my $nCount = $#ARGV + 1;
179my $nIdx;
180
181for ($nIdx = 0; $nIdx < $nCount ; ++$nIdx)
182{
183    my $file = $ARGV[$nIdx];
184    # print("processing: $file\n");
185
186    # change directory, to the current file, due to the fact, that we may be need to call gcov
187    # and gcov will create some extra files, like *.gcov near the current file.
188    # if ( $startdir ne "" )
189    # {
190    #     chdir $startdir;
191    #     $file = basename($file);
192    # }
193
194    my $OBJECTS="";
195    if ($objectdir)
196    {
197        $OBJECTS = "-o " . $objectdir;
198    }
199
200    if (! ($file =~ /\.f$/ ))
201    {
202        my $filef = "$file.f";
203        # if (! -e $filef )
204        # {
205        # print "gcov $OBJECTS -l -f $file >$filef\n";
206        my $blah = `gcov $OBJECTS -n -f $file >$filef`;
207        # }
208        $file = $filef;
209    }
210    read_gcov_function_file($file);
211
212    # go back to old directory, because it's possible to change relative to an other directory.
213    if ( $startdir ne "" )
214    {
215        chdir $cwd;
216    }
217}
218
219# print "$tool_dir\n";
220# print "all is right\n";
221exit(0);
222
223
224# --------------------------------------------------------------------------------
225# Read the map file, which should contain all exported functions.
226sub read_List($)
227{
228    local *INPUT_HANDLE;
229    my $filename = $_[0];
230    my @list;
231    my $line = "";
232    open(INPUT_HANDLE, $filename);
233        # or die("ERROR: cannot open $filename!\n");
234
235	while ($line = <INPUT_HANDLE>)
236	{
237		chomp($line);
238        # reg exp: [spaces]functionname[semicolon][line end]
239		if ($line =~ /^\s+(\w*);$/)
240		{
241			# print("$1\n");
242			push(@list, $1);
243		}
244	}
245	close(INPUT_HANDLE);
246    return @list;
247}
248
249# --------------------------------------------------------------------------------
250# Helper function, test is a given value is found in the global exported function list.
251# the given value format could be a simple function name
252# or a prototype
253# e.g.
254# osl_getSystemPathFromFileURL
255# or
256# void getSystemPathFromFileURL( const char* rtl_...)
257#
258sub contain_in_List($$)
259{
260    my $func;
261    my $value = $_[0];
262    my $list = $_[1];
263
264    if ($donotfilter)
265    {
266        return $value;
267    }
268
269    foreach $func (@$list) # (@aExportedFunctionList)
270    {
271        # first try, direct check
272        if ($value eq $func)
273        {
274            # HWD: print("$value eq $func\n");
275            return $value;
276        }
277
278        # value not found, second try, may be we found it if we search word wise.
279        # helper, to insert a space after the word, before '('
280        $value =~ s/\(/ \(/g;
281        # may be here we should replace all white spaces by ' '
282
283        # split by 'space'
284        my @list = split(' ', $value);
285        for(@list)
286        {
287            # HWD: print "$list[$n]\n";
288            if ($_ eq $func)
289            {
290                # HWD: print ("found $func in $value\n");
291                return $_;
292            }
293        }
294    }
295    # not found
296    return "";
297}
298# --------------------------------------------------------------------------------
299# Read the gcov function (gcov -f) file
300# and compare line by line with the export function list
301# so we get a list of functions, which are only exported, and not all stuff.
302# sample of output
303# new gcov gcc 3.4 format
304sub read_gcov_function_file($)
305{
306    local *INPUT_HANDLE;
307    my $file = $_[0];
308    my $line = "";
309    open(INPUT_HANDLE, $file)
310        or die("ERROR: cannot open $file!\n");
311
312    while ($line = <INPUT_HANDLE>)
313    {
314        chomp($line);
315        # sample line (for reg exp:)
316        # 100.00% of 3 source lines executed in function osl_thread_init_Impl
317        if ($line =~ /^Function \`(.*)\'$/ )
318        {
319            my $sFunctionName = $1;
320            my $sPercentage;
321            $line = <INPUT_HANDLE>;
322            if ($line =~ /^Lines executed:(.*)% of/ )
323            {
324                $sPercentage = $1;
325            }
326            my $value = contain_in_List( $sFunctionName, \@aExportedFunctionList );
327            if ($value)
328            {
329                my $isDeprecated = contain_in_List( $sFunctionName, \@aDeprecatedList );
330                if ($isDeprecated)
331                {
332                    # Function is deprecated, do not export it.
333                }
334                else
335                {
336                    if ($no_percentage)
337                    {
338                        print("$value\n");
339                    }
340                    else
341                    {
342                        print("$sPercentage $value\n");
343                    }
344                }
345            }
346            # push(@aExportedFunctionList, $1);
347        }
348    }
349    close(INPUT_HANDLE);
350}
351
352# gcov format since gcc 3.3.6
353# 100.00% von 3 Zeilen in function helloworld ausgef�hrt
354# 100.00% von 5 Zeilen in function main ausgef�hrt
355# 100.00% von 8 Zeilen in file tmp.c ausgef�hrt
356sub read_gcov_function_file_old_gcc_3($)
357{
358    local *INPUT_HANDLE;
359    my $file = $_[0];
360    my $line = "";
361    open(INPUT_HANDLE, $file)
362        or die("ERROR: cannot open $file!\n");
363
364    while ($line = <INPUT_HANDLE>)
365    {
366        chomp($line);
367        # sample line (for reg exp:)
368        # 100.00% of 3 source lines executed in function osl_thread_init_Impl
369        if ($line =~ /^(.*)% of \d+ source lines executed in function (.*)$/ )
370        {
371            my $value = contain_in_List( $2, \@aExportedFunctionList );
372            if ($value)
373            {
374                my $isDeprecated = contain_in_List( $2, \@aDeprecatedList );
375                if ($isDeprecated)
376                {
377                    # Function is deprecated, do not export it.
378                }
379                else
380                {
381                    if ($no_percentage)
382                    {
383                        print("$value\n");
384                    }
385                    else
386                    {
387                        print("$1 $value\n");
388                    }
389                }
390            }
391            # push(@aExportedFunctionList, $1);
392        }
393    }
394    close(INPUT_HANDLE);
395}
396
397# ------------------------------------------------------------------------------
398# helper, to read the PRJ value out of a makefile.mk file
399sub get_PRJ_from_makefile_mk()
400{
401	local *INPUT_HANDLE;
402    # my $startdir = @_[0];
403	my $line = "";
404    my $value = "";
405	open(INPUT_HANDLE, "makefile.mk")
406        or die("ERROR: cannot open makefile.mk\n");
407
408	while ($line = <INPUT_HANDLE>)
409	{
410		chomp($line);
411		# sample line
412		# PRJ=
413        # HWD: print("$line\n");
414		if ($line =~ /^PRJ\s*=(.*)\s*$/)
415		{
416            # HWD: print("FOUND #####\n");
417            $value = $1;
418            chomp($value);
419            $value =~ s/\$\//\//g;
420		}
421	}
422	close(INPUT_HANDLE);
423    return $value;
424}
425
426# ----------------------------------------------------------------------------
427sub print_usage(*)
428{
429    local *HANDLE = $_[0];
430    my $tool_name = basename($0);
431
432    print(HANDLE <<END_OF_USAGE);
433
434Usage: $tool_name [OPTIONS] INPUTFILE
435
436    -h, --help                     Print this help, then exit
437    -v, --version                  Print version number, then exit
438    -i, --input-allfunc FILENAME   Map file, which contain all exported functions
439    -s, --showallfunc              Shows all exported functions then exit
440    -a, --allfuncinfo              Shows the count of all exported functions then quit
441    -n, --no-percentage            Suppress the output of the percent value for tested functions
442    -d, --do-not-filter            Show all functions, which gcov -f produce
443
444END_OF_USAGE
445    ;
446}
447
448