Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:31:47

0001 #!/usr/bin/env perl
0002 use File::Basename;
0003 use lib dirname($0);
0004 use Getopt::Long;
0005 use Digest::MD5  qw(md5_hex);
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*\#\s*define\s+.+?\\$/){return 1;}
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*#\s*ifndef\s+/)){$first_ifndef=1; $cache->{incsafe}=3; next;}
0941     if($line=~/^\s*#\s*if(n|\s+|)def(ined|\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     #&init($config);
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*#/){next;}
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 }