#! /usr/perl/bin -w
use strict;
use Cwd;

sub searchForStrings;
sub processOneDirectory;
sub correctFileType;

my @remainingDirectories = ();
my $originalDirectory = cwd();
push(@remainingDirectories, $originalDirectory);
my $outputFileName = "$ENV{HOME}/perlFindResult.txt";
unlink ($outputFileName);

while ( my $directoryToProcess = pop (@remainingDirectories))
{
    print "\ndirectoryToProcess: ", $directoryToProcess, "\n";
    #print "\n";
    processOneDirectory($directoryToProcess);
}

sub processOneDirectory
{
    chdir($_[0]);
    if ($_[0] =~ /.*lost\+found.*/)
    {
        print "$_[0]: skipped!\n";
        return;
    }
    my $opendirResult = 0;
    $opendirResult = opendir(DIR, $_[0]);
    if ($opendirResult == 0)
    {
        print "$!\n";
        return;
    }
    my @dirContents = readdir(DIR);
    #print "@dirContents\n";
    for (my $i = 0; $i < @dirContents; $i++)
    {
        if ( (-d $dirContents[$i]) && !(-l $dirContents[$i]) ) #no symblic link
        {
            if ( ($dirContents[$i] =~ /^\./) || ($dirContents[$i] =~ /^\../) )
            {
                #print "$dirContents[$i]: a directory\n"; 
            }
            else
            {
                my $currentDirectory = cwd();
                if ($currentDirectory =~/\/$/)
                {
                    chop ($currentDirectory);
                }
                push (@remainingDirectories, $currentDirectory .
                      "\/$dirContents[$i]");
            }
        }
        elsif (-f $dirContents[$i])
        {
            #print "$dirContents[$i]:a plain file\n";
            if (-T $dirContents[$i])   #interested in text file only
            {
                #print "$dirContents[$i]:a text file\n";
                if ( correctFileType($dirContents[$i]) ==1)
                {
                    searchForStrings($dirContents[$i]);
                }
            }
            else
            {
                #print "$dirContents[$i]:a plain file, but not a text file\n";
            }
        }
        else
        {
            #print "$dirContents[$i]:not a directory, nor a plain file at all\n";
        }
    }
    closedir(DIR);
}

sub searchForStrings
{
    my $fileName = shift (@_);
    my $currentDirectory = cwd();
    if ($currentDirectory =~/\/$/)
    {
        chop ($currentDirectory);
    }
    my $fullPathAndName = $currentDirectory."\/$fileName";
    $fullPathAndName =~ s/$originalDirectory//;
    my @searchStrings = @ARGV;
    my $fileOpenResult = 0;
    $fileOpenResult = open (FH, $fileName);
    if ($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";
            }
            else
            {
                #print "not found\n";
            }
        }
    }
    close (OUTFH);
    close (FH);
}


sub correctFileType
{
    my $fileName = shift (@_);
    if (
            $fileName =~ /.*/        ||    #any file is correct type!!!
            $fileName =~ /\.h$/       ||    #*.h file allowed
            $fileName =~ /\.hh$/      ||    #*.hh file allowed
            $fileName =~ /\.c$/       ||    #*.c file allowed
            $fileName =~ /\.cpp$/           #*.cpp file allowed
       )
    {
        return 1;
    }
    return 0;
}
