| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
|
2
|
|
|
|
|
|
|
package C::Analyzer; |
|
3
|
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
BEGIN { |
|
5
|
1
|
|
|
1
|
|
79717
|
use Exporter (); |
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
46
|
|
|
6
|
1
|
|
|
1
|
|
8
|
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
188
|
|
|
7
|
1
|
|
|
1
|
|
3
|
$VERSION = '0.01'; |
|
8
|
1
|
|
|
|
|
29
|
@ISA = qw(Exporter); |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
#Give a hoot don't pollute, do not export more than needed by default |
|
11
|
1
|
|
|
|
|
4
|
@EXPORT = qw(); |
|
12
|
1
|
|
|
|
|
2
|
@EXPORT_OK = qw(); |
|
13
|
1
|
|
|
|
|
23
|
%EXPORT_TAGS = (); |
|
14
|
|
|
|
|
|
|
} |
|
15
|
|
|
|
|
|
|
|
|
16
|
1
|
|
|
1
|
|
6
|
use strict; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
105
|
|
|
17
|
1
|
|
|
1
|
|
7
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
4025
|
|
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
my %calls = (); |
|
20
|
|
|
|
|
|
|
my @calls_table = (); |
|
21
|
|
|
|
|
|
|
my @rec_track = (); |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head2 new |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
Usage : my $analyzer = new Analyzer( |
|
28
|
|
|
|
|
|
|
_inputPath => "/home/sindhu/test/afs", # folder path |
|
29
|
|
|
|
|
|
|
_cppPath => "/usr/bin", # GNU C preprocessor path |
|
30
|
|
|
|
|
|
|
_inputOption => "dir_and_subdir", # if dir or dir/subdir |
|
31
|
|
|
|
|
|
|
); |
|
32
|
|
|
|
|
|
|
Purpose : Constructors, Static method that return an object |
|
33
|
|
|
|
|
|
|
Returns : Object |
|
34
|
|
|
|
|
|
|
Argument : _inputPath, _inputOption, _cppPath, _functionName |
|
35
|
|
|
|
|
|
|
Throws : None |
|
36
|
|
|
|
|
|
|
Comment : Can be extended for other important inputs as well in future. |
|
37
|
|
|
|
|
|
|
See Also : |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=cut |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
sub new { |
|
44
|
1
|
|
|
1
|
1
|
11
|
my $class = shift; |
|
45
|
1
|
|
|
|
|
6
|
my %params = @_; |
|
46
|
1
|
|
|
|
|
2
|
my $self = {}; |
|
47
|
1
|
50
|
|
|
|
4
|
if ( defined( $params{'_inputPath'} ) ) { |
|
48
|
1
|
|
|
|
|
3
|
$self->{'_inputPath'} = $params{'_inputPath'}; |
|
49
|
|
|
|
|
|
|
} |
|
50
|
|
|
|
|
|
|
else { |
|
51
|
0
|
|
|
|
|
0
|
print "Error: Missing file/folder path\n"; |
|
52
|
0
|
|
|
|
|
0
|
exit; |
|
53
|
|
|
|
|
|
|
} |
|
54
|
|
|
|
|
|
|
|
|
55
|
1
|
50
|
|
|
|
3
|
if ( defined( $params{'_inputOption'} ) ) { |
|
56
|
1
|
|
|
|
|
3
|
$self->{'_inputOption'} = $params{'_inputOption'}; |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
else { |
|
59
|
0
|
|
|
|
|
0
|
init $self->{'_inputOption'} = "dir"; |
|
60
|
|
|
|
|
|
|
} |
|
61
|
1
|
50
|
|
|
|
3
|
if ( defined( $params{'_cppPath'} ) ) { |
|
62
|
1
|
|
|
|
|
2
|
$self->{'_cppPath'} = $params{'_cppPath'}; |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
else { |
|
65
|
0
|
|
|
|
|
0
|
print "Error: Missing GNU C Processor path\n"; |
|
66
|
0
|
|
|
|
|
0
|
exit; |
|
67
|
|
|
|
|
|
|
} |
|
68
|
1
|
50
|
|
|
|
3
|
if ( defined( $params{'_cppOptions'} ) ) { |
|
69
|
0
|
|
|
|
|
0
|
$self->{'_cppOptions'} = $params{'_cppOptions'}; |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
else { |
|
72
|
1
|
|
|
|
|
2
|
$self->{'_cppOptions'} = "-nostdinc"; |
|
73
|
|
|
|
|
|
|
} |
|
74
|
1
|
50
|
|
|
|
3
|
if ( defined( $params{'_functionName'} ) ) { |
|
75
|
0
|
|
|
|
|
0
|
$self->{'_functionName'} = $params{'_functionName'}; |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
else { |
|
78
|
1
|
|
|
|
|
3
|
$self->{'_functionName'} = "main"; |
|
79
|
|
|
|
|
|
|
} |
|
80
|
1
|
50
|
|
|
|
2
|
if ( defined( $params{'_reportType'} ) ) { |
|
81
|
0
|
|
|
|
|
0
|
$self->{'_reportType'} = $params{'_reportType'}; |
|
82
|
|
|
|
|
|
|
} |
|
83
|
|
|
|
|
|
|
else { |
|
84
|
1
|
|
|
|
|
2
|
$self->{'_reportType'} = "Text"; |
|
85
|
|
|
|
|
|
|
} |
|
86
|
1
|
50
|
|
|
|
3
|
if ( defined( $params{'_reportOptions'} ) ) { |
|
87
|
0
|
|
|
|
|
0
|
$self->{'_reportOptions'} = $params{'_reportOptions'}; |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
else { |
|
90
|
1
|
|
|
|
|
2
|
$self->{'_reportOptions'} = "fullDetails"; |
|
91
|
|
|
|
|
|
|
} |
|
92
|
1
|
50
|
|
|
|
3
|
if ( defined( $params{'_treeType'} ) ) { |
|
93
|
0
|
|
|
|
|
0
|
$self->{'_treeType'} = $params{'_treeType'}; |
|
94
|
|
|
|
|
|
|
} |
|
95
|
|
|
|
|
|
|
else { |
|
96
|
1
|
|
|
|
|
4
|
$self->{'_treeType'} = "callTree"; |
|
97
|
|
|
|
|
|
|
} |
|
98
|
1
|
|
|
|
|
4
|
bless $self, $class; |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=head2 init |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
Usage : init() |
|
106
|
|
|
|
|
|
|
Purpose : initializes variables, gets C files in dir/subdirs, |
|
107
|
|
|
|
|
|
|
runs GNU C Preprocessor and updates functions and |
|
108
|
|
|
|
|
|
|
calls in each C file |
|
109
|
|
|
|
|
|
|
Returns : None |
|
110
|
|
|
|
|
|
|
Argument : None |
|
111
|
|
|
|
|
|
|
Throws : None |
|
112
|
|
|
|
|
|
|
Comment : None |
|
113
|
|
|
|
|
|
|
See Also : |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=cut |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub init() { |
|
120
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
|
121
|
0
|
|
|
|
|
|
&clean(); |
|
122
|
0
|
|
|
|
|
|
my $folder = ""; |
|
123
|
0
|
|
|
|
|
|
my $opt = ""; |
|
124
|
0
|
|
|
|
|
|
my $cppPath = ""; |
|
125
|
0
|
|
|
|
|
|
my $cppOpts = ""; |
|
126
|
0
|
|
|
|
|
|
my $funName = ""; |
|
127
|
0
|
|
|
|
|
|
my $cfiles; |
|
128
|
|
|
|
|
|
|
my $ppfiles; |
|
129
|
0
|
|
|
|
|
|
my $cfile; |
|
130
|
|
|
|
|
|
|
|
|
131
|
0
|
0
|
|
|
|
|
$folder = $self->{_inputPath} if defined($folder); |
|
132
|
0
|
0
|
|
|
|
|
$opt = $self->{_inputOption} if defined($opt); |
|
133
|
0
|
0
|
|
|
|
|
$cppPath = $self->{_cppPath} if defined($cppPath); |
|
134
|
0
|
0
|
|
|
|
|
$cppOpts = $self->{_cppOptions} if defined($cppOpts); |
|
135
|
|
|
|
|
|
|
|
|
136
|
0
|
|
|
|
|
|
$cfiles = &getListOfCFiles( \$folder, \$opt ); |
|
137
|
0
|
|
|
|
|
|
$ppfiles = &runGnuPreprocessor( \$cfiles, \$cppPath, \$cppOpts ); |
|
138
|
0
|
|
|
|
|
|
&identifyFunctionsAndCalls( \$ppfiles, \$opt, \$folder ); |
|
139
|
0
|
|
|
|
|
|
return; |
|
140
|
|
|
|
|
|
|
} |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=head2 calltree |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
Usage : calltree() |
|
147
|
|
|
|
|
|
|
Purpose : Initial preperations for calltree generation for |
|
148
|
|
|
|
|
|
|
user given functions. |
|
149
|
|
|
|
|
|
|
Returns : None |
|
150
|
|
|
|
|
|
|
Argument : Takes a reference to list of functions |
|
151
|
|
|
|
|
|
|
Throws : None |
|
152
|
|
|
|
|
|
|
Comment : None |
|
153
|
|
|
|
|
|
|
See Also : |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=cut |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
sub calltree() { |
|
160
|
0
|
|
|
0
|
1
|
|
my ( $class, $functions ) = @_; |
|
161
|
0
|
|
|
|
|
|
my @funclist = (); |
|
162
|
0
|
0
|
|
|
|
|
if ( defined($functions) ) { |
|
163
|
0
|
|
|
|
|
|
@funclist = @{$functions}; |
|
|
0
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
else { |
|
166
|
0
|
|
|
|
|
|
@funclist = qw(main); |
|
167
|
|
|
|
|
|
|
} |
|
168
|
0
|
|
|
|
|
|
foreach my $function (@funclist) { |
|
169
|
0
|
|
|
|
|
|
&prepareCalltreeInit( \$function ); |
|
170
|
|
|
|
|
|
|
} |
|
171
|
0
|
|
|
|
|
|
return; |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
=head2 getListOfCFiles |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
Usage : getListOfCFiles() |
|
179
|
|
|
|
|
|
|
Purpose : Takes folder name and GNU C Preprocessor options |
|
180
|
|
|
|
|
|
|
and returns list of C files in dir/subdir |
|
181
|
|
|
|
|
|
|
Returns : reference to array of C files |
|
182
|
|
|
|
|
|
|
Argument : folder name and GNU C Preprocessor options |
|
183
|
|
|
|
|
|
|
Throws : None |
|
184
|
|
|
|
|
|
|
Comment : None |
|
185
|
|
|
|
|
|
|
See Also : |
|
186
|
|
|
|
|
|
|
None |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=cut |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub getListOfCFiles() { |
|
193
|
0
|
|
|
0
|
1
|
|
my ( $folder, $opt ) = @_; |
|
194
|
0
|
|
|
|
|
|
my @cfiles = (); |
|
195
|
0
|
|
|
|
|
|
my $OS = $^O; |
|
196
|
0
|
|
|
|
|
|
$$folder =~ s/\//\\/g; |
|
197
|
0
|
0
|
0
|
|
|
|
if ( ( defined $OS ) |
|
|
|
|
0
|
|
|
|
|
|
198
|
|
|
|
|
|
|
&& ( $OS eq "MSWin32" ) |
|
199
|
|
|
|
|
|
|
&& ( $$opt eq "dir_and_subdir" ) ) |
|
200
|
|
|
|
|
|
|
{ |
|
201
|
0
|
|
|
|
|
|
@cfiles = `dir /b /s \"$$folder\*.c\"`; |
|
202
|
|
|
|
|
|
|
} |
|
203
|
0
|
0
|
0
|
|
|
|
if ( ( defined $OS ) && ( $OS eq "MSWin32" ) && ( $$opt eq "dir" ) ) { |
|
|
|
|
0
|
|
|
|
|
|
204
|
0
|
|
|
|
|
|
chdir $$folder; |
|
205
|
0
|
|
|
|
|
|
@cfiles = `dir /b *.c`; |
|
206
|
|
|
|
|
|
|
} |
|
207
|
0
|
0
|
0
|
|
|
|
if ( ( defined $OS ) |
|
|
|
|
0
|
|
|
|
|
|
208
|
|
|
|
|
|
|
&& ( $OS eq "linux" ) |
|
209
|
|
|
|
|
|
|
&& ( $$opt eq "dir_and_subdir" ) ) |
|
210
|
|
|
|
|
|
|
{ |
|
211
|
0
|
|
|
|
|
|
my $path = $$folder; |
|
212
|
0
|
|
|
|
|
|
$path =~ s/\\/\//g; |
|
213
|
0
|
|
|
|
|
|
chdir $path; |
|
214
|
0
|
|
|
|
|
|
@cfiles = `find \. -name \*.c`; |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
} |
|
217
|
0
|
0
|
0
|
|
|
|
if ( ( defined $OS ) && ( $OS eq "linux" ) && ( $$opt eq "dir" ) ) { |
|
|
|
|
0
|
|
|
|
|
|
218
|
0
|
|
|
|
|
|
chdir $$folder; |
|
219
|
0
|
|
|
|
|
|
@cfiles = `find *.c`; |
|
220
|
|
|
|
|
|
|
} |
|
221
|
0
|
|
|
|
|
|
return ( \@cfiles ); |
|
222
|
|
|
|
|
|
|
} |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=head2 prepareCalltreeInit |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
Usage : prepareCalltreeInit() |
|
229
|
|
|
|
|
|
|
Purpose : final preparations for calltree generation |
|
230
|
|
|
|
|
|
|
Returns : none |
|
231
|
|
|
|
|
|
|
Argument : function name |
|
232
|
|
|
|
|
|
|
Throws : None |
|
233
|
|
|
|
|
|
|
Comment : None |
|
234
|
|
|
|
|
|
|
See Also : |
|
235
|
|
|
|
|
|
|
None |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=cut |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub prepareCalltreeInit() { |
|
242
|
0
|
|
|
0
|
1
|
|
my ($function) = shift; |
|
243
|
0
|
|
|
|
|
|
my $localtime = localtime(); |
|
244
|
0
|
|
|
|
|
|
my @calls = (); |
|
245
|
0
|
0
|
|
|
|
|
if ( exists $calls{$$function} ) { |
|
246
|
0
|
|
|
|
|
|
@calls = @{ $calls{$$function} }; |
|
|
0
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
} |
|
248
|
|
|
|
|
|
|
else { |
|
249
|
0
|
|
|
|
|
|
print "Function does not exists\n"; |
|
250
|
0
|
|
|
|
|
|
return; |
|
251
|
|
|
|
|
|
|
} |
|
252
|
0
|
0
|
0
|
|
|
|
if ( defined($$function) && defined( $calls[0] ) ) { |
|
253
|
0
|
|
|
|
|
|
print "<0>$$function$calls[0]\n"; |
|
254
|
|
|
|
|
|
|
} |
|
255
|
0
|
|
|
|
|
|
$| = 1; |
|
256
|
0
|
|
|
|
|
|
shift(@calls); |
|
257
|
0
|
|
|
|
|
|
my $calltablelen = scalar(@calls); |
|
258
|
0
|
0
|
|
|
|
|
if ( $calltablelen == 0 ) { |
|
259
|
0
|
|
|
|
|
|
print "Sorry! Function \"$$function\" does not contain any calls"; |
|
260
|
0
|
|
|
|
|
|
return; |
|
261
|
|
|
|
|
|
|
} |
|
262
|
0
|
|
|
|
|
|
&generateCalltree( $$function, 1 ); |
|
263
|
0
|
|
|
|
|
|
print "\n"; |
|
264
|
0
|
|
|
|
|
|
return; |
|
265
|
|
|
|
|
|
|
} |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=head2 generateCalltree |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
Usage : generateCalltree() |
|
272
|
|
|
|
|
|
|
Purpose : Functions that actually generates the functional calltree |
|
273
|
|
|
|
|
|
|
Returns : none |
|
274
|
|
|
|
|
|
|
Argument : function name and tab count |
|
275
|
|
|
|
|
|
|
Throws : None |
|
276
|
|
|
|
|
|
|
Comment : None |
|
277
|
|
|
|
|
|
|
See Also : |
|
278
|
|
|
|
|
|
|
None |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=cut |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
sub generateCalltree() { |
|
285
|
0
|
|
|
0
|
1
|
|
my ( $function, $tabcount ) = ( shift, shift ); |
|
286
|
0
|
0
|
|
|
|
|
if ( $calls{$function} ) { |
|
287
|
0
|
|
|
|
|
|
push( @rec_track, $function ); |
|
288
|
0
|
|
|
|
|
|
my @calls = @{ $calls{$function} }; |
|
|
0
|
|
|
|
|
|
|
|
289
|
0
|
|
|
|
|
|
shift(@calls); |
|
290
|
0
|
|
|
|
|
|
foreach my $call (@calls) { |
|
291
|
0
|
|
|
|
|
|
my $curr_cnt = $tabcount; |
|
292
|
0
|
|
|
|
|
|
my $temp_call = $call; |
|
293
|
|
|
|
|
|
|
|
|
294
|
0
|
0
|
|
|
|
|
if ( $temp_call =~ /^\[/ ) { |
|
295
|
0
|
|
|
|
|
|
next; |
|
296
|
|
|
|
|
|
|
} |
|
297
|
0
|
|
|
|
|
|
$temp_call =~ /(\w+)\s*\(/; |
|
298
|
0
|
|
|
|
|
|
$temp_call = $1; |
|
299
|
0
|
|
|
|
|
|
$temp_call = trim($temp_call); |
|
300
|
0
|
|
|
|
|
|
my $temp_fun = $function; |
|
301
|
0
|
|
|
|
|
|
$temp_fun = trim($temp_fun); |
|
302
|
0
|
|
|
|
|
|
my $is_there = 0; |
|
303
|
0
|
|
|
|
|
|
foreach my $element (@rec_track) { |
|
304
|
|
|
|
|
|
|
|
|
305
|
0
|
0
|
|
|
|
|
if ( $element eq $temp_call ) { |
|
306
|
0
|
|
|
|
|
|
$is_there = 1; |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# $temp_element = $element; |
|
309
|
0
|
|
|
|
|
|
last; |
|
310
|
|
|
|
|
|
|
} |
|
311
|
|
|
|
|
|
|
} |
|
312
|
0
|
0
|
|
|
|
|
if ( $is_there eq 0 ) { |
|
313
|
|
|
|
|
|
|
|
|
314
|
0
|
|
|
|
|
|
my $str = ""; |
|
315
|
0
|
|
|
|
|
|
for ( my $i = 0 ; $i < $tabcount ; $i++ ) { |
|
316
|
|
|
|
|
|
|
|
|
317
|
0
|
|
|
|
|
|
print " "; |
|
318
|
0
|
|
|
|
|
|
$str = "$str" . " "; |
|
319
|
0
|
|
|
|
|
|
$| = 1; |
|
320
|
|
|
|
|
|
|
} |
|
321
|
|
|
|
|
|
|
|
|
322
|
0
|
0
|
|
|
|
|
if ( $call =~ /^\(/ ) { |
|
323
|
0
|
|
|
|
|
|
$call = "__double_def" . "$call"; |
|
324
|
0
|
|
|
|
|
|
print "<$tabcount>$call\n"; |
|
325
|
0
|
|
|
|
|
|
$call = ""; |
|
326
|
|
|
|
|
|
|
} |
|
327
|
|
|
|
|
|
|
else { |
|
328
|
0
|
|
|
|
|
|
print "<$tabcount>$call\n"; |
|
329
|
|
|
|
|
|
|
} |
|
330
|
|
|
|
|
|
|
|
|
331
|
0
|
|
|
|
|
|
$| = 1; |
|
332
|
0
|
|
|
|
|
|
$temp_call = $call; |
|
333
|
0
|
|
|
|
|
|
$temp_call =~ /(\w+)\s*\(/; |
|
334
|
0
|
|
|
|
|
|
$temp_call = $1; |
|
335
|
0
|
|
|
|
|
|
$temp_call = trim($temp_call); |
|
336
|
0
|
0
|
0
|
|
|
|
my $tmp = "$str" . "$temp_call>" |
|
337
|
|
|
|
|
|
|
if ( defined($temp_call) && defined($str) ); |
|
338
|
0
|
|
|
|
|
|
$tmp = ""; |
|
339
|
|
|
|
|
|
|
|
|
340
|
0
|
0
|
|
|
|
|
if ( defined($temp_call) ) { |
|
341
|
0
|
|
|
|
|
|
&generateCalltree( $temp_call, $tabcount + 1 ); |
|
342
|
|
|
|
|
|
|
} |
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
} |
|
345
|
|
|
|
|
|
|
else { |
|
346
|
0
|
|
|
|
|
|
my $str = ""; |
|
347
|
0
|
|
|
|
|
|
for ( my $i = 0 ; $i < $tabcount ; $i++ ) { |
|
348
|
|
|
|
|
|
|
|
|
349
|
0
|
|
|
|
|
|
print " "; |
|
350
|
0
|
|
|
|
|
|
$str = "$str" . " "; |
|
351
|
|
|
|
|
|
|
|
|
352
|
0
|
|
|
|
|
|
$| = 1; |
|
353
|
|
|
|
|
|
|
} |
|
354
|
|
|
|
|
|
|
|
|
355
|
0
|
0
|
|
|
|
|
if ( $call =~ /^\(/ ) { |
|
356
|
0
|
|
|
|
|
|
$call = "__double_def" . "$call"; |
|
357
|
0
|
|
|
|
|
|
print "<$tabcount>$call ---@\n"; |
|
358
|
0
|
|
|
|
|
|
$call = ""; |
|
359
|
|
|
|
|
|
|
} |
|
360
|
|
|
|
|
|
|
else { |
|
361
|
0
|
|
|
|
|
|
print "<$tabcount>$call\n"; |
|
362
|
|
|
|
|
|
|
} |
|
363
|
|
|
|
|
|
|
|
|
364
|
0
|
|
|
|
|
|
my $temp_call = $call; |
|
365
|
0
|
|
|
|
|
|
$temp_call =~ /(\w+)\s*\(/; |
|
366
|
0
|
|
|
|
|
|
$temp_call = $1; |
|
367
|
0
|
|
|
|
|
|
$temp_call = trim($temp_call); |
|
368
|
0
|
|
|
|
|
|
$| = 1; |
|
369
|
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
} |
|
371
|
|
|
|
|
|
|
} |
|
372
|
|
|
|
|
|
|
} |
|
373
|
0
|
|
|
|
|
|
return; |
|
374
|
|
|
|
|
|
|
} |
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
=head2 runGnuPreprocessor |
|
379
|
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
Usage : runGnuPreprocessor() |
|
381
|
|
|
|
|
|
|
Purpose : runs GNU C preprocessor in the user given path |
|
382
|
|
|
|
|
|
|
Returns : returns a reference to list of names of preprocessed files |
|
383
|
|
|
|
|
|
|
Argument : reference of list of C files, CPP Path, Options |
|
384
|
|
|
|
|
|
|
Throws : None |
|
385
|
|
|
|
|
|
|
Comment : None |
|
386
|
|
|
|
|
|
|
See Also : |
|
387
|
|
|
|
|
|
|
None |
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
=cut |
|
390
|
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
sub runGnuPreprocessor() { |
|
394
|
0
|
|
|
0
|
1
|
|
my ( $cfiles, $cppPath, $cppOpts ) = @_; |
|
395
|
0
|
|
|
|
|
|
my ( $prepfile, $prep_str ); |
|
396
|
0
|
|
|
|
|
|
my @ppfiles = (); |
|
397
|
0
|
|
|
|
|
|
my $len = scalar(@$$cfiles); |
|
398
|
0
|
|
|
|
|
|
my $cnt = 0; |
|
399
|
0
|
|
|
|
|
|
foreach my $cfile (@$$cfiles) { |
|
400
|
0
|
|
|
|
|
|
$cnt++; |
|
401
|
0
|
|
|
|
|
|
chomp($cfile); |
|
402
|
0
|
|
|
|
|
|
$cfile =~ s/\\/\//g; |
|
403
|
0
|
|
|
|
|
|
&progress_bar( $cnt, $len, 50, '=' ); |
|
404
|
0
|
0
|
|
|
|
|
if ( $cfile =~ /(.*)(\.c|\.C)$/ ) { |
|
405
|
0
|
|
|
|
|
|
my $stripfile = trim($1); |
|
406
|
0
|
|
|
|
|
|
$stripfile =~ s/\\/\//g; |
|
407
|
0
|
|
|
|
|
|
$prepfile = "$stripfile" . "._pp"; |
|
408
|
|
|
|
|
|
|
} |
|
409
|
|
|
|
|
|
|
$prep_str = |
|
410
|
0
|
|
|
|
|
|
"\"$$cppPath" . "/cpp\"" . " " |
|
411
|
|
|
|
|
|
|
. "$$cppOpts" . " " |
|
412
|
|
|
|
|
|
|
. "\"$cfile\"" . " " |
|
413
|
|
|
|
|
|
|
. "> \"$prepfile\" 2>junk.txt"; |
|
414
|
0
|
|
|
|
|
|
push( @ppfiles, $prepfile ); |
|
415
|
0
|
|
|
|
|
|
system($prep_str); |
|
416
|
|
|
|
|
|
|
} |
|
417
|
0
|
|
|
|
|
|
print "\n"; |
|
418
|
0
|
|
|
|
|
|
@$$cfiles = (); |
|
419
|
0
|
|
|
|
|
|
return ( \@ppfiles ); |
|
420
|
|
|
|
|
|
|
} |
|
421
|
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
423
|
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
=head2 identifyFunctionsAndCalls |
|
425
|
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
Usage : identifyFunctionsAndCalls() |
|
427
|
|
|
|
|
|
|
Purpose : initial preperation for parsing each C file to identify |
|
428
|
|
|
|
|
|
|
functions and calls |
|
429
|
|
|
|
|
|
|
Returns : none |
|
430
|
|
|
|
|
|
|
Argument : reference to list of preprocessor files, options and folder |
|
431
|
|
|
|
|
|
|
names. |
|
432
|
|
|
|
|
|
|
Throws : None |
|
433
|
|
|
|
|
|
|
Comment : None |
|
434
|
|
|
|
|
|
|
See Also : |
|
435
|
|
|
|
|
|
|
None |
|
436
|
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
=cut |
|
438
|
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
440
|
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
sub identifyFunctionsAndCalls() { |
|
442
|
0
|
|
|
0
|
1
|
|
my ( $ppfiles, $opt, $folder ) = @_; |
|
443
|
0
|
|
|
|
|
|
my $fun_calls; |
|
444
|
0
|
|
|
|
|
|
foreach my $ppfile (@$$ppfiles) { |
|
445
|
0
|
|
|
|
|
|
$fun_calls = parseCFile( \$ppfile, \$$opt, \$$folder ); |
|
446
|
0
|
|
|
|
|
|
updateHashTable( \$fun_calls ); |
|
447
|
|
|
|
|
|
|
} |
|
448
|
0
|
|
|
|
|
|
return; |
|
449
|
|
|
|
|
|
|
} |
|
450
|
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
452
|
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
=head2 parseCFile |
|
454
|
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
Usage : parseCFile() |
|
456
|
|
|
|
|
|
|
Purpose : Parser module to identify functions and calls in C files. |
|
457
|
|
|
|
|
|
|
Returns : reference to array of funs and calls. |
|
458
|
|
|
|
|
|
|
Argument : reference to filename, options and foldername |
|
459
|
|
|
|
|
|
|
Throws : None |
|
460
|
|
|
|
|
|
|
Comment : None |
|
461
|
|
|
|
|
|
|
See Also : |
|
462
|
|
|
|
|
|
|
None |
|
463
|
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
=cut |
|
465
|
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
467
|
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
sub parseCFile() { |
|
469
|
0
|
|
|
0
|
1
|
|
my ( $infile, $opt_s, $FolderName ) = shift; |
|
470
|
0
|
|
|
|
|
|
my @t_funs_calls = (); |
|
471
|
0
|
|
|
|
|
|
my @pplines = (); |
|
472
|
0
|
|
|
|
|
|
my $OpenCount = 0; |
|
473
|
0
|
|
|
|
|
|
my $CloseCount = 0; |
|
474
|
0
|
|
|
|
|
|
my $lno = 0; |
|
475
|
0
|
|
|
|
|
|
my $fragment; |
|
476
|
|
|
|
|
|
|
my $filename; |
|
477
|
0
|
|
|
|
|
|
my $fun; |
|
478
|
0
|
0
|
|
|
|
|
open( PPFILE, "<$$infile" ) || die("Cannot open input file $$infile\n"); |
|
479
|
0
|
|
|
|
|
|
@pplines = ; |
|
480
|
0
|
|
|
|
|
|
close(PPFILE); |
|
481
|
|
|
|
|
|
|
|
|
482
|
0
|
|
|
|
|
|
foreach my $ppfile (@pplines) { |
|
483
|
0
|
|
|
|
|
|
$lno++; |
|
484
|
0
|
|
|
|
|
|
$ppfile =~ s/\".*\(.*\"/ /g; |
|
485
|
|
|
|
|
|
|
|
|
486
|
0
|
0
|
|
|
|
|
if ( $ppfile =~ /^\#\s*([0-9]+)\s*\"(.*)\s*\"/ ) { |
|
487
|
0
|
|
|
|
|
|
$lno = $1; |
|
488
|
0
|
|
|
|
|
|
$lno--; |
|
489
|
0
|
|
|
|
|
|
$filename = trim($2); |
|
490
|
0
|
|
|
|
|
|
next; |
|
491
|
|
|
|
|
|
|
} |
|
492
|
0
|
|
|
|
|
|
while ( $ppfile =~ /(\w+)\s*\(/g ) { |
|
493
|
0
|
|
|
|
|
|
my $t_fun = $1; |
|
494
|
0
|
|
|
|
|
|
$t_fun = trim($t_fun); |
|
495
|
0
|
0
|
0
|
|
|
|
if ( ( $t_fun eq "if" ) |
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
496
|
|
|
|
|
|
|
|| ( $t_fun eq "for" ) |
|
497
|
|
|
|
|
|
|
|| ( $t_fun eq "while" ) |
|
498
|
|
|
|
|
|
|
|| ( $t_fun eq "switch" ) |
|
499
|
|
|
|
|
|
|
|| ( $t_fun eq "case" ) |
|
500
|
|
|
|
|
|
|
|| ( $t_fun eq "int" ) |
|
501
|
|
|
|
|
|
|
|| ( $t_fun eq "char" ) |
|
502
|
|
|
|
|
|
|
|| ( $t_fun eq "flaot" ) |
|
503
|
|
|
|
|
|
|
|| ( $t_fun eq "double" ) |
|
504
|
|
|
|
|
|
|
|| ( $t_fun eq "long" ) |
|
505
|
|
|
|
|
|
|
|| ( $t_fun eq "short" ) |
|
506
|
|
|
|
|
|
|
|| ( $t_fun eq "bit" ) |
|
507
|
|
|
|
|
|
|
|| ( $t_fun eq "unsigned" ) |
|
508
|
|
|
|
|
|
|
|| ( $t_fun eq "return" ) ) |
|
509
|
|
|
|
|
|
|
{ |
|
510
|
0
|
|
|
|
|
|
next; |
|
511
|
|
|
|
|
|
|
} |
|
512
|
0
|
0
|
|
|
|
|
if ($opt_s) { |
|
513
|
0
|
|
|
|
|
|
my $filelength = length($FolderName); |
|
514
|
0
|
|
|
|
|
|
$fragment = substr $filename, $filelength; |
|
515
|
0
|
|
|
|
|
|
$fragment = "." . "$fragment"; |
|
516
|
0
|
0
|
|
|
|
|
if ( $t_fun eq "" ) { |
|
517
|
|
|
|
|
|
|
; |
|
518
|
|
|
|
|
|
|
} |
|
519
|
|
|
|
|
|
|
else { |
|
520
|
0
|
|
|
|
|
|
$fun = "$t_fun" . "($lno, $fragment)"; |
|
521
|
|
|
|
|
|
|
} |
|
522
|
|
|
|
|
|
|
} |
|
523
|
|
|
|
|
|
|
else { |
|
524
|
0
|
0
|
|
|
|
|
if ( $t_fun eq "" ) { |
|
525
|
0
|
|
|
|
|
|
print; |
|
526
|
|
|
|
|
|
|
} |
|
527
|
|
|
|
|
|
|
else { |
|
528
|
0
|
|
|
|
|
|
$fun = "$t_fun" . "($lno, $filename)"; |
|
529
|
|
|
|
|
|
|
} |
|
530
|
|
|
|
|
|
|
} |
|
531
|
0
|
|
|
|
|
|
push( @t_funs_calls, $fun ); |
|
532
|
0
|
|
|
|
|
|
$fragment = ""; |
|
533
|
|
|
|
|
|
|
} |
|
534
|
0
|
|
|
|
|
|
while ( $ppfile =~ /(;)/g ) { |
|
535
|
0
|
|
|
|
|
|
push( @t_funs_calls, $1 ); |
|
536
|
|
|
|
|
|
|
} |
|
537
|
0
|
|
|
|
|
|
while ( $ppfile =~ /({)/g ) { |
|
538
|
0
|
|
|
|
|
|
$OpenCount++; |
|
539
|
0
|
|
|
|
|
|
push( @t_funs_calls, $1 ); |
|
540
|
|
|
|
|
|
|
} |
|
541
|
0
|
|
|
|
|
|
while ( $ppfile =~ /(})/g ) { |
|
542
|
0
|
|
|
|
|
|
$CloseCount++; |
|
543
|
0
|
|
|
|
|
|
push( @t_funs_calls, $1 ); |
|
544
|
|
|
|
|
|
|
} |
|
545
|
|
|
|
|
|
|
} |
|
546
|
0
|
|
|
|
|
|
return ( \@t_funs_calls ); |
|
547
|
|
|
|
|
|
|
} |
|
548
|
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
550
|
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
=head2 updateHashTable |
|
552
|
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
Usage : updateHashTable() |
|
554
|
|
|
|
|
|
|
Purpose : updates function wise calls hash table |
|
555
|
|
|
|
|
|
|
Returns : reference to hash table containing functions and calls |
|
556
|
|
|
|
|
|
|
Argument : None |
|
557
|
|
|
|
|
|
|
Throws : None |
|
558
|
|
|
|
|
|
|
Comment : None |
|
559
|
|
|
|
|
|
|
See Also : |
|
560
|
|
|
|
|
|
|
None |
|
561
|
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
=cut |
|
563
|
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
565
|
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
sub updateHashTable() { |
|
567
|
0
|
|
|
0
|
1
|
|
my $fun_calls = shift; |
|
568
|
0
|
|
|
|
|
|
my $OpenCount = 0; |
|
569
|
0
|
|
|
|
|
|
my $CloseCount = 0; |
|
570
|
0
|
|
|
|
|
|
my $function; |
|
571
|
0
|
|
|
|
|
|
my $FUNCTIONFOUND = 0; |
|
572
|
0
|
|
|
|
|
|
my $item = -1; |
|
573
|
0
|
|
|
|
|
|
my $titem; |
|
574
|
0
|
|
|
|
|
|
my $cnt1 = 0; |
|
575
|
0
|
|
|
|
|
|
my $call; |
|
576
|
|
|
|
|
|
|
my $fun_remain; |
|
577
|
|
|
|
|
|
|
|
|
578
|
0
|
|
|
|
|
|
foreach my $x (@$$fun_calls) { |
|
579
|
0
|
|
|
|
|
|
$item++; |
|
580
|
|
|
|
|
|
|
|
|
581
|
0
|
0
|
|
|
|
|
if ( $x eq "{" ) { |
|
582
|
0
|
|
|
|
|
|
$OpenCount++; |
|
583
|
|
|
|
|
|
|
} |
|
584
|
0
|
0
|
|
|
|
|
if ( $x eq "}" ) { |
|
585
|
0
|
|
|
|
|
|
$CloseCount++; |
|
586
|
|
|
|
|
|
|
} |
|
587
|
0
|
0
|
0
|
|
|
|
if ( !defined( @$$fun_calls[$item] ) |
|
588
|
|
|
|
|
|
|
|| !defined( @$$fun_calls[ $item + 1 ] ) ) |
|
589
|
|
|
|
|
|
|
{ |
|
590
|
0
|
|
|
|
|
|
next; |
|
591
|
|
|
|
|
|
|
} |
|
592
|
0
|
|
|
|
|
|
$titem = $item + 1; |
|
593
|
0
|
0
|
0
|
|
|
|
if ( ( @$$fun_calls[$item] =~ /(\w+.*)/ ) |
|
|
|
|
0
|
|
|
|
|
|
594
|
|
|
|
|
|
|
&& ( @$$fun_calls[ $item + 1 ] eq "{" ) |
|
595
|
|
|
|
|
|
|
&& ( $OpenCount == $CloseCount ) ) |
|
596
|
|
|
|
|
|
|
{ |
|
597
|
0
|
|
|
|
|
|
$function = $1; |
|
598
|
0
|
|
|
|
|
|
$function =~ /(\w+)\s*\(/; |
|
599
|
0
|
|
|
|
|
|
$function = $1; |
|
600
|
0
|
|
|
|
|
|
$function = trim($function); |
|
601
|
0
|
|
|
|
|
|
$fun_remain = $'; |
|
602
|
0
|
|
|
|
|
|
$fun_remain = "(" . $fun_remain; |
|
603
|
0
|
|
|
|
|
|
push( @{ $calls{$function} }, $fun_remain ); |
|
|
0
|
|
|
|
|
|
|
|
604
|
0
|
|
|
|
|
|
$FUNCTIONFOUND = 1; |
|
605
|
|
|
|
|
|
|
} |
|
606
|
0
|
0
|
0
|
|
|
|
if ( ( $FUNCTIONFOUND == 1 ) && ( $OpenCount != $CloseCount ) ) { |
|
607
|
0
|
0
|
0
|
|
|
|
if ( ( $x eq "{" ) || ( $x eq "}" ) || ( $x eq ";" ) ) { |
|
|
|
|
0
|
|
|
|
|
|
608
|
0
|
|
|
|
|
|
next; |
|
609
|
|
|
|
|
|
|
} |
|
610
|
|
|
|
|
|
|
else { |
|
611
|
0
|
|
|
|
|
|
$call = $x; |
|
612
|
0
|
|
|
|
|
|
push( @calls_table, $call ); |
|
613
|
0
|
|
|
|
|
|
$call = trim($call); |
|
614
|
0
|
0
|
|
|
|
|
if ( defined($call) ) { |
|
615
|
0
|
|
|
|
|
|
push( @{ $calls{$function} }, $call ); |
|
|
0
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
} |
|
617
|
|
|
|
|
|
|
} |
|
618
|
|
|
|
|
|
|
} |
|
619
|
|
|
|
|
|
|
} |
|
620
|
|
|
|
|
|
|
|
|
621
|
0
|
|
|
|
|
|
return; |
|
622
|
|
|
|
|
|
|
} |
|
623
|
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
625
|
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
=head2 trim |
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
Usage : trim() |
|
629
|
|
|
|
|
|
|
Purpose : trims leading and trailing white spaces in strings |
|
630
|
|
|
|
|
|
|
Returns : trimmed string |
|
631
|
|
|
|
|
|
|
Argument : string |
|
632
|
|
|
|
|
|
|
Throws : None |
|
633
|
|
|
|
|
|
|
Comment : None |
|
634
|
|
|
|
|
|
|
See Also : |
|
635
|
|
|
|
|
|
|
None |
|
636
|
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
=cut |
|
638
|
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
640
|
|
|
|
|
|
|
sub trim($) { |
|
641
|
0
|
|
|
0
|
1
|
|
my $string = shift; |
|
642
|
0
|
0
|
|
|
|
|
$string =~ s/^\s+// if defined($string); |
|
643
|
0
|
0
|
|
|
|
|
$string =~ s/\s+$// if defined($string); |
|
644
|
0
|
|
|
|
|
|
return $string; |
|
645
|
|
|
|
|
|
|
} |
|
646
|
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
648
|
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
=head2 clean |
|
650
|
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
Usage : clean() |
|
652
|
|
|
|
|
|
|
Purpose : safe exit |
|
653
|
|
|
|
|
|
|
Returns : none |
|
654
|
|
|
|
|
|
|
Argument : none |
|
655
|
|
|
|
|
|
|
Throws : None |
|
656
|
|
|
|
|
|
|
Comment : None |
|
657
|
|
|
|
|
|
|
See Also : |
|
658
|
|
|
|
|
|
|
None |
|
659
|
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
=cut |
|
661
|
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
663
|
|
|
|
|
|
|
sub clean() { |
|
664
|
0
|
|
|
0
|
1
|
|
%calls = (); |
|
665
|
0
|
|
|
|
|
|
@calls_table = (); |
|
666
|
0
|
|
|
|
|
|
@rec_track = (); |
|
667
|
0
|
|
|
|
|
|
return; |
|
668
|
|
|
|
|
|
|
} |
|
669
|
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
#################### subroutine header begin #################### |
|
671
|
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
=head2 progress_bar |
|
673
|
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
Usage : progress_bar() |
|
675
|
|
|
|
|
|
|
Purpose : simple and neat progress bar |
|
676
|
|
|
|
|
|
|
Returns : none |
|
677
|
|
|
|
|
|
|
Argument : none |
|
678
|
|
|
|
|
|
|
Throws : None |
|
679
|
|
|
|
|
|
|
Comment : None |
|
680
|
|
|
|
|
|
|
See Also : |
|
681
|
|
|
|
|
|
|
None |
|
682
|
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
=cut |
|
684
|
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
#################### subroutine header end #################### |
|
686
|
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
sub progress_bar { |
|
688
|
0
|
|
|
0
|
1
|
|
my ( $got, $total, $width, $char ) = @_; |
|
689
|
0
|
|
0
|
|
|
|
$width ||= 25; |
|
690
|
0
|
|
0
|
|
|
|
$char ||= '='; |
|
691
|
0
|
|
|
|
|
|
my $num_width = length $total; |
|
692
|
0
|
|
|
|
|
|
local $| = 1; |
|
693
|
0
|
|
|
|
|
|
printf "[%-${width}s] processed [%${num_width}s/%s] (%.2f%%)\r", |
|
694
|
|
|
|
|
|
|
$char x ( ( $width - 1 ) * $got / $total ) . '>', $got, $total, |
|
695
|
|
|
|
|
|
|
100 * $got / +$total; |
|
696
|
|
|
|
|
|
|
} |
|
697
|
|
|
|
|
|
|
#################### main pod documentation begin ################### |
|
698
|
|
|
|
|
|
|
## Below is the stub of documentation for your module. |
|
699
|
|
|
|
|
|
|
## You better edit it! |
|
700
|
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
=head1 NAME |
|
702
|
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
C::Analyzer - Generates C Call Control Flow tree for C source code |
|
704
|
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
706
|
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
use warnings; |
|
708
|
|
|
|
|
|
|
use strict; |
|
709
|
|
|
|
|
|
|
use C::Analyzer; |
|
710
|
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
my @functions = qw(afs_CheckServers afs_cv2string); |
|
712
|
|
|
|
|
|
|
my $analyzer = new Analyzer( |
|
713
|
|
|
|
|
|
|
_inputPath => "/home/foo", |
|
714
|
|
|
|
|
|
|
_cppPath => "/usr/local/bin", |
|
715
|
|
|
|
|
|
|
); |
|
716
|
|
|
|
|
|
|
$analyzer->init(); |
|
717
|
|
|
|
|
|
|
# "main" function taken if no parameter passed to this method. |
|
718
|
|
|
|
|
|
|
$analyzer->calltree( \@functions ); |
|
719
|
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
$analyzer->clean(); |
|
721
|
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
I |
|
723
|
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
725
|
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
Creates Call stack/tree of C source code |
|
727
|
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
=head2 GETTING HELP |
|
729
|
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
If you have questions about Analyzer you can get help from the I mailing list. You can get help |
|
731
|
|
|
|
|
|
|
on subscribing and using the list by emailing I. |
|
732
|
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
=head2 NOTES |
|
734
|
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
The Analyzer is evolving and there are plans to add more features, so it's good to have the latest copy. |
|
736
|
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
=head2 Architecture of Analyzer |
|
738
|
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
|-Input folder of C files-| |----Call Stack Output---| |
|
740
|
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
.------------------------. |
|
742
|
|
|
|
|
|
|
| 1. #include | .-. |
|
743
|
|
|
|
|
|
|
| 2. | .-------. |A| |
|
744
|
|
|
|
|
|
|
| 3. void main(void) | | Perl | |N| .------------------------. |
|
745
|
|
|
|
|
|
|
| 4. { | | script| |A| |A| |<0>main(3, a.c) | |
|
746
|
|
|
|
|
|
|
| 5. foo(); |-------| using |--|P|--|L|-------| <1>foo(5, a.c) | |
|
747
|
|
|
|
|
|
|
| 6. } | | API | |I| |Y| | <2>bar(10, a.c) | |
|
748
|
|
|
|
|
|
|
| 7. | |methods| |Z| `-----------------------/ |
|
749
|
|
|
|
|
|
|
| 8. int foo() | | | |E| |
|
750
|
|
|
|
|
|
|
| 9. { | `-------' |R| |
|
751
|
|
|
|
|
|
|
| 10. bar(); | `-' |
|
752
|
|
|
|
|
|
|
| 11. } | |
|
753
|
|
|
|
|
|
|
`-----------------------/ |
|
754
|
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
=head2 Outline Usage |
|
756
|
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
=head3 C |
|
758
|
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
Analyzer expects couple of mandatory inputs. One, folder that contains C/H files. Second, path for GNU C Preprocessor. |
|
760
|
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
for example: |
|
762
|
|
|
|
|
|
|
my $analyzer = new Analyzer( |
|
763
|
|
|
|
|
|
|
_inputPath => "/home/foo", |
|
764
|
|
|
|
|
|
|
_cppPath => "/usr/local/bin", |
|
765
|
|
|
|
|
|
|
); |
|
766
|
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
=head3 C |
|
768
|
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
Analyzer expects optional inputs as well. |
|
770
|
|
|
|
|
|
|
|
|
771
|
|
|
|
|
|
|
It allows directory and sub directory parsing. Default is directory processing. To tell analyzer module to recursively process |
|
772
|
|
|
|
|
|
|
C files in all directories and sub directories, use _inputOption |
|
773
|
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
for example: |
|
775
|
|
|
|
|
|
|
my $analyzer = new Analyzer( |
|
776
|
|
|
|
|
|
|
_inputPath => "/home/foo", |
|
777
|
|
|
|
|
|
|
_cppPath => "/usr/local/bin", |
|
778
|
|
|
|
|
|
|
_inputOption => "dir_and_subdir", |
|
779
|
|
|
|
|
|
|
); |
|
780
|
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
There is an option to provide additional GNU C Preprocessor options using "_cppOptions" |
|
782
|
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
for example: |
|
784
|
|
|
|
|
|
|
my $analyzer = new Analyzer( |
|
785
|
|
|
|
|
|
|
_inputPath => "/home/foo", |
|
786
|
|
|
|
|
|
|
_cppPath => "/usr/local/bin", |
|
787
|
|
|
|
|
|
|
_inputOption => "dir_and_subdir", |
|
788
|
|
|
|
|
|
|
_cppOptions => "-DMACRO1 -DMACRO2", |
|
789
|
|
|
|
|
|
|
); |
|
790
|
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
=head1 BUGS |
|
792
|
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
None. |
|
794
|
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
=head1 SUPPORT |
|
797
|
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
The Analyzer is free Open Source software. IT COMES WITHOUT WARRANTY OF ANY KIND. |
|
799
|
|
|
|
|
|
|
Please let me know if you could add more features for this module.I will be more than |
|
800
|
|
|
|
|
|
|
happy to add them. |
|
801
|
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
=head1 AUTHOR |
|
803
|
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
Sreekanth Kocharlakota |
|
805
|
|
|
|
|
|
|
CPAN ID: bmpOg |
|
806
|
|
|
|
|
|
|
Sreekanth Kocharlakota |
|
807
|
|
|
|
|
|
|
sreekanth@cpan.org |
|
808
|
|
|
|
|
|
|
http://www.languagesemantics.com |
|
809
|
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
=head1 COPYRIGHT |
|
811
|
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
The Analyzer module is Copyright (c) 1994-2007 Sreekanth Kocharlakota. USA. |
|
813
|
|
|
|
|
|
|
This program is free software licensed under the... |
|
814
|
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
The General Public License (GPL) |
|
816
|
|
|
|
|
|
|
Version 2, June 1991 |
|
817
|
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
The full text of the license can be found in the |
|
819
|
|
|
|
|
|
|
LICENSE file included with this module. |
|
820
|
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
823
|
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
perl(1). |
|
825
|
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
=cut |
|
827
|
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
#################### main pod documentation end ################### |
|
829
|
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
1; |
|
831
|
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
# The preceding line will help the module return a true value |
|
833
|
|
|
|
|
|
|
|