File indexing completed on 2023-03-17 11:26:48
0001
0002 use File::Basename;
0003 use lib dirname($0);
0004 use Getopt::Long;
0005 use Digest::MD5 ;
0006 use SCRAMGenUtils;
0007 $|=1;
0008
0009 my $INSTALL_PATH = dirname($0);
0010 my $curdir=`/bin/pwd`; chomp $curdir;
0011 my $tmp_inc="includechecker/src";
0012 my $dummy_inc="dummy_include";
0013 my $config_cache={};
0014 my $cache_file="config_cache";
0015 my %extra_dummy_file;
0016 $extra_dummy_file{string}{"bits/stringfwd.h"}=1;
0017 $extra_dummy_file{stdexcept}{"exception"}=1;
0018 $config_cache->{COMPILER}="c++";
0019 $config_cache->{COMPILER_FLAGS}[0]="";
0020 $config_cache->{INCLUDE_FILTER}=".+";
0021 $config_cache->{OWNHEADER}[0]='^(.*?)\\.(cc|CC|cpp|C|c|CPP|cxx|CXX)$:"${1}\\.(h|hh|hpp|H|HH|HPP)\\$"';
0022 $config_cache->{FWDHEADER}{'^.*?(\\/|)[^\\/]*[Ff][Ww][Dd].h$'}=1;
0023 $config_cache->{FWDHEADER}{'^iosfwd$'}=1;
0024 $config_cache->{FWDHEADER}{'^bits\/stringfwd.h$'}=1;
0025 $config_cache->{HEADER_EXT}{"\\.(h||hh|hpp|H|HH|HPP)\$"}=1;
0026 $config_cache->{SOURCE_EXT}{"\\.(cc|CC|cpp|C|c|CPP|cxx|CXX)\$"}=1;
0027 $config_cache->{SKIP_INCLUDE_INDIRECT_ADD}={};
0028 $config_cache->{SKIP_INCLUDES}={};
0029 $config_cache->{LOCAL_HEADERS}{'^(.+)/[^/]+$:"$1/.+"'}=1;
0030 $SCRAMGenUtils::CacheType=1;
0031
0032 if(&GetOptions(
0033 "--config=s",\$config,
0034 "--tmpdir=s",\$tmp_dir,
0035 "--filter=s",\$filefilter,
0036 "--redo=s",\$redo,
0037 "--redoerr",\$redoerr,
0038 "--keep",\$keep,
0039 "--detail",\$detail,
0040 "--recursive",\$recursive,
0041 "--includeall",\$includeall,
0042 "--unique",\$unique,
0043 "--sysheader",\$system_header_skip,
0044 "--local",\$local_header_skip,
0045 "--skipheaders",\$skipheaders,
0046 "--help",\$help,
0047 ) eq ""){print "ERROR: Wrong arguments.\n"; &usage_msg();}
0048
0049 if(defined $help){&usage_msg();}
0050
0051 if ((!defined $config) || ($config=~/^\s*$/) || (!-f $config))
0052 {
0053 print "Error: Missing config file.\n";
0054 &usage_msg();
0055 }
0056
0057 if(defined $unique){$unique=1;}
0058 else{$unique=0;}
0059
0060 if(defined $redoerr){$redoerr=1;}
0061 else{$redoerr=0;}
0062
0063 if(defined $system_header_skip){$system_header_skip=0;}
0064 else{$system_header_skip=1;}
0065
0066 if(defined $local_header_skip){$local_header_skip=0;}
0067 else{$local_header_skip=1;}
0068
0069 if(defined $includeall){$includeall=1;}
0070 else{$includeall=0;}
0071
0072 if(defined $detail){$detail=1;}
0073 else{$detail=0;}
0074
0075 if(defined $skipheaders){$skipheaders=1;}
0076 else{$skipheaders=0;}
0077
0078 if(defined $recursive){$recursive=1;}
0079 else{$recursive=0;}
0080
0081 if((!defined $filefilter) || ($filefilter=~/^\s*$/)){$filefilter="";}
0082
0083 if((!defined $redo) || ($redo=~/^\s*$/)){$redo="";}
0084
0085 if(!defined $keep){$keep=0;}
0086 else{$keep=1;}
0087
0088 if ((!defined $tmp_dir) || ($tmp_dir=~/^\s*$/)) {$tmp_dir="/tmp/delete_me_includechecker_$$";}
0089 else
0090 {
0091 if($tmp_dir=~/^[^\/]/){$tmp_dir=&SCRAMGenUtils::fixPath("${curdir}/${tmp_dir}");}
0092 $keep=1;
0093 }
0094
0095 system("mkdir -p ${tmp_dir}/backup/files ${tmp_dir}/backup/ids");
0096 print "TMP directory:$tmp_dir\n";
0097 &init ($config);
0098 chdir($tmp_dir);
0099 if($filefilter eq ""){$filefilter=".+";}
0100 print "MSG: Skipping system headers check:$system_header_skip\n";
0101
0102 foreach my $f (sort(keys %{$config_cache->{FILES}}))
0103 {
0104 &check_file($f);
0105 if (-f "${tmp_dir}/quit"){system("rm -f ${tmp_dir}/quit; touch ${tmp_dir}/chkquit");last;}
0106 }
0107 &final_exit();
0108
0109 sub find_file ()
0110 {
0111 my $file=shift;
0112 foreach my $b (@{$config_cache->{BASE_DIR_ORDERED}})
0113 {if (-f "${b}/${file}"){return $b;}}
0114 return "";
0115 }
0116
0117 sub check_includes ()
0118 {
0119 my $srcfile=shift;
0120 my $cache=shift;
0121 my $origfile=$cache->{original};
0122 my $base_dir=$config_cache->{FILES}{$origfile}{BASE_DIR};
0123 my $origrel_dir=&SCRAMGenUtils::fixPath(dirname($origfile));
0124 my $orig_dir="${base_dir}/${origrel_dir}";
0125 my $filter=$config_cache->{INCLUDE_FILTER};
0126 &read_file ("${base_dir}/${origfile}", $cache);
0127
0128 my $total_inc=scalar(@{$cache->{includes}});
0129 my $inc_added=0;
0130 my $actual_inc_added=0;
0131 my $inc_removed=0;
0132
0133 my $skip=1;
0134 if(($total_inc+$cache->{incsafe}) < $cache->{code_lines}){$skip=&is_skipped($origfile);}
0135 $config_cache->{FILES}{$origfile}{INTERNAL_SKIP}=$skip;
0136
0137 for(my $i=0; $i<$total_inc; $i++)
0138 {$config_cache->{FILES}{$origfile}{INCLUDES}{$cache->{includes}[$i]}=$cache->{includes_line}[$i];}
0139
0140 my $inc_type="ALL_INCLUDES_REMOVED";
0141 my $skip_add=&match_data($origfile,"SKIP_AND_ADD_REMOVED_INCLUDES");
0142 my $skip_add_mod=0;
0143 if($includeall && !$skip_add){$inc_type="ALL_INCLUDES";}
0144 my $otype ="${inc_type}_ORDERED";
0145 $cache->{msglog}=[];
0146 for(my $i=0; $i<$total_inc; $i++)
0147 {
0148 my $inc_file=$cache->{includes}[$i];
0149 my $inc_line=$cache->{includes_line}[$i];
0150 my $b="";
0151 if (exists $config_cache->{FILES}{$inc_file})
0152 {$b=$config_cache->{FILES}{$inc_file}{BASE_DIR};}
0153 elsif(-f "${orig_dir}/${inc_file}")
0154 {
0155 $b=$base_dir;
0156 if($origrel_dir ne ".")
0157 {
0158 my $pinc=$inc_file;
0159 $inc_file=&SCRAMGenUtils::fixPath("${origrel_dir}/${pinc}");
0160 $inc_line=~s/$pinc/${inc_file}/;
0161 $cache->{includes}[$i]=$inc_file;
0162 $cache->{includes_line}[$i]=$inc_line;
0163 $config_cache->{FILES}{$origfile}{INCLUDES}{$inc_file}=$inc_line;
0164 delete $config_cache->{FILES}{$origfile}{INCLUDES}{$pinc};
0165 if($detail){push @{$cache->{msglog}},"MSG: Private header $pinc in $origfile file.($inc_file : $inc_line)\n";}
0166 }
0167 }
0168 else{$b=&find_file ($inc_file);}
0169
0170 my $inc_skip = $skipheaders || &is_skipped($inc_file);
0171 if(!$inc_skip)
0172 {
0173 if($inc_file!~/$filter/){$inc_skip=1;}
0174 elsif(!$recursive && !exists $config_cache->{FILES}{$inc_file})
0175 {
0176 my $fd=dirname($inc_file);
0177 if($fd ne $origrel_dir){$inc_skip=1;}
0178 }
0179 }
0180 if ($b ne "")
0181 {
0182 if (!exists $config_cache->{FILES}{$inc_file})
0183 {
0184 if(($inc_skip==0) && &should_skip("${b}/${inc_file}")){$config_cache->{SKIP_FILES}{$inc_file}=1;$inc_skip=1;}
0185 $config_cache->{FILES}{$inc_file}{COMPILER_FLAGS_INDEX}=$config_cache->{FILES}{$origfile}{COMPILER_FLAGS_INDEX};
0186 $config_cache->{FILES}{$inc_file}{BASE_DIR}=$b;
0187 }
0188 $config_cache->{FILES}{$inc_file}{INTERNAL_SKIP}=$inc_skip;
0189 &check_file($inc_file);
0190 $inc_skip=$config_cache->{FILES}{$inc_file}{INTERNAL_SKIP};
0191 my $num=$cache->{includes_line_number}[$i];
0192 my $cur_total = scalar(@{$cache->{includes}});
0193 if($includeall)
0194 {
0195 foreach my $inc (@{$config_cache->{FILES}{$inc_file}{ALL_INCLUDES_ORDERED}})
0196 {
0197 if(&is_skipped_inc_add($origfile,$inc)){next;}
0198 my $l=$config_cache->{FILES}{$inc_file}{ALL_INCLUDES}{$inc};
0199 if(!exists $config_cache->{FILES}{$origfile}{ALL_INCLUDES}{$inc})
0200 {
0201 push @{$config_cache->{FILES}{$origfile}{ALL_INCLUDES_ORDERED}}, $inc;
0202 $config_cache->{FILES}{$origfile}{ALL_INCLUDES}{$inc}=$l;
0203 }
0204 }
0205 if(!exists $config_cache->{FILES}{$origfile}{ALL_INCLUDES}{$inc_file})
0206 {
0207 push @{$config_cache->{FILES}{$origfile}{ALL_INCLUDES_ORDERED}}, $inc_file;
0208 $config_cache->{FILES}{$origfile}{ALL_INCLUDES}{$inc_file}=$inc_line;
0209 }
0210 }
0211 if($skip)
0212 {
0213 foreach my $inc (@{$config_cache->{FILES}{$inc_file}{ALL_INCLUDES_REMOVED_ORDERED}})
0214 {
0215 if(&is_skipped_inc_add($origfile,$inc)){next;}
0216 my $l=$config_cache->{FILES}{$inc_file}{ALL_INCLUDES_REMOVED}{$inc};
0217 if(!exists $config_cache->{FILES}{$origfile}{ALL_INCLUDES_REMOVED}{$inc})
0218 {
0219 push @{$config_cache->{FILES}{$origfile}{ALL_INCLUDES_REMOVED_ORDERED}}, $inc;
0220 $config_cache->{FILES}{$origfile}{ALL_INCLUDES_REMOVED}{$inc}=$l;
0221 }
0222 }
0223 if(!$skip_add){next;}
0224 }
0225 foreach my $inc (@{$config_cache->{FILES}{$inc_file}{$otype}})
0226 {
0227 if(&is_skipped_inc_add($origfile,$inc,)){next;}
0228 my $l=$config_cache->{FILES}{$inc_file}{$inc_type}{$inc};
0229 if(exists $config_cache->{FILES}{$inc_file}{ALL_INCLUDES_REMOVED}{$inc})
0230 {$config_cache->{FILES}{$origfile}{INCLUDE_REMOVED_INDIRECT}{$inc}=1;}
0231
0232 if(exists $config_cache->{FILES}{$origfile}{INCLUDES}{$inc}){next;}
0233 for(my $j=$i+1; $j<$total_inc; $j++)
0234 {$cache->{includes_line_number}[$j]++;}
0235 push @{$cache->{includes}}, $inc;
0236 push @{$cache->{includes_line}}, $l;
0237 if ($inc_skip)
0238 {
0239 push @{$cache->{includes_line_number}}, $num;
0240 $cache->{includes_line_number}[$i]++;
0241 &add_include ($srcfile, $num-1, $l);
0242 }
0243 else
0244 {
0245 push @{$cache->{includes_line_number}}, $num+1;
0246 &add_include ($srcfile, $num, $l);
0247 }
0248 if($detail){push @{$cache->{msglog}},"Added \"$inc\" in \"$origfile\". Removed/included in \"$inc_file\"\n";}
0249 $skip_add_mod=1;
0250 $num++;
0251 $cur_total++;
0252 $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT}{$inc}=1;
0253 $config_cache->{FILES}{$origfile}{INCLUDES}{$inc}=$l;
0254 $inc_added++;
0255 }
0256 }
0257 elsif($includeall && !exists $config_cache->{FILES}{$origfile}{ALL_INCLUDES}{$inc_file})
0258 {
0259 push @{$config_cache->{FILES}{$origfile}{ALL_INCLUDES_ORDERED}}, $inc_file;
0260 $config_cache->{FILES}{$origfile}{ALL_INCLUDES}{$inc_file}=$inc_line;
0261 }
0262 }
0263 if($detail){foreach my $f (@{$cache->{msglog}}){print "$f";}}
0264 delete $cache->{msglog};
0265 print "#################################################\n";
0266 print "File: $origfile\n";
0267 print " Total lines : ".$cache->{total_lines}."\n";
0268 print " Code lines : ".$cache->{code_lines}."\n";
0269 print " Commented lines : ".$cache->{comments_lines}."\n";
0270 print " Empty lines : ".$cache->{empty_lines}."\n";
0271 print " Number of includes : ".$total_inc."\n";
0272 print " Additional Includes : ".$inc_added."\n\n";
0273 $config_cache->{FILES}{$origfile}{ERROR}=0;
0274 if($skip)
0275 {
0276 if($detail){print "SKIPPED:$origfile\n";}
0277 if($skip_add && $skip_add_mod){&movenewfile($srcfile, $origfile,$orig_dir);}
0278 return;
0279 }
0280
0281 my $stime=time;
0282 my $oflags=$config_cache->{COMPILER_FLAGS}[$config_cache->{FILES}{$origfile}{COMPILER_FLAGS_INDEX}];
0283 my $compiler=$config_cache->{COMPILER};
0284 my $xincshash={};
0285 my $error=0;
0286 my $flags="-shared -fsyntax-only -I${orig_dir} $oflags";
0287 my @origwarns=`$compiler -MMD $flags -o ${srcfile}.o $srcfile 2>&1`;
0288 if ($? != 0){$error=1;}
0289 elsif(-f "${srcfile}.d")
0290 {
0291 my $inc_cache=&read_mmd("${srcfile}.d");
0292 foreach my $inc (@$inc_cache)
0293 {
0294 if($inc=~/^\/.+$/)
0295 {
0296 my $d=dirname($inc);
0297 if(!exists $xincshash->{$d}){$xincshash->{$d}=1;}
0298 }
0299 }
0300 }
0301 my $origwarns_count=scalar(@origwarns);
0302 foreach my $warn (@origwarns)
0303 {chomp $warn;$warn=~s/$srcfile/${base_dir}\/${origfile}/g;}
0304
0305 $total_inc=scalar(@{$cache->{includes}});
0306 if($detail && (exists $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT}))
0307 {
0308 if($includeall)
0309 {print "Following files are added (because those were removed or indirectly added from included headers) ";}
0310 else{print "Following files are added (because those were removed from included headers)";}
0311 print "inorder to make the compilation work.\n";
0312 foreach my $f (keys %{$config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT}})
0313 {print " $f\n";}
0314 print "\n";
0315 }
0316 if ($error)
0317 {
0318 print "File should be compiled without errors.\n";
0319 print "Compilation errors are:\n";
0320 foreach my $w (@origwarns){print "$w\n";}
0321 print "\nCompilation might be failed due to the fact that this file\n";
0322 print "is not self parsed";
0323 if (exists $config_cache->{FILES}{$origfile}{INCLUDE_REMOVED_INDIRECT})
0324 {
0325 print " OR due to removal of some header from other files.\n";
0326 print "Header files removed from other headers are:\n";
0327 foreach my $f (keys %{$config_cache->{FILES}{$origfile}{INCLUDE_REMOVED_INDIRECT}})
0328 {print " $f\n";}
0329 if (exists $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT})
0330 {
0331 print "\nBut following headers are included again in $origfile:\n";
0332 foreach my $f (keys %{$config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT}})
0333 {print " $f\n";}
0334 print "It might be possible that header file include order is causing the problem.\n";
0335 print "Or there is really an error in your $origfile file (might be not self parsed).\n";
0336 }
0337 }
0338 else{print ".\n";}
0339 delete $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT};
0340 delete $config_cache->{FILES}{$origfile}{INCLUDE_REMOVED_INDIRECT};
0341 $config_cache->{FILES}{$origfile}{ERROR}=1;
0342 return;
0343 }
0344 if(-f "${srcfile}.o"){system("rm -f ${srcfile}.o");}
0345 delete $config_cache->{FILES}{$origfile}{INCLUDE_REMOVED_INDIRECT};
0346
0347 my $own_header="";
0348 if (!$cache->{isheader})
0349 {
0350 foreach my $exp (@{$config_cache->{OWNHEADER}})
0351 {
0352 my ($fil,$fil2)=split /:/,$exp;
0353 my $h=$origfile;
0354 if($h=~/$fil/)
0355 {$h=eval $fil2;}
0356 for(my $i=0; $i < $total_inc; $i++)
0357 {
0358 my $f=$cache->{includes}[$i];
0359 if ($f=~/$h/)
0360 {$own_header=$f;last;}
0361 }
0362 if($own_header){print "OWNHEADER: $origfile => $own_header\n";last;}
0363 }
0364 }
0365 if($detail && $origwarns_count>0)
0366 {
0367 print "---------------- $origfile: ORIGINAL WARNINGS -------------------\n";
0368 foreach my $w (@origwarns){print "$w\n";}
0369 print "---------------- $origfile: ORIGINAL WARNINGS : DONE ------------\n";
0370 }
0371
0372 my $num = -1;
0373 my $fwdcheck=0;
0374 `$compiler -M $flags -o ${srcfile}.d $srcfile 2>&1`;
0375 my $origincpath=&find_incs_in_deps("${srcfile}.d",$config_cache->{FILES}{$origfile}{INCLUDES});
0376 my $minc={};
0377 while(1)
0378 {
0379 my $i=&find_next_index ($cache, $num, $fwdcheck);
0380 if ($i==-1)
0381 {
0382 if($fwdcheck==1){last;}
0383 else{$fwdcheck=1;$num=-1;next;}
0384 }
0385 $num = $cache->{includes_line_number}[$i];
0386 my $inc_file=$cache->{includes}[$i];
0387 my $inc_line=$cache->{includes_line}[$i];
0388
0389 if ($inc_file eq $own_header)
0390 {if($detail){print " Skipped checking of \"$inc_file\" (Assumption: .cc always needs its own .h)\n";} next;}
0391 if ((!exists $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT}) ||
0392 (!exists $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT}{$inc_file}))
0393 {
0394 if (exists $config_cache->{SKIP_ORIG_INCLUDES})
0395 {
0396 my $next=0;
0397 foreach my $exp (keys %{$config_cache->{SKIP_ORIG_INCLUDES}})
0398 {
0399 if($origfile=~/$exp/)
0400 {
0401 if($detail){print " Skipped checking of \"$inc_file\" in \"$origfile\" due to SKIP_ORIG_INCLUDES flag in the config file\n";}
0402 $next=1;
0403 last;
0404 }
0405 }
0406 if($next){next;}
0407 }
0408 if (&skip_self_include($origfile,$inc_file))
0409 {if($detail){print " Skipped checking of \"$inc_file\" in \"$origfile\" due to SKIP_SELF_INCLUDES flag in the config file\n";} next;}
0410 }
0411 if(&skip_include($origfile,$inc_file))
0412 {if($detail){print " Skipped checking of \"$inc_file\" in \"$origfile\" due to SKIP_INCLUDES flag in the config file\n";} next;}
0413
0414 my $force_inc_remove=0;
0415 my $exists_in_own_header=0;
0416 my $is_sys_header=0;
0417 my $inc_fpath="";
0418 if (($own_header ne "") &&
0419 (exists $config_cache->{FILES}{$own_header}) &&
0420 (exists $config_cache->{FILES}{$own_header}{INCLUDES}{$inc_file}))
0421 {$exists_in_own_header=1;$force_inc_remove=1;}
0422 else
0423 {
0424 $inc_fpath=$origincpath->{$inc_file};
0425 if(!$inc_fpath){print "ERROR: Could not find full include path for \"$inc_file\" from \"$origfile\"\n";}
0426 $is_sys_header=&is_system_header($inc_fpath,$xincshash);
0427 if ($is_sys_header)
0428 {
0429 if($system_header_skip)
0430 {
0431 if(!exists $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT} ||
0432 !exists $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT}{$inc_file})
0433 {if($detail){print " Skipped checking of \"$inc_file\" in \"$origfile\" due to SYSTEM HEADERS\n";} next;}
0434 else{$force_inc_remove=1; print " FORCED REMOVED(System header indirectly added):$origfile:$inc_file\n";}
0435 }
0436 }
0437 elsif ($local_header_skip)
0438 {
0439 if(&is_local_header($origfile,$inc_file))
0440 {
0441 if(!exists $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT} ||
0442 !exists $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT}{$inc_file})
0443 {if($detail){print " Skipped checking of \"$inc_file\" in \"$origfile\" due to LOCAL HEADERS SKIP\n";} next;}
0444 }
0445 }
0446 }
0447
0448 &comment_line ($srcfile, $num);
0449 if (exists $minc->{$inc_file})
0450 {
0451 print " Skipped checking of \"$inc_file\" in \"$origfile\" due to MULTIPLE INCLUDE STATEMENTS\n";
0452 $force_inc_remove=1;
0453 }
0454 else{$minc->{$inc_file}=1;}
0455 my $loop=2;
0456 if($force_inc_remove){$loop=0;}
0457 elsif($unique){$loop=1;}
0458 my @warns=();
0459 my $inc_req=0;
0460 my $process_flag=0;
0461 for(my $x=0;$x<$loop;$x++)
0462 {
0463 @warns=();
0464 system("rm -f ${srcfile}.o ${srcfile}.d");
0465 $flags="-MD -shared -fsyntax-only -I${tmp_dir}/${dummy_inc} -I${orig_dir} $oflags";
0466 @warns=`$compiler $flags -o ${srcfile}.o $srcfile 2>&1`;
0467 my $ret_val=$?;
0468 if($x==1)
0469 {
0470 my $c=&find_inc_in_deps("${srcfile}.d",$inc_file);
0471 if ($detail){print "INCLUDE PICK UP $x: $inc_file:",join(",",keys %$c),"\n";}
0472 }
0473 foreach my $w (@warns)
0474 {chomp $w;$w=~s/$srcfile/${base_dir}\/${origfile}/;}
0475 my $nwcount=scalar(@warns);
0476 if($detail)
0477 {
0478 print "---------- $origfile : ACTUAL WARN/ERRORS AFTER REMOVING $inc_file (iteration: $x) ----------\n";
0479 foreach my $w (@warns){print "$w\n";}
0480 print "---------- $origfile : ACTUAL WARN/ERRORS AFTER REMOVING $inc_file (iteration: $x) DONE -----\n";
0481 }
0482 if ($ret_val != 0)
0483 {
0484 if($x==0){$inc_req=1;}
0485 else
0486 {
0487 my $sf="${base_dir}/${origfile}";
0488 foreach my $w (@warns)
0489 {
0490 foreach my $ow (@origwarns){if("$ow" eq "$w"){$w="";$ow="";last;}}
0491 if($w)
0492 {
0493 if($w=~/^\s*$sf:\d+:\s*/)
0494 {
0495 if($w!~/\s+instantiated from here\s*$/)
0496 {$inc_req=1; last;}
0497 }
0498 elsif($w=~/^.+?:\d+:\s+confused by earlier errors/)
0499 {$inc_req=1;last;}
0500 }
0501 }
0502 }
0503 }
0504 elsif ($origwarns_count == scalar(@warns))
0505 {
0506 for(my $j=0; $j<$origwarns_count; $j++)
0507 {if ("$warns[$j]" ne "$origwarns[$j]"){$inc_req=1;last;}}
0508 }
0509 else{$inc_req=1;}
0510 if($inc_req || $unique){last;}
0511 elsif($x==0)
0512 {
0513 my $c=&find_inc_in_deps("${srcfile}.d",$inc_file);
0514 my $icount=scalar(keys %$c);
0515 if($icount==0){last;}
0516 if ($detail){print "INCLUDE PICK UP $x: $inc_file:",join(",",keys %$c),"\n";}
0517 if ($is_sys_header){&createdummyfile($config_cache->{FILES}{$origfile},$inc_file);}
0518 else{&createbackup($inc_fpath);}
0519 }
0520 }
0521 if($is_sys_header){&cleanupdummydir();}
0522 else{&recoverbackup($inc_fpath);}
0523
0524 if($inc_req==0)
0525 {
0526 if($unique){delete $minc->{$inc_file};}
0527 system("rm -f ${srcfile}.backup");
0528 $inc_removed++;
0529 if($detail || !exists $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT} ||
0530 !exists $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT}{$inc_file})
0531 {
0532 print " Checking \"$inc_file\" at line number \"$num\" ..... [ Not required ";
0533 if ($exists_in_own_header)
0534 {print "(Exists in its own header) ]\n";}
0535 else{print "]\n";}
0536 }
0537
0538 if (!exists $config_cache->{FILES}{$origfile}{ALL_INCLUDES_REMOVED}{$inc_file})
0539 {
0540 push @{$config_cache->{FILES}{$origfile}{ALL_INCLUDES_REMOVED_ORDERED}}, $inc_file;
0541 $config_cache->{FILES}{$origfile}{ALL_INCLUDES_REMOVED}{$inc_file}=$inc_line;
0542 }
0543 delete $config_cache->{FILES}{$origfile}{INCLUDES}{$inc_file};
0544 }
0545 else
0546 {
0547 system("mv ${srcfile}.backup $srcfile");
0548 my $extra=0;
0549 if (exists $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT})
0550 {
0551 if(exists $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT}{$inc_file})
0552 {$extra=1;}
0553 }
0554 if ($extra)
0555 {print " Checking \"$inc_file\" at line number \"$num\" ..... [ Required (ADD) ]\n";$actual_inc_added++;}
0556 elsif($detail)
0557 {print " Checking \"$inc_file\" at line number \"$num\" ..... [ Required ]\n";}
0558 }
0559 system("rm -f ${srcfile}.o ${srcfile}.d");
0560 }
0561 system("grep -v \"//INCLUDECHECKER: Removed this line:.*//INCLUDECHECKER: Added this line\" $srcfile > ${srcfile}.new");
0562 my $diff=`diff ${srcfile}.new ${base_dir}/${origfile}`; chomp $diff;
0563 if ($diff ne ""){&movenewfile("${srcfile}.new", $origfile,$orig_dir);}
0564 print "\n";
0565 print " Include added : ".$inc_added."\n";
0566 print " Include removed : ".$inc_removed."\n";
0567 print " Actual include added : ".$actual_inc_added."\n";
0568 print " Actual include removed : ",$inc_removed-$inc_added+$actual_inc_added,"\n";
0569 my $dtime=time-$stime;
0570 print " Processing time(sec) : ".$dtime."\n";
0571 delete $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT};
0572 }
0573
0574 sub movenewfile ()
0575 {
0576 my $nfile=shift;
0577 my $file=shift;
0578 my $odir=shift;
0579 my $dir=dirname($file);
0580 my $name=basename($file);
0581 $dir="${tmp_dir}/${tmp_inc}/${dir}";
0582 system("mkdir -p $dir; rm -f ${dir}/${name}; cp $nfile ${dir}/${name}");
0583 if(!-f "${odir}/${name}.original_file_wo_incchk_changes"){system("cp ${odir}/${name} ${odir}/${name}.original_file_wo_incchk_changes");}
0584 system("mv $nfile ${odir}/${name}");
0585 }
0586
0587 sub islocalinc ()
0588 {
0589 my $cache=shift;
0590 my $inc=shift;
0591 if(!exists $cache->{INCLUDE_ADDED_INDIRECT} ||
0592 !exists $cache->{INCLUDE_ADDED_INDIRECT}{$inc})
0593 {return 1;}
0594 return 0;
0595 }
0596
0597 sub createdummyfile ()
0598 {
0599 my $cache=shift;
0600 my $file=shift;
0601 my $extra_only=shift || 0;
0602 if(!$extra_only)
0603 {&createdummyfile1 ($file);}
0604 if(exists $extra_dummy_file{$file})
0605 {
0606 foreach my $f (keys %{$extra_dummy_file{$file}})
0607 {
0608 if(!exists $cache->{INCLUDES}{$f})
0609 {&createdummyfile ($cache,$f);}
0610 }
0611 }
0612 }
0613
0614 sub createbackup()
0615 {
0616 my $file=shift;
0617 my $id=&md5_hex ($file);
0618 if (-f "${tmp_dir}/backup/files/${id}"){return;}
0619 system("echo \"$file\" > ${tmp_dir}/backup/ids/$id && mv $file ${tmp_dir}/backup/files/${id} && touch $file");
0620 }
0621
0622 sub recoverbackup ()
0623 {
0624 my $file=shift;
0625 my $id=shift || &md5_hex ($file);
0626 if (-f "${tmp_dir}/backup/files/${id}")
0627 {system("mv ${tmp_dir}/backup/files/${id} $file");}
0628 system("rm -f ${tmp_dir}/backup/ids/$id ${tmp_dir}/backup/files/${id}");
0629 }
0630
0631 sub createdummyfile1 ()
0632 {
0633 my $file=shift;
0634 my $dir="${tmp_dir}/${dummy_inc}/".dirname($file);
0635 my $file1=basename($file);
0636 system("mkdir -p $dir; touch ${dir}/${file1}");
0637 }
0638
0639 sub cleanupdummydir()
0640 {
0641 system("rm -rf ${tmp_dir}/${dummy_inc}/* 2>&1 > /dev/null");
0642 }
0643
0644 sub is_system_header ()
0645 {
0646 my $file=shift;
0647 my $cache=shift;
0648 if($file=~/^${tmp_dir}\/${tmp_inc}\/.+/){return 0;}
0649 foreach my $d (@{$config_cache->{BASE_DIR_ORDERED}})
0650 {if($file=~/^$d\/.+/){return 0;}}
0651 foreach my $d (keys %$cache)
0652 {
0653 my $d1=$d;
0654 $d1=~s/\+/\\\+/g;
0655 if($file=~/^$d1\/.+/){return 0;}
0656 }
0657 return 1;
0658 }
0659
0660 sub find_inc_in_deps ()
0661 {
0662 my $file=shift;
0663 my $inc=shift;
0664 my $paths={};
0665 if(!-f "$file"){return $paths;}
0666 $inc=~s/\+/\\\+/g;
0667 my $lines=&read_mmd($file);
0668 foreach my $line (@$lines)
0669 {if($line=~/^(.+?\/$inc)$/){$paths->{$1}=1;}}
0670 return $paths;
0671 }
0672
0673 sub find_incs_in_deps ()
0674 {
0675 my $file=shift;
0676 my $cache=shift;
0677 my $paths={};
0678 if(!-f "$file"){return $paths;}
0679 my %incs=();
0680 my $hasinc=0;
0681 foreach my $inc (keys %$cache)
0682 {
0683 my $xinc=$inc;
0684 $xinc=~s/\+/\\\+/g;
0685 $incs{$xinc}=$inc;
0686 $hasinc++;
0687 }
0688 if(!$hasinc){return $paths;}
0689 my $lines=&read_mmd($file);
0690 foreach my $line (@$lines)
0691 {
0692 foreach my $xinc (keys %incs)
0693 {
0694 if($line=~/^\s*(.+?\/$xinc)$/)
0695 {$paths->{$incs{$xinc}}=$line;delete $incs{$xinc};$hasinc--;last;}
0696 }
0697 if(!$hasinc){return $paths;}
0698 }
0699 if($hasinc)
0700 {
0701 print "MSG: Could not find the following includes:\n";
0702 foreach my $inc (keys %incs){print " ",$incs{$inc},"\n";}
0703 }
0704 return $paths;
0705 }
0706
0707 sub find_next_index ()
0708 {
0709 my $cache=shift;
0710 my $prev=shift;
0711 my $fwdcheck=shift || 0;
0712 if(!defined $prev){$prev=-1;}
0713 my $count=scalar(@{$cache->{includes_line_number}});
0714 my $next=345435434534;
0715 my $index=-1;
0716 for(my $i=0; $i<$count;$i++)
0717 {
0718 my $inc=$cache->{includes}[$i];
0719 my $isfwd=0;
0720 foreach my $fwd (keys %{$config_cache->{FWDHEADER}})
0721 {if($inc=~/$fwd/){$isfwd=1; last;}}
0722 if($fwdcheck==1)
0723 {if(!$isfwd){next;}}
0724 elsif($isfwd){next;}
0725 my $j=$cache->{includes_line_number}[$i];
0726 if (($j>$prev) && ($j<$next)){$next=$j;$index=$i;}
0727 }
0728 return $index;
0729 }
0730
0731 sub read_mmd()
0732 {
0733 my $file=shift;
0734 my $cache=[];
0735 if(!open(MMDFILE,$file)){die "Can not open \"$file\" for reading.";}
0736 while(my $line=<MMDFILE>)
0737 {
0738 chomp $line;
0739 $line=~s/\s*(\\|)$//;$xline=~s/^\s*//;
0740 if($line=~/:$/){next;}
0741 foreach my $l (split /\s+/,$line)
0742 {push @$cache,$l;}
0743 }
0744 close(MMDFILE);
0745 return $cache;
0746 }
0747
0748 sub check_cyclic ()
0749 {
0750 my $file=shift;
0751 my $key=shift || "INC_LIST";
0752 my $msg="";
0753 my $depth = scalar(@{$config_cache->{$key}});
0754 if ($depth > 0)
0755 {
0756 for(my $i=0; $i<$depth; $i++)
0757 {
0758 if($config_cache->{$key}[$i] eq $file)
0759 {
0760 my $msg="";
0761 for(my $j=$i; $j<$depth;$j++)
0762 {$msg.=$config_cache->{$key}[$j]." -> ";}
0763 $msg.=$file;
0764 }
0765 }
0766 }
0767 return $msg;
0768 }
0769
0770 sub should_skip ()
0771 {
0772 my $file=shift;
0773 if(-f "$file")
0774 {
0775 foreach my $line (`cat $file`)
0776 {
0777 chomp $line;
0778 if($line=~/^\s*\
0779 if($line=~/^\s*template\s*<.+/){return 1;}
0780 }
0781 }
0782 return 0;
0783 }
0784
0785 sub check_file ()
0786 {
0787 my $file=shift;
0788 my $depth = scalar(@{$config_cache->{INC_LIST}});
0789 my $cymsg=&check_cyclic($file);
0790 if($cymsg){print "WARNING: Cyclic includes:\n"; print "$cymsg\n";}
0791 if (exists $config_cache->{FILES}{$file}{DONE}){return;}
0792 $depth++;
0793 $config_cache->{FILES}{$file}{DONE}=1;
0794 $config_cache->{REDONE}{$file}=1;
0795 delete $config_cache->{FILES}{$file}{ERROR};
0796 delete $config_cache->{FILES}{$file}{FINAL_DONE};
0797 push @{$config_cache->{INC_LIST}}, $file;
0798
0799 my $base=$config_cache->{FILES}{$file}{BASE_DIR};
0800 my $check=1;
0801 my $tmpfile="";
0802 my %cache=();
0803
0804 my $dir="${tmp_dir}/tmp_${depth}";
0805 system("mkdir -p $dir");
0806
0807 $cache{$tmpfile}{isheader}=-1;
0808 foreach my $ext (keys %{$config_cache->{HEADER_EXT}})
0809 {
0810 if(($ext!~/^\s*$/) && ($file=~/$ext/))
0811 {
0812 $tmpfile=rearrangePath ("${dir}/".basename($file).".cc");
0813 $cache{$tmpfile}{isheader}=1;
0814 if ($skipheaders){$config_cache->{FILES}{$file}{INTERNAL_SKIP}=1;}
0815 }
0816 }
0817 if($cache{$tmpfile}{isheader} == -1)
0818 {
0819 foreach my $ext (keys %{$config_cache->{SOURCE_EXT}})
0820 {
0821 if(($ext!~/^\s*$/) && ($file=~/$ext/))
0822 {
0823 $tmpfile=rearrangePath ("${dir}/".basename($file));
0824 $cache{$tmpfile}{isheader}=0;
0825 }
0826 }
0827 }
0828 if($cache{$tmpfile}{isheader} == -1)
0829 {
0830 print "WARNING: $file does match any of the following src/header extension regexp.\n";
0831 foreach my $ext (keys %{$config_cache->{HEADER_EXT}},keys %{$config_cache->{SOURCE_EXT}})
0832 {if($ext!~/^\s*$/){print " $ext\n";}}
0833 $config_cache->{FILES}{$file}{FINAL_DONE}=1;
0834 }
0835 $cache{$tmpfile}{incsafe}=0;
0836
0837 if ($tmpfile ne "")
0838 {
0839 system("cp -pf ${base}/${file} $tmpfile; chmod u+w $tmpfile");
0840 $cache{$tmpfile}{original}=$file;
0841 &check_includes ($tmpfile, $cache{$tmpfile});
0842 if($config_cache->{FILES}{$file}{ERROR} == 0)
0843 {$config_cache->{FILES}{$file}{FINAL_DONE}=1;}
0844 if($keep)
0845 {
0846 my $d=dirname("${tmp_dir}/cache/files/$file");
0847 if(!-d $d){system("mkdir -p $d");}
0848 &SCRAMGenUtils::writeHashCache($config_cache->{FILES}{$file}, "${tmp_dir}/cache/files/$file");
0849 }
0850 }
0851 system("rm -rf $dir");
0852 pop @{$config_cache->{INC_LIST}};
0853 }
0854
0855 sub comment_line ()
0856 {
0857 my $file=shift;
0858 my $line_number=shift;
0859 my $nfile="${file}.new_$$";
0860 if (!open (OLDFILE, "$file")){die "Can not open file $file for reading(FROM: comment_line:1)\n";}
0861 if (!open (NEWFILE, ">$nfile")){die "Can not open file $nfile for writing(FROM: comment_line:2)\n";}
0862 my $l=0;
0863 while(my $line=<OLDFILE>)
0864 {
0865 $l++;
0866 if ($l == $line_number)
0867 {print NEWFILE "//INCLUDECHECKER: Removed this line: $line";}
0868 else{print NEWFILE "$line";}
0869 }
0870 close(OLDFILE);
0871 close(NEWFILE);
0872 system("mv $file ${file}.backup");
0873 system("mv $nfile $file");
0874 }
0875
0876 sub add_include ()
0877 {
0878 my $file=shift;
0879 my $line_number=shift;
0880 my $add=shift;
0881 if($add!~/^.+?\s+\/\/INCLUDECHECKER: Added this line\s*$/)
0882 {$add="$add //INCLUDECHECKER: Added this line";}
0883 my $nfile="${file}.new_$$";
0884 if (!open (OLDFILE, "$file")){die "Can not open file $file for reading (From: add_include1)\n";}
0885 if (!open (NEWFILE, ">$nfile")){die "Can not open file $nfile for writing (From: add_include1)\n";}
0886 my $l=0;
0887 my $printed=0;
0888 while(my $line=<OLDFILE>)
0889 {
0890 if ($l == $line_number)
0891 {print NEWFILE "$add\n";$printed=1;}
0892 print NEWFILE "$line";
0893 $l++;
0894 }
0895 if (!$printed)
0896 {print NEWFILE "$add\n";$printed=1;}
0897 close(OLDFILE);
0898 close(NEWFILE);
0899 system("mv $nfile $file");
0900 }
0901
0902 sub read_file ()
0903 {
0904 my $file=shift;
0905 my $cache=shift;
0906 my $origfile=$cache->{original};
0907
0908 $config_cache->{FILES}{$origfile}{INCLUDES}={};
0909 $config_cache->{FILES}{$origfile}{ALL_INCLUDES_REMOVED}={};
0910 $config_cache->{FILES}{$origfile}{ALL_INCLUDES_REMOVED_ORDERED}=[];
0911 delete $config_cache->{FILES}{$origfile}{INCLUDE_REMOVED_INDIRECT};
0912 delete $config_cache->{FILES}{$origfile}{INCLUDE_ADDED_INDIRECT};
0913 delete $config_cache->{FILES}{$origfile}{ALL_INCLUDES};
0914 delete $config_cache->{FILES}{$origfile}{ALL_INCLUDES_ORDERED};
0915 if($includeall)
0916 {
0917 $config_cache->{FILES}{$origfile}{ALL_INCLUDES}={};
0918 $config_cache->{FILES}{$origfile}{ALL_INCLUDES_ORDERED}=[];
0919 }
0920
0921 &SCRAMGenUtils::readCXXFile($file,$cache);
0922 if(!exists $cache->{lines}){return;}
0923
0924 $cache->{includes}=[];
0925 $cache->{includes_line_number}=[];
0926 $cache->{incsafe} = 0;
0927
0928 my $total_lines=scalar(@{$cache->{lines}});
0929 my $first_ifndef=0;
0930 my $extern=0;
0931 for(my $i=0;$i<$total_lines;$i++)
0932 {
0933 my $line=$cache->{lines}[$i];
0934 if(($i==0) && ($line=~/^\s*#\s*ifndef\s+([^\s]+)\s*$/))
0935 {
0936 my $def=$1;
0937 my $nline=$cache->{lines}[$i+1];
0938 if($nline=~/^\s*#\s*define\s+$def\s*/){$i++;$first_ifndef=1;$cache->{incsafe}=3;next;}
0939 }
0940 if (!$first_ifndef && $cache->{isheader} && ($line=~/^\s*
0941 if($line=~/^\s*
0942 {$i=&SCRAMGenUtils::skipIfDirectiveCXX ($cache->{lines}, $i+1, $total_lines);next;}
0943
0944 while($line=~/\\\//){$line=~s/\\\//\//;}
0945 if($line=~/^\s*extern\s+\"C(\+\+|)\"\s+\{\s*$/){$extern=1;next;}
0946 if($extern && $line=~/^\s*\}.*/){$extern=0; next;}
0947 if ($line=~/^\s*#\s*include\s*([\"<](.+?)[\">])\s*(.*)$/)
0948 {
0949 my $inc_file=$2;
0950 my $comment=$3;
0951 my $num=$cache->{line_numbers}[$i];
0952 if($inc_file!~/^\./)
0953 {
0954 my $inc_filex=&SCRAMGenUtils::fixPath($inc_file);
0955 if($inc_file ne $inc_filex)
0956 {
0957 $line=~s/$inc_file/$inc_filex/;
0958 print "WARNING: Please fix the include statement on line NO. $num of file \"$origfile\"\n";
0959 print " by replacing \"$inc_file\" with \"$inc_file1\".\n";
0960 $inc_file=$inc_file1;
0961 }
0962 }
0963 else{print "WARNING: Include statement \"$inc_file\" on line NO. $num of file \"$origfile\" has a relative path. Please fix this.\n";}
0964 if($comment=~/\/\/\s*INCLUDECHECKER\s*:\s*SKIP/i){print " Skipped checking of \"$inc_file\" in \"$origfile\"(Developer forced skipping)\n";next;}
0965 if($extern){print " Skipped checking of \"$inc_file\" in \"$origfile\"(\"extern\" section include)\n";next;}
0966 push @{$cache->{includes}}, $inc_file;
0967 push @{$cache->{includes_line_number}}, $num;
0968 push @{$cache->{includes_line}}, $line;
0969 }
0970 }
0971 }
0972
0973 sub updateFromCachedFiles ()
0974 {
0975 my $dir=shift || "${tmp_dir}/cache/files";
0976 my $bdir=shift || $dir;
0977 foreach my $f (&SCRAMGenUtils::readDir($dir))
0978 {
0979 my $fp="${dir}/${f}";
0980 if(-d $fp){&updateFromCachedFiles($fp,$bdir);}
0981 elsif(-f $fp)
0982 {
0983 my $file=$fp;
0984 $file=~s/^$bdir\///;
0985 $config_cache->{FILES}{$file}=&SCRAMGenUtils::readHashCache($fp);
0986 }
0987 }
0988 }
0989
0990 sub resotre_backup ()
0991 {
0992 my $ids="${tmp_dir}/backup/ids";
0993 foreach my $id (&SCRAMGenUtils::readDir($ids,2))
0994 {
0995 my $ref;
0996 if(!open($ref,"${ids}/${id}")){die "Can not open file for reading: ${ids}/${id}";}
0997 my $file=<$ref>; chomp $file;
0998 close($ref);
0999 &recoverbackup($file,$id);
1000 print "Recovered backup: $file\n";
1001 }
1002 }
1003
1004 sub init ()
1005 {
1006 my $config=shift;
1007 if ("$tmp_dir" ne "/")
1008 {
1009 &resotre_backup ();
1010 system("mkdir -p ${tmp_dir}/${tmp_inc} ${tmp_dir}/${dummy_inc} ${tmp_dir}/cache");
1011 system("/bin/rm -rf ${tmp_dir}/tmp_* 2>&1");
1012 system("/bin/rm -rf ${tmp_dir}/${dummy_inc}/* 2>&1");
1013 if (-f "${tmp_dir}/cache/${cache_file}")
1014 {
1015 $config_cache=&SCRAMGenUtils::readHashCache("${tmp_dir}/cache/${cache_file}");
1016 $config_cache->{REDONE}={};
1017 if(-d "${tmp_dir}/cache/files"){&updateFromCachedFiles("${tmp_dir}/cache/files");}
1018 foreach my $f (keys %{$config_cache->{FILES}})
1019 {
1020 if($redo && ($f=~/$redo/)){delete $config_cache->{FILES}{$f}{DONE};delete $config_cache->{FILES}{$f}{INTERNAL_SKIP};next;}
1021 if(exists $config_cache->{FILES}{$f}{DONE})
1022 {
1023 if(($config_cache->{FILES}{$f}{FINAL_DONE}==1) ||
1024 (($config_cache->{FILES}{$f}{ERROR}==1) && ($redoerr==0))){$config_cache->{FILES}{$f}{DONE}=1;}
1025 else{delete $config_cache->{FILES}{$f}{DONE};}
1026 }
1027 }
1028
1029 if(exists $config_cache->{INCLUDEALL})
1030 {
1031 if($config_cache->{INCLUDEALL} != $includeall)
1032 {
1033 my $msg="with";
1034 if($includeall){$msg="without";}
1035 print "WARNING: Previously you had run includechecker.pl ",$msg," --includeall command-line option.\n";
1036 print "WARNING: Using the previous value of includeall\n";
1037 $includeall=$config_cache->{INCLUDEALL};
1038 }
1039 }
1040 else{$config_cache->{INCLUDEALL}=$includeall;}
1041 if(exists $config_cache->{SYSTEM_HEADER_SKIP})
1042 {
1043 if($config_cache->{SYSTEM_HEADER_SKIP} != $system_header_skip)
1044 {
1045 my $msg="without";
1046 if($system_header_skip){$msg="with";}
1047 print "WARNING: Previously you had run includechecker.pl ",$msg," --sysheader command-line option.\n";
1048 print "WARNING: Using the previous value of sysheader\n";
1049 $system_header_skip=$config_cache->{SYSTEM_HEADER_SKIP};
1050 }
1051 }
1052 else{$config_cache->{SYSTEM_HEADER_SKIP}=$system_header_skip;}
1053 if(exists $config_cache->{SKIP_HEADERS})
1054 {
1055 if($config_cache->{SKIP_HEADERS} != $skipheaders)
1056 {
1057 my $msg="without";
1058 if($skipheaders){$msg="with";}
1059 print "WARNING: Previously you had run includechecker.pl ",$msg," --skipheaders command-line option.\n";
1060 print "WARNING: Using the previous value of sysheader\n";
1061 $skipheaders=$config_cache->{SKIP_HEADERS};
1062 }
1063 }
1064 else{$config_cache->{SKIP_HEADERS}=$skipheaders;}
1065 if(exists $config_cache->{LOCAL_HEADER_SKIP})
1066 {
1067 if($config_cache->{LOCAL_HEADER_SKIP} != $local_header_skip)
1068 {
1069 my $msg="without";
1070 if($local_header_skip){$msg="with";}
1071 print "WARNING: Previously you had run includechecker.pl ",$msg," --local command-line option.\n";
1072 print "WARNING: Using the previous value of local\n";
1073 $local_header_skip=$config_cache->{LOCAL_HEADER_SKIP};
1074 }
1075 }
1076 else{$config_cache->{LOCAL_HEADER_SKIP}=$local_header_skip;}
1077 my $pfil=$config_cache->{FILEFILTER};
1078 if(($pfil ne $filefilter) && ($filefilter ne ""))
1079 {
1080 print "WARNING: You have tried to change the file filter used for previous run. Script is going to use the previous value.\n";
1081 print " New filter:\"$filefilter\"\n";
1082 print " Old filter:\"$pfil\"\n";
1083 }
1084 $filefilter=$pfil;
1085 delete $config_cache->{INC_LIST};
1086 if (!-f "${tmp_dir}/cache/${cache_file}.append"){&SCRAMGenUtils::writeHashCache($config_cache, "${tmp_dir}/cache/${cache_file}");return;}
1087 else{system("rm -f ${tmp_dir}/cache/${cache_file}.append");}
1088 }
1089 }
1090 &read_config ($config);
1091 $config_cache->{INCLUDEALL}=$includeall;
1092 $config_cache->{FILEFILTER}=$filefilter;
1093 $config_cache->{SYSTEM_HEADER_SKIP}=$system_header_skip;
1094 $config_cache->{LOCAL_HEADER_SKIP}=$local_header_skip;
1095 $config_cache->{SKIP_HEADERS}=$skipheaders;
1096 if($keep)
1097 {
1098 &SCRAMGenUtils::writeHashCache($config_cache, "${tmp_dir}/cache/${cache_file}");
1099
1100 }
1101 }
1102
1103 sub final_exit ()
1104 {
1105 my $code=shift || 0;
1106 if ("$tmp_dir" ne "/")
1107 {
1108 if ($keep)
1109 {
1110 system("/bin/rm -rf ${tmp_dir}/tmp_* 2>&1");
1111 print "Tmp directory to reuse: $tmp_dir\n";
1112 }
1113 else{system("/bin/rm -rf $tmp_dir");}
1114 }
1115 exit $code;
1116 }
1117
1118 sub rearrangePath ()
1119 {
1120 my $d=shift || return "";
1121 if($d=~/^[^\/]/){$d="${curdir}/${d}";}
1122 return &SCRAMGenUtils::fixPath ($d);
1123 }
1124
1125 sub read_config ()
1126 {
1127 my $file=shift;
1128 my $flag_index=scalar(@{$config_cache->{COMPILER_FLAGS}})-1;
1129 foreach my $line (`cat $file`)
1130 {
1131 chomp $line;
1132 if($line=~/^\s*
1133 if($line=~/^\s*$/){next;}
1134 if($line=~/^\s*COMPILER\s*=\s*(.+)$/)
1135 {
1136 $config_cache->{COMPILER}=$1;
1137 }
1138 elsif($line=~/^\s*COMPILER_FLAGS\s*=\s*(.+)$/)
1139 {
1140 push @{$config_cache->{COMPILER_FLAGS}}, "$1";
1141 $flag_index++;
1142 }
1143 elsif($line=~/^\s*DEFAULT_COMPILER_FLAGS\s*=\s*(.+)$/)
1144 {
1145 $config_cache->{COMPILER_FLAGS}[0]=$1;
1146 }
1147 elsif($line=~/^\s*BASE_DIR\s*=\s*(.+)$/)
1148 {
1149 $line=$1;
1150 foreach my $dir (split /\s+/,$line)
1151 {
1152 if (!-d $dir){print "BASE_DIR \"$dir\" does not exist.\n"; next;}
1153 if(!exists $config_cache->{BASE_DIR_ORDERED}){$config_cache->{BASE_DIR_ORDERED}=[];}
1154 if(!exists $config_cache->{BASE_DIR}{$dir})
1155 {
1156 $config_cache->{BASE_DIR}{$dir}=1;
1157 $config_cache->{NON_SYSTEM_INCLUDE}{$dir}=1;
1158 push @{$config_cache->{BASE_DIR_ORDERED}}, $dir;
1159 }
1160 }
1161 }
1162 elsif($line=~/^\s*HEADER_EXT\s*=\s*(.+)$/)
1163 {
1164 $line=$1;
1165 foreach my $exp (split /\s+/,$line)
1166 {$config_cache->{HEADER_EXT}{$exp}=1;}
1167 }
1168 elsif($line=~/^\s*SOURCE_EXT\s*=\s*(.+)$/)
1169 {
1170 $line=$1;
1171 foreach my $exp (split /\s+/,$line)
1172 {$config_cache->{SOURCE_EXT}{$exp}=1;}
1173 }
1174 elsif($line=~/^\s*INCLUDE_FILTER\s*=\s*(.+)$/)
1175 {
1176 $line=$1;
1177 $config_cache->{INCLUDE_FILTER}=$line;
1178 }
1179 elsif($line=~/^\s*SKIP_FILES\s*=\s*(.+)$/)
1180 {
1181 $line=$1;
1182 foreach my $file (split /\s+/,$line){$config_cache->{SKIP_FILES}{$file}=1;}
1183 }
1184 elsif($line=~/^\s*SKIP_AND_ADD_REMOVED_INCLUDES\s*=\s*(.+)$/)
1185 {
1186 $line=$1;
1187 foreach my $file (split /\s+/,$line){$config_cache->{SKIP_AND_ADD_REMOVED_INCLUDES}{$file}=1;}
1188 }
1189 elsif($line=~/^\s*FWDHEADER\s*=\s*(.+)$/)
1190 {
1191 $line=$1;
1192 foreach my $file (split /\s+/,$line){$config_cache->{FWDHEADER}{$file}=1;}
1193 }
1194 elsif($line=~/^\s*SKIP_INCLUDES\s*=\s*(.+)$/)
1195 {
1196 $line=$1;
1197 foreach my $exp (split /\s+/,$line)
1198 {$config_cache->{SKIP_INCLUDES}{$exp}=1;}
1199 }
1200 elsif($line=~/^\s*SKIP_SELF_INCLUDES\s*=\s*(.+)$/)
1201 {
1202 $line=$1;
1203 foreach my $exp (split /\s+/,$line)
1204 {$config_cache->{SKIP_SELF_INCLUDES}{$exp}=1;}
1205 }
1206 elsif($line=~/^\s*SKIP_ORIG_INCLUDES\s*=\s*(.+)$/)
1207 {
1208 $line=$1;
1209 foreach my $exp (split /\s+/,$line)
1210 {$config_cache->{SKIP_ORIG_INCLUDES}{$exp}=1;}
1211 }
1212 elsif($line=~/^\s*LOCAL_HEADERS\s*=\s*(.+)$/)
1213 {
1214 $line=$1;
1215 foreach my $exp (split /\s+/,$line)
1216 {$config_cache->{LOCAL_HEADERS}{$exp}=1;}
1217 }
1218 elsif($line=~/^\s*SKIP_INCLUDE_INDIRECT_ADD\s*=\s*(.+)$/)
1219 {
1220 $line=$1;
1221 foreach my $exp (split /\s+/,$line)
1222 {$config_cache->{SKIP_INCLUDE_INDIRECT_ADD}{$exp}=1;}
1223 }
1224 elsif($line=~/^\s*FILES\s*=\s*(.+)$/)
1225 {
1226 $line=$1;
1227 foreach my $file (split /\s+/,$line)
1228 {if(!exists $config_cache->{FILES}{$file}){$config_cache->{FILES}{$file}{COMPILER_FLAGS_INDEX}=$flag_index;}}
1229 }
1230 elsif($line=~/^\s*OWNHEADER\s*=\s*(.+)$/)
1231 {
1232 $line=$1;
1233 foreach my $x (split /\s+/,$line)
1234 {
1235 my $found=0;
1236 foreach my $p (@{$config_cache->{OWNHEADER}})
1237 {if($p eq $x){$found=1;last;}}
1238 if(!$found){push @{$config_cache->{OWNHEADER}},$x;}
1239 }
1240 }
1241 }
1242 my $fil=$filefilter;
1243 if($fil eq ""){$fil=".+";}
1244 foreach my $f (sort keys %{$config_cache->{FILES}})
1245 {
1246 my $b=&find_file($f);
1247 if($b){$config_cache->{FILES}{$f}{BASE_DIR}=$b;}
1248 else{delete $config_cache->{FILES}{$f}; print "$f does not exist in any base directory.\n";}
1249 }
1250 }
1251
1252 sub check_skip ()
1253 {
1254 my $file=shift || return 0;
1255 my $inc=shift || return 0;
1256 my $key=shift || return 0;
1257 foreach my $exp (keys %{$config_cache->{$key}})
1258 {
1259 my ($fexp,$val)=split /:/,$exp;
1260 if($fexp && $val)
1261 {
1262 if($file=~/$fexp/)
1263 {
1264 my $x=eval $val;
1265 if($inc=~/$x/){return 1;}
1266 }
1267 }
1268 }
1269 return 0;
1270 }
1271
1272 sub is_local_header ()
1273 {return &check_skip(shift,shift,"LOCAL_HEADERS");}
1274
1275 sub skip_include ()
1276 {
1277 my $file=shift || return 0;
1278 my $inc=shift || return 0;
1279 my $ccfile=0;
1280 if ($inc=~/^.+(\.[^\.]+)$/)
1281 {
1282 my $fext=$1;
1283 $ccfile=1;
1284 foreach my $exp (keys %{$config_cache->{HEADER_EXT}}){if($inc=~/$exp/){$ccfile=0;last;}}
1285 }
1286 return $ccfile || &check_skip($file,$inc,"SKIP_INCLUDES");
1287 }
1288
1289 sub skip_self_include ()
1290 {return &check_skip(shift,shift,"SKIP_SELF_INCLUDES");}
1291
1292 sub is_skipped_inc_add ()
1293 {return &check_skip(shift,shift,"SKIP_INCLUDE_INDIRECT_ADD");}
1294
1295 sub is_skipped()
1296 {
1297 my $file=shift;
1298 if($file!~/$filefilter/){return 1;}
1299 if((exists $config_cache->{FILES}{$file}) && (exists $config_cache->{FILES}{$file}{INTERNAL_SKIP}))
1300 {return $config_cache->{FILES}{$file}{INTERNAL_SKIP};}
1301 foreach my $type ("SKIP_FILES","FWDHEADER","SKIP_AND_ADD_REMOVED_INCLUDES")
1302 {if(&match_data($file,$type)){return 1;}}
1303 return 0;
1304 }
1305
1306 sub match_data ()
1307 {
1308 my $data=shift;
1309 my $type=shift;
1310 if(!exists $config_cache->{$type}){return 0;}
1311 foreach my $exp (keys %{$config_cache->{$type}}){if ($data=~/$exp/){return 1;}}
1312 return 0;
1313 }
1314
1315 sub usage_msg()
1316 {
1317 print "Usage: \n$0 \\\n\t[--config <file>] [--tmpdir <path>] [--filter <redexp>] [--redo <regexp>]\\\n";
1318 print " [--redoerr] [--keep] [--recursive] [--unique] [--includeall] [--sysheader] [--local]\\\n";
1319 print " [--detail] [--help]\n\n";
1320 print " --config <file> File which contains the list of files to check.\n";
1321 print " File format is:\n";
1322 print " COMPILER=<compiler path> #Optional: Default is \"".$config_cache->{COMPILER}."\".\n";
1323 print " COMPILER_FLAGS=<flags> #Optional: Default are \"".$config_cache->{COMPILER_FLAGS}[0]."\".\n";
1324 print " HEADER_EXT=<regexp> #Optional: Default is \"".join(", ",keys %{$config_cache->{HEADER_EXT}})."\".\n";
1325 print " SOURCE_EXT=<regexp> #Optional: Default is \"".join(", ",keys %{$config_cache->{SOURCE_EXT}})."\".\n";
1326 print " INCLUDE_FILTER=<regexp> #Optional: Default is \"".$config_cache->{INCLUDE_FILTER}."\"\n";
1327 print " #This filter is use to find the included files.\n";
1328 print " FILES=<relppath1> <relpath2> #' ' separated list of files relative paths\n";
1329 print " FILES=<relpath3>\n";
1330 print " SKIP_FILES=<regexp1> <regexp2> #Optional: ' ' separated list regular expressions\n";
1331 print " SKIP_FILES=<regexp3>\n";
1332 print " SKIP_INCLUDES=<regexp1_InFile>:<regexp2_IncludedFile> <regexp3_InFile>:<regexp4_IncludeFile>\n";
1333 print " #Optional: ' ' separated list regular expressions\n";
1334 print " SKIP_INCLUDES=<regexp5_InFile>:<regexp5_IncludeFile>\n";
1335 print " SKIP_INCLUDE_INDIRECT_ADD=<regexp_InFile>:<regexp_IncludeFile>\n";
1336 print " LOCAL_HEADERS=<regexp_InFile>:<regexp_IncludeFile> <regexp_InFile>:<regexp_IncludeFile>\n";
1337 print " BASE_DIR=<dir1> <dir2> #Path where all the FILES exists.\n";
1338 print " BASE_DIR=<dir3>\n";
1339 print " #One can use it multiple times to provide many base directories.\n";
1340 print " OWNHEADER=<regexp1>:\"<regexp2>\"\n";
1341 print " #by default file1.h is assumed to be aheader file of file1.C|Cc|Cxx etc.\n";
1342 print " #But if your source files and header files do not exist in same directory then\n";
1343 print " #you can provide your own filters. e.g.\n";
1344 print " #OWNHEADER=^src\\/(.+?)\\.C:\"interface/\$1.h\"\n";
1345 print " #means that a own header for file src/file1.C exists in interface/file1.h\n";
1346 print " One can redefine COMPILER_FLAGS so the rest of the FILES\n";
1347 print " will use these new flags.\n";
1348 print " --tmpdir <path> Tmp directory where the tmp files will be generated.\n";
1349 print " Default is /tmp/delete_me_includechecker_<pid>.\n";
1350 print " --filter <regexp> Process only those files which matches the filter <regexp>.\n";
1351 print " --redo <regexp> Recheck all the files which matches the filter <regexp>.\n";
1352 print " --redoerr Recheck all the files had errors durring last run.\n";
1353 print " --keep Do not delete the tmp files.\n";
1354 print " --recursive Recursively check all the included headers if\n";
1355 print " they exist in one of the BASE_DIR.\n";
1356 print " --unique If a header is already included in one of your included headers then remove it.\n";
1357 print " e.g. if B.h includes A.h and C.h include both A.h and B.h then remove A.h for\n";
1358 print " C.h as its alreay included by B.h. If this option is not used then script will\n";
1359 print " check if a included header is really used or not by compiling it couple of time.\n";
1360 print " --includeall Add all the headers from an included header file (which are not already included in file to check).\n";
1361 print " --sysheader Do not skip checking for system headers.\n";
1362 print " --local Do not skip checking for local headers(for fast processing local headers of a package are not checked).\n";
1363 print " --detail To get more detailed output.\n";
1364 print " --help To see this help message.\n";
1365 exit 0;
1366 }