3 # C Cross Referencing & Documentation tool. Version 1.5.
5 # A Perl script to determine the required headers for source files.
7 # Written by Andrew M. Bishop
9 # This file Copyright 1999 Andrew M. Bishop
10 # It may be distributed under the GNU Public License, version 2, or
11 # any higher version. See section COPYING of the GNU Public license
12 # for conditions under which this file may be redistributed.
27 # The compiler program.
36 # The C pre-processor arguments (-D, -I).
43 # Parse the command line arguments
48 print
"Usage: fixheader filename [filename ...] [-v] [-o]\n";
49 print
" [-Odirname] [-Nbasename] [-Rdirname]\n";
50 print
" [-Ddefine] [-Udefine] [-Iinclude]\n";
52 print
"-v Output verbose information during the processing.\n";
53 print
"-o Output a modified source file after testing.\n";
62 $_ eq
'-v' && do { $verbose=1; last switch
;};
63 $_ eq
'-o' && do { $output=1; last switch
;};
64 m
/^
-R/ && die
"The -R option is not implemented\n";
65 m
/^
-N/ && do { if($_ eq
"-N") {shift; $cxref_name=$ARGV[0];} else {$cxref_name=substr
($_,2);} last switch
;};
66 m
/^
-O/ && do { if($_ eq
"-O") {shift; $cxref_output=$ARGV[0];} else {$cxref_output=substr
($_,2);} last switch
;};
67 -f $_ && do { push
(@files
,$_); last switch
;};
69 $cpp_args.
=" '".
$_.
"'";
78 foreach
$file (@files
)
80 # Initialise the headers
82 @cur_headers
=&GetFileHeaders
($file);
84 @all_headers
=@cur_headers
;
90 @cxref_headers
=&GetCxrefHeaders
();
92 foreach
$h (@cxref_headers
)
94 next
if($file eq substr
($h,1,length
($h)-2));
95 foreach
$hh (@all_headers
)
100 @all_headers
=(@all_headers
,$h) if($h =~ m
/^
\"/);
101 @all_headers
=($h,@all_headers
) if($h =~ m
/^\
</);
105 foreach
$header (@all_headers
)
107 $use_headers{$header}=3;
110 foreach
$header (@cur_headers
)
112 $use_headers{$header}=1;
115 # Test the file as it is now
117 print
"\nTesting file $file\n" if($verbose);
119 print
"\nWe need to know how well it works without changing it\n" if($verbose);
120 $current=&TryTheseHeaders
($file,"unchanged file",());
124 @all_headers
=@cur_headers
;
127 # Try all of the headers
131 print
"\nThis is a header file so we should try all possible headers\n" if($verbose);
132 $all=&TryTheseHeaders
($file,"all headers",@all_headers
);
139 # Try removing headers
141 print
"\nNow we try to remove unneeded headers\n" if($verbose);
145 ($remove,@remain_headers
)=&TryRemovingHeaders
($file,$all,@all_headers
);
147 if(($all<0 && $all!=$remove) ||
$remove<$all)
150 @all_headers
=@remain_headers
;
151 print
"\nWe need to try again now we have removed some problem headers\n" if($verbose);
155 # Print out a summary
157 print
"\nSummary for $file\n\n";
160 foreach
$header (@all_headers
)
162 print
" Removed: \#include $header\n" if($use_headers{$header}==0);
163 print
" Kept : \#include $header\n" if($use_headers{$header}==1);
164 print
" Added : \#include $header\n" if($use_headers{$header}==3);
165 $added.
=" $header" if($use_headers{$header}==3);
168 &FixupFile
($file,$added) if($output);
175 # Get the included headers from an existing file.
185 open
(IN
,"<$file") || die
"Cannot open the source file '$file'\n";
189 push
(@headers
,$1) if(m
/^
[ \t]*\
#include ([<\"][^>\"]+[>\"])/);
199 # Get the headers from the cxref database
207 open
(INC
,"<$cxref_output/$cxref_name.include") || die
"Cannot open the cxref database file '$cxref_output/$cxref_name.include'\n";
212 local($file,@heads
)=split(" +");
216 next
if($headers{$h});
221 push
(@headers
,"\"".substr
($h,1).
"\"");
225 push
(@headers
,"<".
$h.
">");
237 # Try removing them one at a time.
240 sub TryRemovingHeaders
242 local($file,$curr,@headers
)=@_
;
244 local(@best_headers
)=();
246 foreach
$header (reverse
(@headers
))
248 next
if($use_headers{$header}==0 ||
$use_headers{$header}==2);
252 foreach
$h (@headers
)
254 next
if($use_headers{$h}==0 ||
$use_headers{$h}==2);
255 push
(@try_headers
,$h) if($h ne
$header);
258 $use_head=$use_headers{$header};
259 $use_headers{$header}=-1;
260 $try=&TryTheseHeaders
($file,"to remove $header",@try_headers
);
261 $use_headers{$header}=$use_head;
263 if(($curr>=0 && $try>=0 && $try<=$curr) ||
($curr<0 && $try>=0))
265 $use_headers{$header}--;
268 if(($best>=0 && $try>=0 && $try<=$best) ||
($best<0 && $try>$best))
271 @best_headers
=@try_headers
;
275 return($best,@best_headers
);
280 # Try the specified headers
285 local($file,$what,@these
)=@_
;
287 print
" Trying $what .." if($verbose);
288 $result=&TryCompile
($file,@these
);
289 print
" ($result)" if($verbose);
293 print
" OK\n" if($verbose);
297 print
" Failed\n" if($verbose);
305 # Try compiling the file and see if it works.
310 local($file,@headers
)=@_
;
316 $tmpfile =~ s
/\.
([ch
])/.cxref.
$1.c
/;
318 die
"Cannot create temporary filename from name '$file'\n" if($file eq
$tmpfile);
320 open
(IN
,"<$file") || die
"Cannot open the source file '$file'\n";
321 open
(OUT
,">$tmpfile") || die
"Cannot create the temporary file '$tmpfile'\n";
323 foreach
$header (@headers
)
325 print OUT
"#include $header\n" if($use_headers{$header}==3);
330 next
if(m
/^
[ \t]*\
#include ([<\"][^>\"]+[>\"])/ && $use_headers{$1}!=1);
337 # Test the compilation
339 $result=system
"$cc $cflags $tmpfile -o /dev/null $cpp_args > $file.cxref-result 2>&1";
341 chop
($length=`wc -l $file.cxref-result | awk '{print \$1}'`);
344 unlink
"$file.cxref-result";
346 $result=($result & 0xffff);
349 {$length=-1-$length;}
356 # Fixup the headers in the file.
361 local($file,$added)=@_
;
366 $newfile =~ s
/\.
([ch
])/.cxref.
$1/;
368 die
"Cannot create temporary filename from name '$file'\n" if($file eq
$newfile);
370 open
(IN
,"<$file") || die
"Cannot open the source file '$file'\n";
371 open
(OUT
,">$newfile") || die
"Cannot create the output file '$newfile'\n";
375 (@added
)=split(" ",$added);
379 printf OUT
"#include %-30s /* Added by cxref */\n",$h;
387 if(m
/^
[ \t]*\
#include ([<\"][^>\"]+[>\"])(.*)$/)
389 printf OUT
"/* #include %-30s* Removed by cxref */ %s\n",$1,$2 if($use_headers{$1}==0);
390 print OUT
$_ if($use_headers{$1}==1);