Restored work-around for hangs when trying to use disk-based handlers
[tangerine.git] / tools / cxref / contrib / fixheader.pl
blob261c431b30a1b0d1c3d6956ca7b25d73abe7daf7
1 #!/bin/sh
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.
15 exec perl -x $0 $*
17 exit 1
19 #!perl
21 # The verbose flag
22 $verbose=0;
24 # The output flag
25 $output=0;
27 # The compiler program.
28 $cc="gcc";
29 $cflags="-Wall -c";
31 # The cxref options.
32 $cxref_root=".";
33 $cxref_name="cxref";
34 $cxref_output=".";
36 # The C pre-processor arguments (-D, -I).
37 $cpp_args="";
39 # The files to check.
40 @files=();
43 # Parse the command line arguments
46 if( $#ARGV==-1 )
48 print "Usage: fixheader filename [filename ...] [-v] [-o]\n";
49 print " [-Odirname] [-Nbasename] [-Rdirname]\n";
50 print " [-Ddefine] [-Udefine] [-Iinclude]\n";
51 print "\n";
52 print "-v Output verbose information during the processing.\n";
53 print "-o Output a modified source file after testing.\n";
54 exit 0;
57 while ( $#ARGV >= 0 )
59 $_=$ARGV[0];
60 switch:
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.=" '".$_."'";
71 shift;
75 # The main program
78 foreach $file (@files)
80 # Initialise the headers
82 @cur_headers=&GetFileHeaders($file);
84 @all_headers=@cur_headers;
86 %use_headers=();
88 if($file =~ m/\.h$/)
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)
97 $h="" if($hh eq $h);
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",());
122 if($current>=0)
124 @all_headers=@cur_headers;
127 # Try all of the headers
129 if($file =~ m/\.h$/)
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);
134 else
136 $all=$current;
139 # Try removing headers
141 print "\nNow we try to remove unneeded headers\n" if($verbose);
143 tryagain:
145 ($remove,@remain_headers)=&TryRemovingHeaders($file,$all,@all_headers);
147 if(($all<0 && $all!=$remove) || $remove<$all)
149 $all=$remove;
150 @all_headers=@remain_headers;
151 print "\nWe need to try again now we have removed some problem headers\n" if($verbose);
152 goto tryagain;
155 # Print out a summary
157 print "\nSummary for $file\n\n";
159 $added="";
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);
170 print "\n";
175 # Get the included headers from an existing file.
178 sub GetFileHeaders
180 local($file)=@_;
181 local(@headers)=();
183 # Parse the file
185 open(IN,"<$file") || die "Cannot open the source file '$file'\n";
187 while(<IN>)
189 push(@headers,$1) if(m/^[ \t]*\#include ([<\"][^>\"]+[>\"])/);
192 close(IN);
194 return(@headers);
199 # Get the headers from the cxref database
202 sub GetCxrefHeaders
204 local(@headers)=();
205 local(%headers)=();
207 open(INC,"<$cxref_output/$cxref_name.include") || die "Cannot open the cxref database file '$cxref_output/$cxref_name.include'\n";
209 while(<INC>)
211 chop;
212 local($file,@heads)=split(" +");
214 foreach $h (@heads)
216 next if($headers{$h});
217 $headers{$h}=1;
219 if($h =~ m/^%/)
221 push(@headers,"\"".substr($h,1)."\"");
223 else
225 push(@headers,"<".$h.">");
230 close(INC);
232 return(@headers);
237 # Try removing them one at a time.
240 sub TryRemovingHeaders
242 local($file,$curr,@headers)=@_;
243 local($best)=$curr;
244 local(@best_headers)=();
246 foreach $header (reverse(@headers))
248 next if($use_headers{$header}==0 || $use_headers{$header}==2);
250 @try_headers=();
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))
270 $best=$try;
271 @best_headers=@try_headers;
275 return($best,@best_headers);
280 # Try the specified headers
283 sub TryTheseHeaders
285 local($file,$what,@these)=@_;
287 print " Trying $what .." if($verbose);
288 $result=&TryCompile($file,@these);
289 print " ($result)" if($verbose);
291 if($result>=0)
293 print " OK\n" if($verbose);
295 else
297 print " Failed\n" if($verbose);
300 return $result;
305 # Try compiling the file and see if it works.
308 sub TryCompile
310 local($file,@headers)=@_;
311 $length=0;
313 # Modify the file
315 $tmpfile=$file;
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);
328 while(<IN>)
330 next if(m/^[ \t]*\#include ([<\"][^>\"]+[>\"])/ && $use_headers{$1}!=1);
331 print OUT;
334 close(IN);
335 close(OUT);
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}'`);
343 unlink "$tmpfile";
344 unlink "$file.cxref-result";
346 $result=($result & 0xffff);
348 if($result)
349 {$length=-1-$length;}
351 return($length);
356 # Fixup the headers in the file.
359 sub FixupFile
361 local($file,$added)=@_;
363 # Modify the file
365 $newfile=$file;
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";
373 if($added)
375 (@added)=split(" ",$added);
377 foreach $h (@added)
379 printf OUT "#include %-30s /* Added by cxref */\n",$h;
382 print OUT "\n";
385 while(<IN>)
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);
392 else
394 print OUT;
398 close(IN);
399 close(OUT);