# Include finder

my %NDir;
my %VisitedFiles;
my $InitDir;
chomp($InitDir=`cd`);

sub NormalizeDirectory {
    $dir = shift;
    if ( "$NDir{$dir}" ne "") {
	return $NDir{$dir};
    }
    chdir($dir);
    chomp($ndir=`cd`);
    chdir($InitDir);
    $NDir{$dir} = $ndir;
    $ndir;
}

sub NormalizeFile {
    $file = shift;
    $arg = $file;
    $file =~ s/.*[\\\/]//;
    $arg =~ s/[\\\/][^\\\/]*$// ;
    if ( "$arg" ne "" && "$arg" ne "$file") {
	$dir = &NormalizeDirectory($arg);
	$file = "$dir/$file";
    } 
    $file;
}

my $WaitInclude;
$WaitInclude = 0;

my $NoPredefInclude;
$NoPredefInclude = 0;

my @Directories;
my @CFiles;
my @ResultFiles;

sub PushDirectory {
    my $arg = shift;
    foreach $dir (@Directories) {
	if ( "$arg" eq "$dir" ) {
	    return ;
	}
    }
    push(@Directories, $arg);
}

sub AnalyzeArg {
    my $arg = shift;
    $option = $arg;
    $option =~ s/@/@@/g;
    $option =~ s/"/@/g;
    $arg =~ s/^\"//;
    $arg =~ s/\"$//;
    if ($WaitInclude) {
      $WaitInclude = 0;
      $arg =~ s/^\"//;
      $arg =~ s/\"$//;
      PushDirectory (&NormalizeDirectory($arg));
    } elsif ($arg =~ /^[-\/]i[^ ]/i) {
      $arg =~ s/^[-\/]i//i;
      $arg =~ s/^\"//;
      $arg =~ s/\"$//;
      PushDirectory(&NormalizeDirectory($arg));
    } elsif ($arg =~ /^[-\/]i\s*$/i) {
      $WaitInclude = 1;
    } elsif ("$arg" eq "-no_predef") {
	  $NoPredefInclude = 1
    }
}

sub AnalyzeFile {
    my $file = shift;
    $file =~ s/^@//;
    # A file indirection : First line is supposed to be options
    # Other lines are filename
    if (open(INDI, "$file")) {
    	my @opt=<INDI>;
    	close(INDI);
        my $opts = $opt[0];
        $curopt = "";
        $inside = 0;
	foreach $l (split(//, $opts)) {
            if ($l eq "\"") {
                if ( $inside == 1) {
		    $inside = 0;
		} else {
		    $inside = 1;
		}
            }
	    if ($l eq " " && $inside == 0 && $curopt ne "") {
		AnalyzeArg $curopt;
		$curopt = "";
	    } else {
		$curopt = "$curopt$l";
            }
        }
	AnalyzeArg $curopt;
        $i = 1;
        while ($i < @opt) {
	    $f = $opt[$i];
	    $f =~ s/\n//;
	    AnalyzeArg $f;
	    $i++;
	}
    } else {
        # Finally it doesn't seem to be a file
    	AnalyzeArg $arg;
    }
}

my $cont;
$cont = 1;
while (@ARGV && $cont) {
	$file = shift;
    if ($file =~ /^--/) {
		$cont = 0;
	} else {
		$file =~ s/.*[\\\/]//;
		push (@CFiles, $file);
		$arg = $file;
		$arg =~ s/[\\\/][^\\\/]*$// ;
		if ( "$arg" ne "" && "$arg" ne "$file") {
			PushDirectory (&NormalizeDirectory($arg));
		} else {
			chomp($cwd=`cd`);
			PushDirectory($cwd);
		}
	}
}


while (@ARGV) {
    $arg = shift;
    if ($arg =~ /^@/) {
        AnalyzeFile $arg
    } else {
    	AnalyzeArg $arg;
    }
}

sub FindFile {
    my $file = $_[0];
    my $res;
    my $dir;
    my $f;

    if ( "$VisitedFiles{$file}" ne "" ) {
	return "";
    }

    foreach $dir (@Directories) {
        $f = "$dir/$file";
	if ( "$VisitedFiles{$f}" ne "" ) {
	    return "";
	}
	if (open(FI, "$f")) {
	    close(FI);
	    push (@ResultFiles, &NormalizeFile("$f"));
	    return "$f";
	}
    }

    $f = &NormalizeFile($file);
    if (open(FI, "$f")) {
	close(FI);
	push (@ResultFiles, "$f");
	return "$f";
    }
    return "";
}

sub FindFileList {
    my $file = $_[0];
    my $efn = FindFile($file);

    if ($efn eq "") {
	return "";
    }

    $VisitedFiles{$file} = 1;
    $VisitedFiles{$efn} = 1;

    open(FI, "$efn");
    my @lines=<FI>;
    close(FI);
    
    my @includes;
    if ($NoPredefInclude) {
	@includes = grep (/#include\s+\".*\"/, @lines);
    } else {
	@includes = grep (/#include\s+[\"<].*[\">]/, @lines);
    }
    foreach $inc (@includes) {
	$inc =~ s/\s*#include\s+\"//;
	$inc =~ s/\".*\n//;
	if ($NoPredefInlcude == 0) {
	    $inc =~ s/\s*#include\s+<//;
	    $inc =~ s/>.*\n//;
	}
	FindFileList ("$inc");
    }
}

foreach $file (@CFiles) {
    FindFileList ("$file");
}

# Write the files.
# Only include files, one per line.
$firstDep = 1;
foreach $res (@ResultFiles) {
  if ($firstDep) {
    $firstDep = 0;
  } else {
    print "$res\n";
  }
}

exit 0;
