#! C:\Perl\bin -w
use strict;
use Cwd;


sub testForCorrectFileTypes
{
    my $nullFile = 0;
    my $fileName = shift (@_);
    if (
            ( -T $fileName )     &&  # commentOut if searching notTextFile 
            $fileName =~ /.*/    ||  # keep this line to search any file, 
                                     # otherwise comment it out if searching 
                                     # code file only 
            $nullFile
       )
    {
        0;
    }
    elsif
        (
            ( -T $fileName )          &&    # We search text file only
            $fileName =~ /\.h$/       ||    #*.h file allowed
            $fileName =~ /\.hh$/      ||    #*.hh file allowed
            $fileName =~ /\.c$/       ||    #*.c file allowed
            $fileName =~ /\.cpp$/     ||    #*.cpp file allowed
            $fileName =~ /\.cxx$/     ||    #*.cxx file allowed
            $nullFile
       )
    {
        1;
    }
    else
    {
        2;
    }
}


my @remainingDirectories = ();
my $originalDirectory = cwd();
if ($originalDirectory =~ /\/$/)
{
    chop ($originalDirectory);
}
my $outputFileNameString = "perlFindResult.txt";
push(@remainingDirectories, $originalDirectory);
my $outputFileName = $originalDirectory . "\/$outputFileNameString";
unlink ($outputFileName);
my $i = 0;
while ( my $directoryToProcess = pop (@remainingDirectories))
{
    #print $directoryToProcess, "\n";
    print "$i    ";
    processOneDirectory($directoryToProcess);
    $i++;
}

sub processOneDirectory
{
    chdir($_[0]);
    if ($_[0] =~ /.*lost\+found.*/)
    {
        print "$_[0]: skipped!\n";
        return;
    }
    my $opendirResult = opendir(DIR, $_[0]);
    if ($opendirResult == 0)
    {
        print "$_[0]: $!\n";
        return;
    }
    my @dirContents = readdir(DIR);
    #print "@dirContents\n";
    for (my $i = 0; $i < @dirContents; $i++)
    {
        if ( -d $dirContents[$i] )
        {
            if ( ($dirContents[$i] =~ /^\./) || ($dirContents[$i] =~ /^\../) )
            {
                #print "$dirContents[$i]: a directory\n"; 
            }
            else
            {
                if ( -l $dirContents[$i] ) 
                {
                    print "skip symbLinkDir: $dirContents[$i]\n";
                }
                else
                {
                    my $currentDirectory = cwd();
                    if ($currentDirectory =~ /\/$/)
                    {
                        chop ($currentDirectory);
                    }
                    push (@remainingDirectories, $currentDirectory .
                          "\/$dirContents[$i]");
                }
            }
        }
        elsif (-f $dirContents[$i] )
        {
            my $testResult = testForCorrectFileTypes($dirContents[$i]);
            if ( $testResult == 0) #interested in ALL files
            {
                searchForStrings($dirContents[$i]);
            }
            elsif ($testResult == 1)
            {
                #print "$dirContents[$i]:a text file\n";
                searchForStrings($dirContents[$i]);
            }
            else
            {
                #not a correct file type
            }
        }
        else
        {
            #print "$dirContents[$i]:not directory, not plain file at all\n";
        }
    }
    closedir(DIR);
}

sub searchForStrings
{
    my $fileName = shift (@_);
    my $currentDirectory = cwd();
    if ($currentDirectory =~ /\/$/)
    {
        chop ($currentDirectory);
    }
    my $fullPathAndName = $currentDirectory ."\/$fileName";
    my $tempOriginalDirectory = $originalDirectory;
    $tempOriginalDirectory =~ s/([*?+])/[$1]/g; #name C++ has problem
    $fullPathAndName =~ s/$tempOriginalDirectory/./;
    my @searchStrings = @ARGV;
    my $fileOpenResult = 0;
    $fileOpenResult = open (FH, $fileName);
    if ( !defined ( $fileOpenResult ) || ( $fileOpenResult == 0 ) )
    {
        print "$fileName: $!\n";
        return;
    }
    open (OUTFH, ">>$outputFileName") or die $!;
    while (<FH>)
    {
        chomp($_);
        for (my $i = 0; $i < @searchStrings; $i++)
        {
            if (/$searchStrings[$i]/)
            {
                print "\n$fullPathAndName\:\:$.: $_\n";
                print OUTFH "$fullPathAndName\:\:$.: $_\n\n";
            }
            else
            {
                #print "not found\n";
            }
        }
    }
    close (OUTFH);
    close (FH);
}


