#!/usr/bin/perl -w # NAME: showincs.pl # AIM: Read a C/C++ file and show included files... # 17/05/2013 - Change list spearator depending on OS - win=';', unix=':' # 17/03/2013 - Add summary at end, and no search for incs in 'windows' includes # 23/05/2012 - Exclude searching linux includes - # 12/11/2011 - Maybe some MACRO expansion # 04/12/2010 - Added scan of directories to find the file... # 02/12/2010 - Update - added INC directories... use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use File::Spec; # File::Spec->rel2abs($rel); # we are IN the SLN directory, get ABSOLUTE from RELATIVE use Cwd; my $os = $^O; my $perl_dir = '/home/geoff/bin'; my $PATH_SEP = '/'; my $temp_dir = '/tmp'; if ($os =~ /win/i) { $perl_dir = 'C:\GTools\perl'; $temp_dir = $perl_dir; $PATH_SEP = "\\"; } unshift(@INC, $perl_dir); require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl' Check paths in \@INC...\n"; # log file stuff our ($LF); my $pgmname = $0; if ($pgmname =~ /(\\|\/)/) { my @tmpsp = split(/(\\|\/)/,$pgmname); $pgmname = $tmpsp[-1]; } my $outfile = $temp_dir.$PATH_SEP."temp.$pgmname.txt"; open_log($outfile); # user variables my $VERS = "0.0.7 2013-05-17"; ###my $VERS = "0.0.6 2013-03-17"; ###my $VERS = "0.17/05/20130.5 2012-05-23"; my $load_log = 0; my $g_in_file = ''; my $g_in_root = ''; my $include_linux = 0; my $exclude_externals = 1; my $g_out_file = ''; my $do_directory_scan = 0; # seems wasteful my $scan_all_files = 0; # do NOT scan windows/sdk/linux includes for includes my $abort_on_missed = 0; my @find_list = (); ### program variables my @finds = (); my $total_lines = 0; my %scanned_files = (); my @warnings = (); my $cwd = cwd(); #my %g_files_done = (); my $done_dir_scans = 0; my %ref_dir_scans = (); my @g_INC_dirs = (); my @missing_files = (); my $verbosity = 0; my $debug_on = 0; my $def_file = 'C:\FG\17\3rdParty\include\gdal\gdal.h'; #my $def_file = 'C:\FGCVS\boost-trunk\boost\tr1\unordered_set.hpp'; my $def_root = ''; # no root to scan 'C:\FGCVS\boost-trunk'; #my $def_file = 'C:\Projects\giflib\lib\dgif_lib.c'; #my $def_root = 'C:\Projects\giflib'; #my $def_file = 'C:\Projects\libsigc\libsigc++-2.2.8\sigc++\signal.cc'; #my $def_root = 'C:\Projects\libsigc\libsigc++-2.2.8'; sub VERB1() { return ($verbosity > 0); } sub VERB2() { return ($verbosity > 1); } sub VERB5() { return ($verbosity > 4); } sub VERB9() { return ($verbosity > 8); } sub show_warnings($) { my ($val) = @_; if (@warnings) { prt( "\nGot ".scalar @warnings." WARNINGS...\n" ); foreach my $itm (@warnings) { prt("$itm\n"); } prt("\n"); } elsif ($val) { #prt( "\nNo warnings issued.\n\n" ); } } sub pgm_exit($$) { my ($val,$msg) = @_; show_warnings($val); if (length($msg)) { $msg =~ s/\n$//; prt("$msg\n"); } # prt("$msg ".localtime(time())."\n"); close_log($outfile,$load_log); exit($val); } sub prtw($) { my ($tx) = shift; $tx =~ s/\n$//; prt("$tx\n"); push(@warnings,$tx); } sub si_process_in_file($$); sub path_per_os($) { my $path = shift; if ($os =~ /Win/i) { $path = path_u2d($path); } else { $path = path_d2u($path); } return $path; } sub fix_dir_string($) { my ($rdir) = @_; if (! ( ${$rdir} =~ /(\\|\/)$/) ) { ${$rdir} .= $PATH_SEP; } } sub begins_with { my ($rt, $pt) = @_; my $ln = length($rt); my ($i); if (length($pt) >= $ln) { for ($i = 0; $i < $ln; $i++) { return 0 if (substr($rt,$i,1) ne substr($pt,$i,1)); } return 1; # does indeed begin with... } return 0; } sub sub_first_from_second_if($$) { my ($d1,$d2) = @_; if (being_with($d1,$d2)) { $d2 = substr($d2, length($d1)); } return $d2; } # FIXES FOR THE FULL FILE NAME # 1. ensure ALL DOS format # 2. if given a FULL PATH name, remove C:\FG\20\FlightGear # 3. if any removal, ensure any beginning '\' is removed sub sub_root_dir($) { my ($ff) = shift; # = $a_dir.$src $ff = path_per_os($ff); my $rd = $g_in_root; # get_root_dir(); if (begins_with($rd, $ff)) { $ff = substr($ff, length($rd)); } return $ff; } ######################################################## ### DIRECTORY SCANNING ### sub si_do_dir_scan($$$); sub si_do_dir_scan($$$) { my ($rparams,$dir,$lv) = @_; my $rda = ${$rparams}{'SI_CURR_DIR_SCAN'}; $dir .= "\\" if !($dir =~ /(\\|\/)$/); $dir = path_per_os($dir); my ($file,$ff,$n,$d); my @dirs = (); prt("Moment, doing full directory scan of [$dir]...\n") if (($lv == 0) && VERB1()); if (opendir(DIR,$dir)) { my @files = readdir(DIR); closedir(DIR); foreach $file (@files) { next if (($file eq '.')||($file eq '..')); $ff = $dir.$file; if (-d $ff) { push(@dirs,$ff); next; } # 0 1 2 3 push(@{$rda},[$file,$ff,0,0]); } } if (@dirs) { foreach $file (@dirs) { si_do_dir_scan($rparams,$file,$lv+1); } } if ($lv == 0) { $file = scalar @{$rda}; prt("Done scan... got $file files...\n") if (VERB5()); ${$rparams}{'SI_CURR_DONE_SCAN'} = 1; } } sub si_is_file_in_scan($$$$) { my ($rparams,$test,$inc,$ra) = @_; if (! ${$rparams}{'SI_CURR_DONE_SCAN'} ) { my $dir = ${$rparams}{'SI_CURR_IN_ROOT'}; if (-d $dir) { si_do_dir_scan($rparams,$dir,0); } else { prtw("WARNING: Directory SEARCH FAILED! [$dir] NOT found!\n"); return 0; } } my $rda = ${$rparams}{'SI_CURR_DIR_SCAN'}; my $cnt = scalar @{$rda}; my ($i,$file,$fcnt,$ff); $fcnt = 0; for ($i = 0; $i < $cnt; $i++) { $file = ${$rda}[$i][0]; #if ($test eq $file) { if ($inc eq $file) { $ff = ${$rda}[$i][1]; # could now check if $fd at least partially matches, but for now push(@{$ra},$ff); $fcnt++; } } #prt("Directory SEARCH for [$inc] [$test], found $fcnt. Only 1st used.\n") if ($fcnt); # if ($dbg_lac20); return $fcnt; } ######################################################## ### DIRECTORY SCANNING ### sub do_dir_scan($$$); sub do_dir_scan($$$) { my ($rparams,$dir,$lv) = @_; my $rda = ${$rparams}{'CURR_DIR_SCAN'}; $dir = path_per_os($dir); fix_dir_string(\$dir); my ($file,$ff,$n,$d); my @dirs = (); prt("Moment, doing full directory scan of [$dir]...\n") if (($lv == 0) && VERB9()); if (opendir(DIR,$dir)) { my @files = readdir(DIR); closedir(DIR); foreach $file (@files) { next if (($file eq '.')||($file eq '..')); $ff = $dir.$file; if (-d $ff) { push(@dirs,$ff); next; } # 0 1 2 3 push(@{$rda},[$file,$ff,0,0]); } } else { prtw("WARNING: FAILED to OPEN [$dir]\n"); } foreach $file (@dirs) { do_dir_scan($rparams,$file,$lv+1); } if ($lv == 0) { $file = scalar @{$rda}; prt("Done scan... got $file files...\n") if (VERB9()); ${$rparams}{'CURR_DONE_SCAN'} = 1; ${$rparams}{'CURR_FILE_COUNT'} = $file; } } sub get_anon_hash() { my %h = (); return \%h; } sub get_dir_scan_rh($) { my ($dir) = @_; my $rparams = get_anon_hash(); ${$rparams}{'CURR_DONE_SCAN'} = 0; ## 0 1 2 3 #push(@{$rda},[$file,$ff,0,0]); ${$rparams}{'CURR_DIR_SCAN'} = []; do_dir_scan($rparams,$dir,0); return $rparams; } sub get_dir_scan_hash($) { my ($src) = @_; $src = path_per_os($src); if (defined $ref_dir_scans{$src}) { return $ref_dir_scans{$src}; } $ref_dir_scans{$src} = get_dir_scan_rh($src); $done_dir_scans++; return $ref_dir_scans{$src}; } my $shown_msvc_incs = 0; # prt("Got $cnt 'MSVC' directories... using vcvarsall.bat\n") if (VERB1()); my $shown_msvc_cnt = 0; # prt("$dir - with $cnt files...\n"); sub get_msvc_includes() { my ($insdir); my @vc8 = (); my %dirs = (); my $cnt = 0; my %h = (); $h{'*CURR_TOTAL_CNT*'} = 0; if (vc_get_include_dirs2(\$insdir,0) ) { $cnt = scalar @{$insdir}; # prt("OK got $cnt\n"); my $rd = \%dirs; my ($dir,$min,$len); $cnt = 0; $min = 0; foreach $dir (@{$insdir}) { if (-d $dir) { # if ( add_to_files_lc($dir,$rd) ) # check NOT duplicate if (defined ${$rd}{$dir}) { # already in LIST } else { push(@vc8,$dir); $cnt++; ${$rd}{$dir} = $cnt; $len = length($dir); $min = $len if ($len > $min); } } } if (@vc8) { $cnt = scalar @vc8; prt("Got $cnt 'MSVC' directories... using vcvarsall.bat\n") if (VERB1() && !$shown_msvc_incs ); $shown_msvc_incs = 1; $min = 0; foreach $dir (@vc8) { $len = length($dir); $min = $len if ($len > $min); } foreach $dir (@vc8) { # my $rh = get_dir_scan_rh($dir); my $rh = get_dir_scan_hash($dir); $h{$dir} = $rh; $cnt = ${$rh}{'CURR_FILE_COUNT'}; $h{'*CURR_TOTAL_CNT*'} += $cnt; if (VERB9() && !$shown_msvc_cnt) { $dir .= " " while (length($dir) < $min); prt("$dir - with $cnt files...\n"); $shown_msvc_cnt = 1; } } } } else { prt("Failed to get include directories!\n"); } $h{'*MSVC_DIR_LIST*'} = \@vc8; # array list of KEYS to directory scan hash return \%h; } my %msvc_checked = (); sub in_msvc_includes2($$) { my ($inc,$rff) = @_; my ($ra,$dir,$ff); if (defined $msvc_checked{$inc}) { $ff = $msvc_checked{$inc}; if (length($ff)) { ${$rff} = $ff; return 1; } return 0; } if (vc_get_include_dirs2(\$ra,0) ) { foreach $dir (@{$ra}) { fix_dir_string(\$dir); $ff = $dir.$inc; ###prt("Checking for [$ff] "); if (-f $ff) { ${$rff} = $ff; ###prt("Found [$inc] [$ff]\n"); $msvc_checked{$inc} = $ff; return 1; } #prt("Check for [$ff] FAILED!\n"); } } $msvc_checked{$inc} = ''; return 0; } sub in_msvc_includes($) { my ($inc) = @_; my $rh = get_msvc_includes(); # my $rdsh = get_dir_scan_rh($dir); # stored $h{$dir} = $rdsh; my $tcnt = ${$rh}{'*CURR_TOTAL_CNT*'}; my $rkya = ${$rh}{'*MSVC_DIR_LIST*'}; # array list of KEYS to directory scan hash my ($key,$fil,$dir,$cnt); my ($i,$fn,$ff,$lcfn); my $lcinc = path_per_os($inc); # file name to OS form $lcinc = lc($lcinc) if ($os =~ /Win/i); #all lower case in WIN32 foreach $key (@{$rkya}) { if (defined ${$rh}{$key}) { my $rka = ${$rh}{$key}; # list of files in this directory #my $rda = ${$rparams}{'CURR_DIR_SCAN'}; #${$rparams}{'CURR_DONE_SCAN'} = 1; $cnt = ${$rka}{'CURR_FILE_COUNT'}; my $rda = ${$rka}{'CURR_DIR_SCAN'}; $cnt = scalar @{$rda}; # should equal CURR_FILE_COUNT $dir = path_per_os($key); fix_dir_string(\$dir); for ($i = 0; $i < $cnt; $i++) { $fn = ${$rda}[$i][0]; # get FILE name $lcfn = lc($fn); $ff = $dir.$inc; if ($lcfn eq $lcinc) { return 1; } elsif ( -f $ff ) { return 2; } } } } return 0; } sub in_unix_includes2($$) { my ($inc,$rff) = @_; my $dir = "C:\\Projects\\include"; return 0 if (! -d $dir); fix_dir_string(\$dir); my $ff = $dir.$inc; if (-f $ff) { ${$rff} = $ff; return 1; } return 0; } sub in_unix_includes($) { my ($inc) = @_; my $dir = "C:\\Projects\\include"; my $rka = get_dir_scan_hash($dir); my $cnt = ${$rka}{'CURR_FILE_COUNT'}; ## 0 1 2 3 #push(@{$rda},[$file,$ff,0,0]); my $rda = ${$rka}{'CURR_DIR_SCAN'}; $cnt = scalar @{$rda}; my ($i,$fn,$lcfn,$lcinc,$ff); $lcinc = lc($inc); $dir .= "\\" if (!($dir =~ /\\$/)); for ($i = 0; $i < $cnt; $i++) { $fn = ${$rda}[$i][0]; # get FILE name $lcfn = lc($fn); $ff = $dir.$fn; if ($lcfn eq $lcinc) { return 1; } elsif (-f $ff) { return 2; } } return 0; } sub get_PSDK_directory() { my $dir = 'C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include'; return $dir if (-d $dir); # 20120529 - Add Win7_-PC platform SDK directory $dir = 'C:\Program Files\Microsoft SDKs\Windows\v7.1\include'; return $dir if (-d $dir); prtw("WARNING: Platform SDK directory NOT found! FIX ME!!\n"); return ""; } sub in_sdk_includes2($$) { my ($inc,$rff) = @_; my $dir = get_PSDK_directory(); return 0 if (length($dir) == 0); fix_dir_string(\$dir); my $ff = $dir.$inc; if (-f $ff) { ${$rff} = $ff; return 1; } return 0; } sub in_sdk_includes($) { my $inc = shift; my $dir = get_PSDK_directory(); return 0 if (length($dir) == 0); my $rka = get_dir_scan_hash($dir); my $cnt = ${$rka}{'CURR_FILE_COUNT'}; ## 0 1 2 3 #push(@{$rda},[$file,$ff,0,0]); my $rda = ${$rka}{'CURR_DIR_SCAN'}; $cnt = scalar @{$rda}; my ($i,$fn,$lcfn,$lcinc,$ff); my $iswin = ($os =~ /Win/i) ? 1 : 0; $lcinc = ($iswin ? lc($inc) : $inc); fix_dir_string(\$dir); for ($i = 0; $i < $cnt; $i++) { $fn = ${$rda}[$i][0]; # get FILE name $lcfn = ($iswin ? lc($fn) : $fn); $ff = $dir.$fn; if ($lcfn eq $lcinc) { return 1; } elsif (-f $ff) { return 2; } } return 0; } sub check_finds($$$) { my ($inf,$lnn,$tline) = @_; my ($find); foreach $find (@find_list) { if ($tline =~ /$find/i) { push(@finds,[$inf,$lnn,$find,$tline]); } } $total_lines++; $scanned_files{$inf} = 1; } sub si_process_in_file($$) { my ($rparams,$lev) = @_; my $inf = ${$rparams}{'SI_CURR_IN_FILE'}; my $rfd = ${$rparams}{'SI_REF_FILES_DONE'}; # \%files_done my $rdo = ${$rparams}{'SI_RA_FILES_DONE'}; my $rid = ${$rparams}{'SI_REF_INCS_DONE'}; my $rincs = ${$rparams}{'SI_REF_INCS_ARRAY'}; my $cin_root = ${$rparams}{'SI_CURR_IN_ROOT'}; my $rincdirs = ${$rparams}{'SI_REF_INCLUDE_DIRS'}; # already done - fix_dir_string(\$cin_root); my $dbg_01 = ${$rparams}{'SI_CURR_DBG_SI01'}; my $dbg_02 = ${$rparams}{'SI_CURR_DBG_SI02'}; my $dbg_03 = ${$rparams}{'SI_CURR_DBG_SI03'}; if (! open INF, "<$inf") { pgm_exit(1,"ERROR: Unable to open file [$inf]\n"); } my @lines = ; close INF; my $lncnt = scalar @lines; prt("\n[01] Processing $lncnt lines, from [$inf]...\n") if ($dbg_01 || VERB9()); my ($line,$inc,$lnn,$name,$dir,$ff,$ch,$ok); my ($n,$d,$cnt,$i,$fcnt,@arr); my ($ifitem,$tline,$defitem,$impitem,$pragitem,$erritem,$unditem,$useitem); my ($fnd,$icnt,$ra); ($name,$dir) = fileparse($inf); $dir = $cwd if ($dir =~ /^\.(\\|\/)$/); $dir .= "\\" if (!($dir =~ /(\\|\/)$/)); $lnn = 0; my @incs = (); $icnt = scalar @{$rincdirs}; for ($i = 0; $i < $lncnt; $i++) { $line = $lines[$i]; chomp $line; $tline = trim_all($line); $lnn++; check_finds($inf,$lnn,$tline); if ($line =~ /\s*#\s*include\s+(.+)$/) { $inc = $1; $inc =~ s/\/\/.*$//; $inc =~ s/\/\*.*$//; $inc = trim_all($inc); $ch = substr($inc,0,1); if ($inc =~ /<(.+)>/) { $inc =~ s/<(.+)>/$1/; } elsif ($inc =~ /"(.+)"/) { $inc =~ s/"(.+)"/$1/; } $ok = "NEW"; $fnd = 0; ($n,$d) = fileparse($inc); if ( defined ${$rid}{$inc} ) { prt("[01] Line $lnn: [$inc] via [$ch] DONE\n") if ($dbg_01 || VERB9()); $fnd = -1; } else { prt("[01] Line $lnn: [$inc] via [$ch] $ok\n") if ($dbg_01 || VERB9()); $ff = $dir.$inc; $ok = 'NOT FOUND'; if (-f $ff) { $ok = 'ok 1'; prt("[01] Line $lnn: [$inc] found 1 [$ff]\n") if ($dbg_01 || VERB9()); $fnd = 1; } else { if ($inc =~ /(\\|\/)/) { ($n,$d) = fileparse($inc); $ff = $dir.$n; if (-f $ff) { $ok = 'ok 2'; prt("[01] Line $lnn: [$inc] found 2 [$ff]\n") if ($dbg_01 || VERB9()); $fnd = 2; } else { $ff = $cin_root.$n; if (-f $ff) { $ok = 'ok 3'; prt("[01] Line $lnn: [$inc] found 3 [$ff]\n") if ($dbg_01 || VERB9()); $fnd = 3; } elsif ($do_directory_scan) { @arr = (); prt("[01] Line $lnn: Checking [$inc] [$ff] in directory scan...\n") if ($dbg_01 || VERB9()); if ( si_is_file_in_scan($rparams,$ff,$inc,\@arr) ) { $fcnt = scalar @arr; $ff = $arr[0]; prt("[01] Line $lnn: Returned $fcnt, trying [$ff] ") if ($dbg_01 || VERB9()); if (-f $ff) { $ok = 'ok 4'; $fnd = 4; } prt(" $ok\n") if ($dbg_01 || VERB9()); } elsif (($inc =~ /(\\|\/)/) && $do_directory_scan) { ($n,$d) = fileparse($inc); if ( si_is_file_in_scan($rparams,$ff,$n,\@arr) ) { $fcnt = scalar @arr; $ff = $arr[0]; prt("[01] Line $lnn: Returned $fcnt, trying [$ff] ") if ($dbg_01 || VERB9()); if (-f $ff) { $ok = 'ok 5'; $fnd = 5; } prt(" $ok\n") if ($dbg_01 || VERB9()); } } else { prt("[01] Line $lnn: [$inc] NOT FOUND [$ff]\n") if ($dbg_01 || VERB9()); } } } } else { $ff = $cin_root.$n; if (-f $ff) { $ok = 'ok 6'; prt("[01] Line $lnn: [$inc] found 6 [$ff]\n") if ($dbg_01 || VERB9()); $fnd = 6; } elsif ($do_directory_scan) { @arr = (); prt("[01] Line $lnn: Checking [$inc] [$ff] in directory scan...\n") if ($dbg_01 || VERB9()); if ( si_is_file_in_scan($rparams,$ff,$inc,\@arr) ) { $fcnt = scalar @arr; $ff = $arr[0]; prt("[01] Line $lnn: Returned $fcnt, trying [$ff] ") if ($dbg_01 || VERB9()); if (-f $ff) { $ok = 'ok 7'; $fnd = 7; } prt(" $ok\n") if ($dbg_01 || VERB9()); } else { prt("[01] Line $lnn: [$inc] NOT FOUND [$ff]\n") if ($dbg_01 || VERB9()); } } } } if ($fnd == 0) { if ($icnt) { foreach $d (@{$rincdirs}) { $d .= "\\" if ( !($d =~ /(\\|\/)$/) ); $ff = $d.$inc; if (-f $ff) { $ok = 'ok 8'; $fnd = 8; last; } } } } if ($fnd == 0) { if (in_msvc_includes2($inc,\$ff)) { $ok = " [$ff]"; $fnd = 9; } } if ($fnd == 0) { if (in_sdk_includes2($inc,\$ff)) { $ok = " [$ff]"; $fnd = 10; } } if (($fnd == 0) && $include_linux) { if (in_unix_includes2($inc,\$ff)) { $ok = " [$ff]"; $fnd = 11; } } if ($fnd) { $ff = path_per_os($ff); } else { $ff = $inc; } ${$rid}{$inc} = $inf; ${$rfd}{$ff} = $inf; push(@{$rdo},$inf); # 0 1 2 3 4 5 6 push(@{$rincs},[$ff,$inc,$ch,$lnn,$inf,$ok,$fnd]); push(@incs, [$ff,$inc,$ch,$lnn,$inf,$ok,$fnd]); prt("[01] $lev: Stored:$ok:$fnd: [$ff] [$inc] [$ch] [$lnn] [$inf]\n") if ($dbg_01 || $dbg_03 || VERB9()); } } elsif ($line =~ /\s*#\s*if\s+(.+)$/) { $ifitem = $1; $ifitem =~ s/\/\/.*$//; $ifitem =~ s/\/\*.*$//; prt("[02] #if [$ifitem]\n") if ($dbg_02); } elsif ($line =~ /\s*#\s*ifdef\s+(.+)$/) { $ifitem = $1; $ifitem =~ s/\/\/.*$//; $ifitem =~ s/\/\*.*$//; prt("[02] #ifdef [$ifitem]\n") if ($dbg_02); } elsif ($line =~ /\s*#\s*ifndef\s+(.+)$/) { $ifitem = $1; $ifitem =~ s/\/\/.*$//; $ifitem =~ s/\/\*.*$//; prt("[02] #ifndef [$ifitem]\n") if ($dbg_02); } elsif ($line =~ /\s*#\s*else\s+(.+)$/) { $ifitem = $1; $ifitem =~ s/\/\/.*$//; $ifitem =~ s/\/\*.*$//; prt("[02] #else [$ifitem]\n") if ($dbg_02); } elsif ($line =~ /\s*#\s*elif\s+(.+)$/) { $ifitem = $1; $ifitem =~ s/\/\/.*$//; $ifitem =~ s/\/\*.*$//; prt("[02] #elif [$ifitem]\n") if ($dbg_02); } elsif ($line =~ /\s*#\s*endif\s+(.+)$/) { $ifitem = $1; $ifitem =~ s/\/\/.*$//; $ifitem =~ s/\/\*.*$//; prt("[02] #endif [$ifitem]\n") if ($dbg_02); } elsif ($line =~ /\s*#\s*define\s+(.+)$/) { $defitem = $1; $defitem =~ s/\/\/.*$//; $defitem =~ s/\/\*.*$//; prt("[02] #define [$ifitem]\n") if ($dbg_02); } elsif ($line =~ /\s*#\s*import\s+(.+)$/) { $impitem = $1; $impitem =~ s/\/\/.*$//; $impitem =~ s/\/\*.*$//; prt("[02] #import [$impitem]\n") if ($dbg_02); } elsif ($line =~ /\s*#\s*pragma\s+(.+)$/) { $pragitem = $1; $pragitem =~ s/\/\/.*$//; $pragitem =~ s/\/\*.*$//; prt("[02] #pragma [$ifitem]\n") if ($dbg_02); } elsif ($line =~ /\s*#\s*error\s+(.+)$/) { $erritem = $1; $erritem =~ s/\/\/.*$//; $erritem =~ s/\/\*.*$//; prt("[02] #error [$erritem]\n") if ($dbg_02); } elsif ($line =~ /\s*#\s*undef\s+(.+)$/) { $unditem = $1; $unditem =~ s/\/\/.*$//; $unditem =~ s/\/\*.*$//; prt("[02] #undef [$unditem]\n") if ($dbg_02); } elsif ($line =~ /\s*#\s*use\s+(.+)$/) { $useitem = $1; $useitem =~ s/\/\/.*$//; $useitem =~ s/\/\*.*$//; prt("[02] #use [$useitem]\n") if ($dbg_02); } } # now process the includes, for includes $cnt = scalar @incs; for ($i = 0; $i < $cnt; $i++) { # 0 1 2 3 4 5 6 #push(@incs, [$ff,$inc,$ch,$lnn,$inf,$ok,$fnd]); $ra = $incs[$i]; $ff = ${$ra}[0]; #$incs[$i][0]; $ok = ${$ra}[5]; #$incs[$i][5]; $fnd = ${$ra}[6]; #$incs[$i][6]; push(@missing_files,$ra) if ($fnd == 0); if (-f $ff) { if (($fnd < 9) || $scan_all_files) { ${$rparams}{'SI_CURR_IN_FILE'} = $ff; si_process_in_file($rparams,($lev+1)); } } elsif ($do_directory_scan) { $inc = $incs[$i][1]; $ch = $incs[$i][2]; prt("[01] Unable to locate [$inc]! [$ch]... Searching dir scan...\n") if ($dbg_01 || VERB9()); @arr = (); if ( si_is_file_in_scan($rparams,$ff,$inc,\@arr) ) { $fcnt = scalar @arr; prt("[01] Returned $fcnt, trying each...\n") if ($dbg_01 || VERB9()); foreach $ff (@arr) { ${$rparams}{'SI_CURR_IN_FILE'} = $ff; si_process_in_file($rparams,($lev+1)); } } elsif ($inc =~ /(\\|\/)/) { ($n,$d) = fileparse($inc); if ( si_is_file_in_scan($rparams,$ff,$n,\@arr) ) { $fcnt = scalar @arr; prt("[01] Returned $fcnt, trying each...\n") if ($dbg_01 || VERB9()); foreach $ff (@arr) { ${$rparams}{'SI_CURR_IN_FILE'} = $ff; si_process_in_file($rparams,($lev+1)); } } } } } } sub compare_paths($$) { my ($p1,$p2) = @_; if ($os =~ /win/i) { $p1 = lc(path_u2d($p1)); $p2 = lc(path_u2d($p2)); } else { $p1 = path_d2u($p1); $p2 = path_d2u($p2); } return 1 if ($p1 eq $p2); return 0; } sub si_show_found_list($) { my ($rparams) = @_; my $rh = ${$rparams}{'SI_REF_FILES_DONE'}; # \%files_done my $inf = ${$rparams}{'SI_MAIN_IN_FILE'}; my $rdo = ${$rparams}{'SI_RA_FILES_DONE'}; my $rincs = ${$rparams}{'SI_REF_INCS_ARRAY'}; my ($key,$val,$k2,$v2,$file,$cnt,$done,$icnt,$key2); my ($ricnt,$ifile,$i,$ok,$min,$len,$vcnt,$ccnt); my %h = (); my $rh2 = \%h; $cnt = scalar @{$rdo}; $ricnt = scalar @{$rincs}; my %fdone = (); prt("\nIn the processing of [$inf]... found $cnt includes...\n") if (VERB1()); foreach $key (keys %{$rh}) { $val = ${$rh}{$key}; # get the file in which it was found ${$rh2}{$val} = [] if (!defined ${$rh2}{$val}); $v2 = ${$rh2}{$val}; push(@{$v2},$key); # store what was found in that file } # now per the files searched $icnt = 0; %fdone = (); $min = 0; foreach $key2 (@{$rdo}) { if ( ! defined $fdone{$key2} ) { $fdone{$key2} = 1; $done = 0; foreach $key (keys %{$rh2}) { if (compare_paths($key,$key2)) { $val = ${$rh2}{$key}; $file = sub_root_dir($key); # prt("File [$file] has...\n"); foreach $k2 (@{$val}) { $icnt++; $ok = 'Missed'; $file = sub_root_dir($k2); #prt("Checking [$k2] in all incs..\n"); for ($i = 0; $i < $ricnt; $i++) { # 0 1 2 3 4 5 #push(@incs,[$ff,$inc,$ch,$lnn,$inf,$ok]); $ifile = ${$rincs}[$i][0]; # FULL FILE #prt(" With [$ifile]...\n"); if ($ifile eq $k2) { $ok = ${$rincs}[$i][5]; $file = ${$rincs}[$i][1]; last; } } #prt(" $icnt: $file $ok\n"); $len = length($file); $min = $len if ($len > $min); } $done = 1; } } if (!$done) { if ($abort_on_missed) { prt("ERROR: Not found [$key2]! Searched list\n"); my @arr = keys %{$rh2}; prt(join("\n",@arr)."\n"); pgm_exit(1,"ERROR INTERNAL: Missed [$key2]! WHY? FIX THIS!!!\n"); } } } } $icnt = 0; %fdone = (); my @found = (); foreach $key2 (@{$rdo}) { if ( ! defined $fdone{$key2} ) { $fdone{$key2} = 1; $done = 0; foreach $key (keys %{$rh2}) { if ($key eq $key2) { $val = ${$rh2}{$key}; $file = sub_root_dir($key); $vcnt = scalar @{$val}; prt("\n") if (VERB9()); prt("File [$file] has $vcnt 'include'...\n"); foreach $k2 (@{$val}) { $icnt++; $ok = 'Missed'; $file = sub_root_dir($k2); # dummy include #prt("Checking [$k2] in all incs..\n"); for ($i = 0; $i < $ricnt; $i++) { # 0 1 2 3 4 5 #push(@incs,[$ff,$inc,$ch,$lnn,$inf,$ok]); $ifile = ${$rincs}[$i][0]; # FULL FILE #prt(" With [$ifile]...\n"); if ($ifile eq $k2) { $ok = ${$rincs}[$i][5]; $file = ${$rincs}[$i][1]; # get original INCLUDE last; } } $file .= ' ' while (length($file) < $min); $ok .= " [$k2]" if ($ok eq 'ok'); $ccnt = sprintf("%4d",$icnt); if ($exclude_externals && !VERB9()) { if ($ok =~ /^ok/) { prt(" $ccnt: $file $ok\n") if (VERB5()); push(@found,$k2); } } elsif (VERB9()) { prt(" $ccnt: $file $ok\n"); push(@found,$k2); } } $done = 1; } } if (!$done) { if ($abort_on_missed) { #prt("Missed [$key2]! WHY?\n"); pgm_exit(1,"ERROR INTERNAL: Missed [$key2]! WHY? FIX THIS!!! 2\n"); } } } } return \@found; } sub setup_params($$) { my ($inf,$inr) = @_; my %params = (); my $rparams = \%params; ${$rparams}{'SI_MAIN_IN_FILE'} = $inf; ${$rparams}{'SI_CURR_IN_FILE'} = $inf; ${$rparams}{'SI_CURR_IN_ROOT'} = $inr; my %files_done = (); my $rfd = \%files_done; ${$rparams}{'SI_REF_FILES_DONE'} = $rfd; my @done_order = (); my $rdo = \@done_order; ${$rparams}{'SI_RA_FILES_DONE'} = $rdo; my @incs = (); ${$rparams}{'SI_REF_INCS_ARRAY'} = \@incs; my %incs_done = (); my $rid = \%incs_done; ${$rparams}{'SI_REF_INCS_DONE'} = $rid; ${$rparams}{'SI_CURR_DBG_SI01'} = 0; ${$rparams}{'SI_CURR_DBG_SI02'} = 0; ${$rparams}{'SI_CURR_DBG_SI03'} = 0; ${$rparams}{'SI_CURR_DONE_SCAN'} = 0; ${$rparams}{'SI_CURR_DIR_SCAN'} = []; ${$rparams}{'SI_REF_INCLUDE_DIRS'} = \@g_INC_dirs; return $rparams; } sub si_show_count($) { my $ra = shift; my $cnt = scalar @{$ra}; prt("List $cnt include files "); prt("excluding externals ") if ($exclude_externals && !VERB9()); prt("no output (-o) given ") if (length($g_out_file) == 0); prt("\n"); my $msg = join("\n",sort @{$ra}); $msg .= "\n"; if (length($g_out_file)) { write2file($msg,$g_out_file); prt("List written to [$g_out_file]\n"); } prt($msg) if (VERB1()); $cnt = scalar @missing_files; prt("\nMissed $cnt includes...\n"); my ($i,$inf,$len,$min,$lnn); $min = 0; for ($i = 0; $i < $cnt; $i++) { $ra = $missing_files[$i]; $msg = ${$ra}[0]; $len = length($msg); $min = $len if ($len > $min); } # 0 1 2 3 4 5 6 # push(@{$rincs},[$ff,$inc,$ch,$lnn,$inf,$ok,$fnd]); for ($i = 0; $i < $cnt; $i++) { $ra = $missing_files[$i]; $msg = ${$ra}[0]; $lnn = ${$ra}[3]; $inf = ${$ra}[4]; $msg .= ' ' while (length($msg) < $min); prt("$msg in [$inf] at $lnn\n"); } } sub si_show_finds() { my $cnt = scalar @finds; my $fcnt = scalar keys(%scanned_files); my ($inf,$lnn,$find,$ra,$tline); if ($cnt) { prt("Have $cnt finds... scanned $total_lines lines from $fcnt files...\n"); foreach $ra (@finds) { $inf = ${$ra}[0]; $lnn = ${$ra}[1]; $find = ${$ra}[2]; $tline = ${$ra}[3]; prt("$lnn: $inf, found [$find]\n"); prt("Line: [$tline]\n") if (VERB1()); } } } ######################################### ### MAIN ### parse_args(@ARGV); my $rph = setup_params($g_in_file,$g_in_root); si_process_in_file($rph,0); my $ra = si_show_found_list($rph); si_show_count($ra); si_show_finds(); pgm_exit(0,""); ######################################## sub need_arg { my ($arg,@av) = @_; pgm_exit(1,"ERROR: [$arg] must have following argument!\n") if (!@av); } sub parse_args { my (@av) = @_; my ($arg,$sarg,$tmp,@arr,$cnt); while (@av) { $arg = $av[0]; if ($arg =~ /^-/) { $sarg = substr($arg,1); $sarg = substr($sarg,1) while ($sarg =~ /^-/); if (($sarg =~ /^h/i)||($sarg eq '?')) { give_help(); pgm_exit(0,"Help exit(0)"); } elsif ($sarg =~ /^f/) { need_arg(@av); shift @av; $sarg = strip_quotes($av[0]); push(@find_list,$sarg); prt("Added [$sarg] to find list\n") if (VERB1()); } elsif ($sarg =~ /^i/) { need_arg(@av); shift @av; $sarg = $av[0]; $g_in_file = File::Spec->rel2abs($sarg); prt("Set INPUT file to [$g_in_file]\n") if (VERB1()); } elsif ($sarg =~ /^I/) { need_arg(@av); shift @av; $sarg = $av[0]; if ($os =~ /win/i) { @arr = split(/;/,$sarg); } else { @arr = split(/:/,$sarg); } foreach $sarg (@arr) { $tmp = File::Spec->rel2abs($sarg); if (-d $tmp) { push(@g_INC_dirs,$tmp); prt("Added INC directory [$tmp]\n") if (VERB1()); } else { pgm_exit(1,"ERROR: Directory [$tmp], rel [$sarg] does NOT exist!\n"); } } } elsif ($sarg =~ /^l/) { $load_log = 1; } elsif ($sarg =~ /^o/) { need_arg(@av); shift @av; $sarg = $av[0]; $g_out_file = $sarg; prt("Set output to [$g_out_file]\n") if (VERB1()); } elsif ($sarg =~ /^r/) { need_arg(@av); shift @av; $sarg = $av[0]; $g_in_root = File::Spec->rel2abs($sarg); prt("Set root to [$g_in_root]\n") if (VERB1()); } elsif ($sarg =~ /^v/i) { if ($sarg =~ /^v(\d+)$/) { $verbosity = $1; } else { while ($sarg =~ /^v/i) { $verbosity++; $sarg = substr($sarg,1); } } prt("Set verbosity to $verbosity\n") if (VERB1()); } else { pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n"); } } else { $g_in_file = File::Spec->rel2abs($arg); prt("Set input to [$g_in_file]\n") if (VERB1()); } shift @av; } if ($debug_on) { prtw("WARNING: DEBUG is ON\n"); if (length($g_in_file) == 0) { $g_in_file = File::Spec->rel2abs($def_file); prt("[debug_on] Set input to DEFAULT [$g_in_file]\n"); } if (length($g_in_root) == 0) { if (length($def_root)) { $g_in_root = File::Spec->rel2abs($def_root); } else { ($arg,$g_in_root) = fileparse($g_in_file); } prt("[debug_on] Set root to DEFAULT [$g_in_root]\n"); } $verbosity = 9; $load_log = 1; } if (length($g_in_file) == 0) { pgm_exit(1,"ERROR: No input files found in command!\n"); } if (! -f $g_in_file) { pgm_exit(1,"ERROR: Unable to find in file [$g_in_file]! Check name, location...\n"); } if (length($g_in_root) == 0) { ($arg,$g_in_root) = fileparse($g_in_file); } fix_dir_string(\$g_in_root); if (! -d $g_in_root) { pgm_exit(1,"ERROR: Unable to find in directory [$g_in_root]! Check name, location...\n"); } } sub give_help { prt("$pgmname: $VERS\n"); prt("Usage: $pgmname [options] in-file\n"); prt("Options:\n"); prt(" --help (-h or -?) = This help, and exit 0.\n"); prt(" --in (-i) = Alternative to set INPUT file.\n"); prt(" --INC (-I) = Set include search directories.\n"); prt(" --load (-l) = Load LOG at end. ($outfile)\n"); prt(" --LINUX (-L) = Include search of 'linux' include folder.\n"); prt(" --out file (-o) = Output the list to this file.\n"); prt(" --root (-r) = Set ROOT directory.\n"); prt(" --verb[n] (-v) = Bump [or set] verbosity. def=$verbosity\n"); prt(" --find word (-f) = Find this 'word' in the files.\n"); prt("\n"); prt("Purpose:\n"); prt(" Treat the input files as a C/C++ file, and search for 'include' items.\n"); prt(" Then each 'included' file will be searched, and a summary shown at the end.\n"); prt("Notes:\n"); prt(" If no root directory is given, the the directory of the in-file will be used as\n"); prt(" the root. Obviously both the in-file and root directory MUST exist.\n"); prt("The -I can be a list, separated with ';' in win, and ':' in unix.\n"); } # eof - showincs.pl