#!/perl -w
# NAME: findinc.pl
# AIM: Scan all headers to find input string ...
use strict;
use warnings;
use File::Basename;
unshift(@INC, 'C:/GTools/perl');
require 'logfile.pl' or die "Unable to load logfile.pl ...\n";
# log file stuff
my ($LF);
my $pgmname = $0;
if ($pgmname =~ /\w{1}:\\.*/) {
	my @tmpsp = split(/\\/,$pgmname);
	$pgmname = $tmpsp[-1];
}
my $outfile = "temp.$pgmname.txt";
open_log($outfile);
###prt( "$0 ... Hello, World ...\n" );

# check ENVIRONMENT for this
my $include = 'INCLUDE';

# ================================================================
# FIND STRING
# ================================================================
# FEATURES
my $whole = 1;
my $nocase = 0;
my $shownotwhole = 0;
my $add_unix_includes = 0;  # include Ubuntu /usr/include list - in my C:\Projects\include ...
my $use_unix_only = 0;
my $unix_includes = 'C:\Projects\include';
my $add_unix_apple = 0;     # include APPLE includes, from Louis machine
my $apple_incs = "C:\\DTEMP\\usr\\include";
my $incddk = 0;
my $trimall = 1;    # show only the trim_all line
my $showprocessed = 0;  # show "$fold_count: Processed: [$inf] ... $hfcnt files, $lncnt lines, $fndcnt finds ...
my $exclude_comments = 1;
my $maxlines = 100000;

# FIND THIS
my $find = 'time_t';
##my $find = '__time_t';
##my $find = 'major_t';   # hmmm, does NOT exist in unix headers, but is defined as 'int' in a autogen config.h or tar 1.20
##my $find = 'EINVAL';
##my $find = 'size_t';    # NUMEROUSE
##my $find = 'CP_UTF8';   # WinNls.h (101)
##my $find = 'execvp';
##my $find = 'uintmax_t';
##my $find = 'mkdir';
##my $find = 'F_OK';
##my $find = 'getline';
###my $find = 'group';
###my $find = 'passwd';
##my $find = 'F_GETFD';
##my $find = 'major_t';
##my $find = 'S_IRWXUGO';
##my $find = 'UINTMAX_MAX';
##my $find = 'S_ISUID';
###my $find = 'S_IFDIR';
###my $find = 'S_ISDIR';
###my $find = 'S_IRUSR';
###my $find = 'option';
###my $find = '__dirstream';
###my $find = 'DIR';
##my $find = 'STD_ERROR_HANDLE';
##my $find = "EINTR";
##my $find = "O_BINARY";
##my $find = "MAX_";
##my $find = "SSIZE_T";
##my $find = "_CRT_DOUBLE";
##my $find = "off_t";     # typedef long off_t #define _OFF_T_DEFINED wchar.h & sys\types.h
#my $find = 'FILE_OFFSET_BITS';
##my $find = 'LARGE_FILES';
##my $find = 'HANDLE';
##my $find = "WIN64";
##my $find = '_INTEGRAL_MAX_BITS';
##my $find = '_USE_32BIT_TIME_T';
##my $find = 'intptr_t';
##my $find = '_stati64';
##my $find = 'uint32_t';
##my $find = 'stat.inl';
##my $find = 'UNREFERENCED_PARAMETER';
##my $find = '220326';
##my $find = 'SRCINVERT';
##my $find = "WM_MOUSEMOVE";
##my $find = '_CRT_SECURE_NO_DEPRECATE';
##my $find = '_MRTIMP';
##my $find = 'FILETIME';
##my $find = '_S_IWRITE';
##my $find = 'POLLFD';
##my $find = 'timespec';
###my $find = 'timeval';
###my $find = 'CLSID';
###my $find = "NTSTRSAFE_H_INCLUDED";
###my $find = "strto";
###my $find = "_CRT_NONSTDC_DEPRECATE";
###my $find = "stricmp";
###my $find = "INVALID_SOCKET";
###my $find = "HINTERNET";
###my $find = "PHTTP_REQUEST";
###my $find = 'EINTR';
###my $find = 'WINAPI';
###my $find = 'socklen_t';
###my $find = '64-bit';
###my $find = 'LONGLONG';

# program variables
my @found = ();
my @foundtd = ();
my @foundif = ();
my @foundit = ();
my @folders = ();
my @functions = ();
my %vc8_hash = ();
my $vc8_dir = 'C:\Program Files\Microsoft Visual Studio 8\VC\vcpackages\vcprojectengine.dll.config';
my @vc8_incs = ();
my @vc8_found = ( 'C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include', #  907 File(s)     51,017,044 bytes
'C:\Program Files\Debugging Tools for Windows\sdk\inc', #  4 File(s)        780,272 bytes
'C:\Program Files\Debugging Tools for Windows\winext\manifest', #  32 File(s)      1,264,957 bytes
'C:\Program Files\Microsoft DirectX SDK (October 2006)\Include', #   82 File(s)      3,511,805 bytes
'C:\Program Files\Microsoft DirectX SDK (October 2006)\Samples\C++\Common', #  9 File(s)        135,789 bytes
'C:\Program Files\Microsoft DirectX SDK (October 2006)\Samples\C++\DXUT\Core', #  3 File(s)         56,644 bytes
'C:\Program Files\Microsoft DirectX SDK (October 2006)\Samples\C++\DXUT\Optional', #  8 File(s)        111,530 bytes
'C:\Program Files\Microsoft DirectX SDK (October 2006)\Samples\C++\Misc\DxDiagReport',  # 10 File(s)         23,610 bytes
'C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include\atl', #  13 File(s)      1,512,619 bytes
'C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include\crt', #  65 File(s)        608,821 bytes
'C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include\crt\sys', #   5 File(s)         12,467 bytes
'C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include\gl', #  3 File(s)         99,389 bytes
'C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include\mfc', #   44 File(s)        962,431 bytes
#'C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\misc\Include Updates', #  1 File(s)        138,296 bytes
'C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\src\crt', #   79 File(s)        474,787 bytes
'C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\src\crt\sys', # 5 File(s)         15,741 bytes
'C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\src\mfc', #  21 File(s)        644,692 bytes
'C:\Program Files\Microsoft SQL Server\90\SDK\Include', #    4 File(s)        169,617 bytes
'C:\Program Files\Microsoft Visual Studio 8\VC\include', #   72 File(s)      1,284,522 bytes
'C:\Program Files\Microsoft Visual Studio 8\VC\include\msclr', #   8 File(s)        151,706 bytes
'C:\Program Files\Microsoft Visual Studio 8\VC\include\sys', # 5 File(s)         17,462 bytes
);

my @ddk_dirs = (
'C:\WINDDK\inc\wxp', # 259 File(s)     14,038,709 bytes
'C:\WINDDK\inc\wnet', #277 File(s)     14,783,122 bytes
'C:\WINDDK\inc\crt', # 66 File(s)        687,162 bytes
'C:\WINDDK\inc\crt\gl', #  3 File(s)         99,395 bytes
'C:\WINDDK\inc\crt\sys' ); #  5 File(s)         12,477 bytes

# debug
# #########################################
my $dbg1 = 0;	# show all config lines
my $dbg2 = 0;	# show 'Processing ...'
my $dbg3 = 0;	# show expansionss ...
my $dbg4 = 0;	# show vc8 BAT loading ...
my $dbg5 = 0;	# show folder about to be searched
my $dbg6 = 0;	# show NOT found in environment
my $dbg7 = 0;	# show "INCLUDE=[$iln] ...
my $dbg8 = 0;	# show "Count ".scalar @v8." others ...
my $dbg10 = 0;	# show "Warnings: Failed to OPEN [$inf] ...
my $dbg11 = 0;  # show "WARNING: $of is NOT a valid folder ... check name, location ...
# #########################################

my $file = '';
my $fold_count = 0;
my $file_lines = 0;
my $total_lines = 0;
my $find_count = 0;
my $tot_finds = 0;
my $tot_files = 0;
my $last_file = '';

my $tot_folder_count = 0;
my $tot_line_count = 0;
my $tot_file_count = 0;

parse_args(@ARGV);

prt( "Finding [$find] ... " );
show_config();

my $envstg = $ENV{$include};
if (defined $envstg) {
	my @ar = split(';',$envstg);
    foreach my $it (@ar) {
        if (length($it)) {
            if (($it eq '.')||($it eq '..')) {
                next;
            }
            if (-d $it) {
                add_sub_directories($it);
            }
        }
    }

} else {
	prt( "$include NOT found in environment ...\n" ) if ($dbg6);
}
my $vc8_env = $ENV{"VS80COMNTOOLS"};
if (defined $vc8_env) {
	# we have MSVC8
	my $vc8_bat = $vc8_env . "vsvars32.bat";
	if (-f $vc8_bat) {
		load_vc8_bat($vc8_bat);
	} else {
		prt( "WARNING: [$vc8_bat] not found ...\n" );
	}
}

my @v8 = get_vc8_dirs();
if ($incddk) {
	push(@v8, @ddk_dirs);
}

prt( "Count ".scalar @v8." others ...\n" ) if ($dbg8);
foreach my $d (@v8) {
    ###add_folder_includes($d);
    if (length($d)) {
        if (($d eq '.')||($d eq '..')) {
            next;
        }
        if (-d $d) {
            add_sub_directories($d);
        }
    }
}

add_folder_includes( $apple_incs ) if ($add_unix_apple);
if ($add_unix_includes) {
    @folders = () if ($use_unix_only);
    add_folder_includes( $unix_includes )
}

my $fdrcnt = scalar @folders;
prt( "Will search (up to) $fdrcnt folders ...\n" );
if ($dbg5) {
	foreach $file (@folders) {
		prt( "$file\n" );
	}
}
foreach $file (@folders) {
    if ($file eq $unix_includes) {
        prt( "Commencing UNIX includes ($file) ...\n" );
    } elsif ($file eq $apple_incs) {
        prt( "Commencing APPLE includes ($file) ...\n" );
    }
	process_folder($file);
}

prt( "Done $tot_line_count lines ... $tot_file_count files, $tot_folder_count folders ...\n" );

my $itcnt = scalar @foundit;
my $fcnt = scalar @found;
my $tcnt = scalar @foundtd;
my $icnt = scalar @foundif;
my $funccnt = scalar @functions;
my $donecnt = 0;
# output of FINDS
if ($itcnt) {
	prt( "\nFound $itcnt ... not define, typedef, ...\n" );
	foreach $file (@foundit) {
		prt( "$file\n" );
		$donecnt++;
	}
}
if ($fcnt) {
	prt( "\nFound $fcnt with #define ...\n" );
	foreach $file (@found) {
		prt( "$file\n" );
		$donecnt++;
	}
}
if ($tcnt) {
	prt( "\nFound $tcnt with typedef ...\n" );
	foreach $file (@foundtd) {
		prt( "$file\n" );
		$donecnt++;
	}
}
if ($icnt) {
	prt( "\nFound $icnt with #if ...\n" );
	foreach $file (@foundif) {
		prt( "$file\n" );
		$donecnt++;
	}
}
if ($funccnt) {
	prt( "\nFound $funccnt functions ...\n" );
	foreach $file (@functions) {
	    prt("$file ");
		$donecnt++;
	}
}
prt( "No special finds ...\n" ) if (!$donecnt);
# FINAL OUTPUT SUMMARY
prt( "\n" );
prt( "In finding [$find] ... with " );
show_config();
prt( "Processed $fold_count folders, $tot_files files, $total_lines lines, $tot_finds finds ...\n" );
prt( "\n" );

close_log($outfile,1);
exit(0);
#####################################################################

sub add_2_folders {
    my ($dir) = shift;
	my $lcd = lc($dir);
	foreach $file (@folders) {
		my $lcf = lc($file);
		if ($lcd eq $lcf) {
            return;
		}
	}
	push(@folders, $dir);
}

sub add_sub_directories {
    my ($inf) = shift;
	if ( opendir( DIR, $inf ) ) {
        add_2_folders( $inf ) ;
		my @fils = readdir(DIR);
		closedir DIR;
        foreach my $fil (@fils) {
            if (($fil eq '.')||($fil eq '..')) {
                next;
            }
            my $ff = $inf;
            $ff .= "\\" if !($ff =~ /(\\|\/)$/ );
            $ff .= $fil;
            if (-d $ff) {
                add_2_folders($ff);
            }
        }
    } else {
        prt( "WARNING: Can NOT open $inf ...\n" );
    }
}

sub add_folder_includes {
    my ($of) = shift;
    if (-d $of) {
        add_sub_directories( $of );
    } else {
        prt( "WARNING: $of is NOT a valid folder ... check name, location ...\n" ) if ($dbg11);
    }
}


sub load_vc8_cfg {
	my ($vc8c) = shift;
	if (open INF, "<$vc8c") {
		my @clns = <INF>;
		close INF;
		foreach my $cln (@clns) {
			chomp $cln;
			$cln = trim_all($cln);
			prt( "$cln\n" ) if ($dbg1);
			if ($cln =~ /include=\"(.+)\"/i) {
				my $iln = $1;
				my @vc8i = split(';',$iln);
				prt( "INCLUDE=[$iln]\n" ) if ($dbg7);
				foreach my $itm (@vc8i) {
					push(@vc8_incs, $itm);
				}
			}
		}
	} else {
		prt( "WARNING: can not open [$vc8c] ... $! ...\n" );
	}
}

sub load_vc8_bat {
	my ($vc8b) = shift;
	if (open INB, "<$vc8b") {
		my @lns = <INB>;
		close INB;
		foreach my $ln (@lns) {
			chomp $ln;
			$ln = trim_all($ln);
			if ($ln =~ /\@*SET\s+(.*)/) {
				my @arr = split(/=/,$1);
				my $sz = scalar @arr;
				if ($sz == 2) {
					my $ky = uc($arr[0]);
					my $val = $arr[1];
					$vc8_hash{$ky} = $val;
					prt( "[$ky]=[$val]\n" ) if ($dbg4);
					if ($ky =~ /^VCINSTALLDIR$/i) {
						# got the INSTALL DIECTORY
						my $vc8_cfg = $val. "\\vcpackages\\vcprojectengine.dll.config";
						if (-f $vc8_cfg) {
							load_vc8_cfg($vc8_cfg);
						} else {
							prt( "WARNING: [$vc8_cfg] does not exist ...\n" );
						}
					}

				} else {
					prt( "SET $1\n" );
				}
			}
		}
		foreach my $item (@vc8_incs) {
			# expand
			if ($item =~ /.*\$\((.+)\).+/) {
				my $eit = uc($1);
				prt( "Item [$eit] in [$item] needs expansion ...\n" ) if ($dbg3);
				foreach my $key (keys %vc8_hash) {
					if ($key eq $eit) {
						$item =~ s/\$\($key\)/$vc8_hash{$key}\\/i;
						prt( "New item = [$item] ...\n" ) if ($dbg3);
						last;
					}
				}
			}
			###push(@folders, $item) if (length($item));
			add_folder_includes( $item ) if (length($item));
		}
	} else {
		prt( "WARNING: No open of [$vc8b] ... $! ...\n" );
	}
}

sub is_whole_test {
	my ($ln) = shift;
	if ($ln eq $find) {
		return 1;
	}
	my $ind = index($ln, $find);
	if ($ind >= 0) {
		if ($ind == 0) {
			my $bal = substr($ln,length($find));
			if ($ln =~ /^$find[\s\),;_]+/) {
				return 1;
			}
		} else {
			if ($ln =~ /[\s\(,;\*_]+$find[\s\),;_]+/) {
				return 1;
			}
		}
	}
	return 0;
}

sub is_whole {
	my ($ln) = shift;
	my ($bgn, $end, $ord);
	my $found = 0;
	if ($nocase) {
		if ( $ln =~ /^(.*)$find(.*)$/i ) {
			$bgn = $1;
			$end = $2;
			$found = 1;
		}
	} else {
		if ( $ln =~ /^(.*)$find(.*)$/ ) {
			$bgn = $1;
			$end = $2;
			$found = 1;
		}
	}
	if ($found) {
		$ord = length($bgn);
		if ($ord >= 0) {
			###my $bgn = substr($ln,0,$ord);
			###my $end = substr($ln,$ord+length($find));
			my $bl = length($bgn);
			my $el = length($end);
			if ( ($bl == 0) && ($el == 0) ) {
				#prt( "Found $find in $line ...index $ord ... [NULL], [NULL]\n" );
				return 1;	# whole in that it is the ONLY word in the line
			} elsif ( $bl && $el ) {
				# got BEGIN and END
				if ( !($bgn =~ /\w$/) && !($end =~ /^\w/) ) {
					#prt( "Found $find in $line ...index $ord... [$bgn], [$end]\n" );
					return 1;
				}
			} elsif ( $bl ) {
				# only $bl
				if ( !($bgn =~ /\w$/) ) {
					#prt( "Found $find in $line ...index $ord... [$bgn], [NULL]\n" );
					return 1;
				}
			} else {
				# got $el
				if ( !($end =~ /^\w/) ) {
					#prt( "Found $find in $line ...index $ord... [NULL], [$end]\n" );
					return 1;
				}
			}
		}
	}
	return 0;
}

sub C_comment_starts {
    my ($txt) = shift;
    my $len = length($txt);
    my $ptxt = '';
    my $ttxt = '';
    my ($k, $ch, $pch, $k2, $nch);
    for ($k = 0; $k < $len; $k++) {
        $k2 = $k + 1;
        $ch = substr($txt,$k,1);
        $nch = (($k2 < $len) ? substr($txt,$k2,1) : '');
        if (($ch eq '/')&&($nch eq '*')) {
            $ttxt = substr($txt,($k2+1));
            return $k2, $ptxt, $ttxt;   # return offset, previous and begin comment
        }
        $pch = $ch;
        $ptxt .= $ch;
    }
    return 0, $ptxt, $ttxt;
}

sub inline_comment_starts {
    my ($txt) = shift;
    my $len = length($txt);
    my $ptxt = '';
    my ($k, $ch, $pch, $k2, $nch);
    for ($k = 0; $k < $len; $k++) {
        $k2 = $k + 1;
        $ch = substr($txt,$k,1);
        $nch = (($k2 < $len) ? substr($txt,$k2,1) : '');
        if (($ch eq '/')&&($nch eq '/')) {
            return $k2, $ptxt;   # return offset, previous
        }
        $pch = $ch;
        $ptxt .= $ch;
    }
    return 0, $ptxt;
}

sub C_comment_ends {
    my ($txt) = shift;
    my $len = length($txt);
    my $ttxt = '';
    my ($k, $ch, $pch, $k2, $nch);
    for ($k = 0; $k < $len; $k++) {
        $k2 = $k + 1;
        $ch = substr($txt,$k,1);
        $nch = (($k2 < $len) ? substr($txt,$k2,1) : '');
        if (($ch eq '*')&&($nch eq '/')) {
            $ttxt = substr($txt,($k2+1));
            return $k2, $ttxt;  # return trailing 
        }
        $pch = $ch;
    }
    return 0, $ttxt;
}


sub remove_comments {
    my (@lns) = @_;
    my @nlns = ();
    my ($ise, $atxt, $ctxt);
    my ($isc,$ptxt,$ttxt);

    my $incomm = 0;
    foreach my $ln (@lns) {
        chomp $ln;
        if ($incomm) {
            ($ise,$atxt) = C_comment_ends($ln);
            if ($ise) {
                $incomm = 0;
                $ctxt = trim_all($atxt);
                if (length($ctxt)) {
                    $ln = $ctxt;
                } else {
                    next;
                }
            } else {
                next;
            }
        }
        ($isc,$ptxt,$ttxt) = C_comment_starts($ln);
        if ($isc) {
            # C comment starting ...
            ($ise,$atxt) = C_comment_ends($ttxt);
            if ($ise) {
                $ptxt = trim_all($ptxt);
                $atxt = trim_all($atxt);
                $ctxt = $ptxt;      # get any PREVIOUS, to /* commant start
                $ctxt .= ' ' if (length($ctxt) && length($atxt) && ($atxt ne ';'));
                $ctxt .= $atxt if length($atxt);    # add any AFTER */ text
                $ctxt = trim_all($ctxt);
                if (length($ctxt)) {
                    $ln = $ctxt;    # got some TAIL text
                } else {
                    next;   # else nothing after */ on this line - goto NEXT
                }
            } else {
                $incomm = 1;    # line contains '/*' comment start ...
                $ptxt = trim_all($ptxt);    # trim any previous
                if (length($ptxt)) {
                    $ln = $ptxt;    # keep the previous
                } else {
                    next;   # else go to NEXT line
                }
            }
        } else {
            ($isc,$ptxt) = inline_comment_starts($ln);
            if ($isc) {
                $ctxt = trim_all($ptxt);
                if (length($ctxt)) {
                    $ln = $ctxt;
                } else {
                    next;   # got no previous to '//' start
                }
            }
        }
        push(@nlns, $ln) if length($ln);
    }
    return @nlns;
}

sub process_file {
	my ($ff) = shift;
	my $iret = 0;
	my ($bgn, $end, $lbgn, $lend);
	if (open INF, "<$ff") {
		my @lines = <INF>;
		close INF;
        $tot_file_count++;
		$iret = 1;
		my $lnno = 0;
        # PROCESS FILE LINE BY LINE
        ###########################
        @lines = remove_comments(@lines) if ($exclude_comments);
		foreach my $line (@lines) {
            $tot_line_count++;
            prt( "Done $tot_line_count lines ... $tot_file_count files, $tot_folder_count folders ...\n" ) if (($tot_line_count % $maxlines) == 0);
			$lnno++;
			chomp $line;
            $line = trim_all($line) if ($trimall);
			my $fnd = 0;
			my $fnd2 = 0;
			my $found = 0;
			if ($nocase) {
				if ( $line =~ /^(.*)$find(.*)$/i ) {
					$bgn = $1;
					$end = $2;
					$found = 1;
				}
			} else {
				if ( $line =~ /^(.*)$find(.*)$/ ) {
					$bgn = $1;
					$end = $2;
					$found = 1;
				}
			}
			if ($found) {
				$fnd2 = 1;	# if it FOUND in the LINE, at least
				if ($whole) {
					###if ($line =~ /[\s\(,;\*_]*$find[\s\),;_]+/) {
					if (is_whole($line)) {
						$fnd = 1;
					}
				} else {
					$fnd = 1;
				}
			}

			if ($fnd) {
				$find_count++;
				if ($line =~ /#\s*define/) {
					push(@found, "$line - $ff ($lnno)");
				} elsif ($line =~ /typedef\s+/) {
					push(@foundtd, "$line - $ff ($lnno)");
				} elsif ($line =~ /#\s*if\w*\s*/) {
					push(@foundif, "$line - $ff ($lnno)");
				} else {
					push(@foundit, "$line - $ff ($lnno)");
				}
                prt( "File: [$ff]\n" ) if ($last_file ne $ff);
				prt( " $lnno: [$line]\n" );
                $last_file = $ff;
			} elsif ($fnd2) {
                if ($shownotwhole) {
    				prt( "NOT WHOLE [$line] - $ff ($lnno)\n" );
                }
			}
			if (($fnd || $fnd2)&&($find eq "_CRT_NONSTDC_DEPRECATE")) {
				if ($line =~ /_CRT_NONSTDC_DEPRECATE\((\w+)\)\s+/) {
					my $func = $1;
					$func = substr($func,1) if ($func =~ /^_/);
					prt( "$func\n" );
					push(@functions, $func);
				}
			}
		}
		$file_lines = $lnno;
	} else {
		prt( "Warning: Failed to open [$ff] ...\n" );
	}
	return $iret;
}

sub process_folder {
	my ($inf) = shift;
	prt( "Processing $inf folder ...\n" ) if ($dbg2);
	if ( opendir( DIR, $inf ) ) {
		my @files = readdir(DIR);
		closedir DIR;
        $tot_folder_count++;
		$fold_count++;
		my $hfcnt = 0;
		my $lncnt = 0;
		my $fndcnt = 0;
        my @subdirs = ();
		foreach my $fl (@files) {
			if (($fl eq '.') || ($fl eq '..')) {
				next;
			}
			my $ff = $inf;
			$ff .= "\\" if ( !( substr($inf,-1,1) =~ /[\\\/]+/ ) );
			$ff .= $fl;
            if (-d $ff) {
                add_2_folders($ff);
                next;
            }
			my ($nm, $dir, $ext) = fileparse( $fl, qr/\.[^.]*/ );
			my $lcext = lc($ext);
            if (length($ext) == 0) {
                ## let these through
            } elsif ( !(($lcext eq '.h')||($lcext eq '.hxx')||($lcext eq '.hpp')) ) {
				next;
			}
			$file_lines = 0;
			$find_count = 0;
			if (process_file($ff)) {
				$total_lines += $file_lines;
				$lncnt += $file_lines;
				$fndcnt += $find_count;
				$tot_finds += $find_count;
				$hfcnt++;
			}
		}
		$tot_files += $hfcnt;
		prt( "$fold_count: Processed: [$inf] ... $hfcnt files, $lncnt lines, $fndcnt finds ...\n" ) if ($showprocessed);
	} else {
		prt( "Warnings: Failed to OPEN [$inf] ...\n" ) if ($dbg10);
	}
}

#######################

sub get_vc8_dirs {
	return @vc8_found;
}

sub show_config {
	prt( "Options: whole=". ($whole ? "On" : "Off") ." " );
	prt( " case=". ($nocase ? "Off" : "On") ." " );
	prt( " ddk=" . ($incddk ? "On" : "Off") . " " );
    prt( " unix=". (( $add_unix_includes && $use_unix_only ) ? "Only" : ($add_unix_includes ? "On" : "Off") . " " ));
    prt( " xcomm=". ($exclude_comments ? "On" : "Off") . " " );
	prt( "\n" );
}

sub give_help {
	prt( "$pgmname: [Options] find_string ...\n" );
	prt( "Options:\n" );
	prt( " -?        = This brief help....\n" );
	prt( " -whole    = Only WHOLE (def=". ($whole ? "On" : "Off") .")\n" );
	prt( " -notwhole = NOT WHOLE\n" );
	prt( " -case     = Case sensitive. (def=". ($nocase ? "Off" : "On") .")\n" );
	prt( " -nocase   = Case insensitive.\n" );
	prt( " -ddk      = Include DDK folders (def=". ($incddk ? "On" : "Off") . ")\n" );
	prt( " -noddk    = Exclude DDK folders\n" );
    prt( " -unix     = Include 'unix' includes (def=". ($add_unix_includes ? "On" : "Off"). " in $unix_includes )\n" );
	prt( " -nounix   = Exclude 'unix' folder\n" );
	exit(0);
}

# parse arguments ...
sub parse_args {
	my (@av) = @_;	# = (@ARGV);
	while (@av) {
		my $arg = $av[0];
		my $ch = substr($arg,0,1);
		if (($ch eq '-')||($ch eq '/')) {
			$arg = substr($arg,1);
			if (($arg eq '?')||($arg =~ /^h$/i)) {
				give_help();
			} elsif ($arg eq 'whole') {
				$whole = 1;
				prt( "Setting WHOLE ...\n" );
			} elsif ($arg eq 'notwhole') {
				$whole = 0;
				prt( "Setting NOT WHOLE ...\n" );
			} elsif ($arg eq 'case') {
				$nocase = 0;
				prt( "Setting CASE ...\n" );
			} elsif ($arg eq 'nocase') {
				$nocase = 1;
				prt( "Setting NO CASE ...\n" );
			} elsif ($arg eq 'ddk') {
				$incddk = 1;
				prt( "Setting INCLUDE DDK folder ...\n" );
			} elsif ($arg eq 'noddk') {
				$incddk = 0;
				prt( "Setting NOT INCLUDE DDK folder ...\n" );
            } elsif ($arg eq 'unix') {
                $add_unix_includes = 1;
				prt( "Setting INCLUDE UNIX folder ($unix_includes)...\n" );
            } elsif ($arg eq 'nounix') {
                $add_unix_includes = 0;
				prt( "Setting NOT INCLUDE UNIX folder ($unix_includes)...\n" );
			} else {
				prt( "ERROR: Unknown option -$arg ...\n" );
				give_help();
			}
		} else {
			$find = $arg;
			prt( "Setting FIND to [$find] ...\n" );
		}

		shift @av;
	}
}

# eof - findinc.pl

