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
|
|
|
|
|
|
|
|