#!/usr/bin/perl
#
#     CREATOR: DAn Williams
#        DATE: Sept 2 2000
# DESCRIPTION: maps out include files from C programs
#    FILENAME: IncludeMap.pl
#     STARTED: see date
#   PLATFORMS: Linux 
#   

# EXAMPLE: (letters represent filenames, where each was #included from the file above)
#            A
#    |-------|-------|
#    B       C       D
# /--|   /-------\   |-------|-----\
# E  F   G       H   I       J     K
#
#
# DATA OUTPUT:
#   TREE: (A,B,E,F,C,G,H,D,I,J,K)
#    DEP: (0,1,2,2,1,2,2,1,2,2,2)
#
# PROGRAM OUTPUT:
#
# A
# |
# +-B
# | +-E
# | |
# | +-F
# |
# +-C
# | +-G
# | |
# | +-H
# |
# +-D
#   +-I
#   |
#   +-J
#   |
#   +-K
#
# NOTES:
#  -I should be using hash tables, but there's enough to think about as is...
#  -this will also pickup on any #includes that are commented out.
#  -I feel guilt for having this many comments in an interperted language... how ironic.
#  -its been subbed to death, converts to hash easy though...
#  -feed me something recursive and I'll regurgitate it, the hard way.

use IO::File;

$InputFile = new IO::File;
$InputFileName = $ARGV[0];

$curLev = 1; #initial tree level

clearPre();
clearPost();
addToPre($InputFileName, 0);

do {
    $ok = 0; #assume worst case
    while (@preTree != 0) {
        # only check files that are from the prev. level
	if (moveItemFromPreToPost() == ($curLev-1)) {
	    #if an item is found in any file, we have to make a new pass
	    $ok |= findItems(getWorkingFileName());
	}
    }
    moveAllFromPostToPre(); # reset environment
    clearPost();
    $curLev++; #next level
} while ($ok);

displayResult();
#EOC (end of code)

#--------------------------------- displayResult --------------------------
sub displayResult {
    $count = @preTree;
    for ($index = 0; $index < $count; $index++) {
        for ($space=0; $space < @preDep[$index]; $space++) {
	    print "  ";
	}
        print "@preTree[$index]\n"; 
    }	
    return 1;    
}
    
#------------------------------------ debugLine ----------------------------
# print out core data
sub debugLine {
    print "preTree:\n";
    foreach(@preTree) {
	print " ->$_<-\n";
    }

    print "preDep:\n";
    foreach(@preDep) {
	print " ->$_<-\n";
    }

    print "postDep:\n";
    foreach(@postDep) {
	print " ->$_<-\n";
    }

    print "postTree:\n";
    foreach(@postTree) {
	print " ->$_<-\n";
    }
    print "----------\n";
    return 1;
}
    
#-------------------------- moveItemFromPreToPost -----------------------
# move item from beggining of @pre to end of @post
#
# pop(post, shift(pre))
#
sub moveItemFromPreToPost {
    push(@postTree, shift(@preTree));    
    push(@postDep, ($itsLevel = shift(@preDep)));
    return $itsLevel;
}

#-------------------------------- findItems ------------------------------
#find all the #include mentions in a given file
sub findItems {
    $anyFound = 0; # assume worst

    #open file
    if (not open($InputFile, "<$_[0]")) {
	print ("Unable to open input file $_[0]\n");
	return 0;
    }
    
    # read through the whole file
    while (<$InputFile>) {
	
## Catch C include statements
##   $_ =~ /(\s*)(\#include\s)["|<](.*)["|>]/
	
	# found an #include line?
	if ($_ =~ /(\s*)(\#include\s)"(.*)"/) {
            addToPost($3, $curLev); # add it as a sub item to the last main item
	    $anyfound = 1;
	}		   	
    }
    
    #close file and leave
    close ($InputFile);        
    return $anyfound;
}

#------------------------------- moveAllFromPostToPre -----------------------
#move everthing from post to pre
sub moveAllFromPostToPre {
    @preTree = @postTree;
    @preDep = @postDep;
    return 1;
}

#----------------------------------- ClearPost ---------------------------
# clear the post list
sub clearPost {
    @postTree = ();
    @postDep = ();
    return 1;
}

#----------------------------------- ClearPre ---------------------------
# clear the pre list
sub clearPre {
    @preTree = ();
    @preDep = ();
    return 1;
}

#------------------------------------ addToPre ----------------------------
# add item to preList
sub addToPre {
    push (@preTree, $_[0]);
    push (@preDep, $_[1]);
    return 1;
}

#------------------------------------ addToPost ----------------------------
# add item to postList
sub addToPost {
    push (@postTree, $_[0]);
    push (@postDep, $_[1]);
    return 1;
}

#----------------------------------- getWorkingFileName ---------------------
# return the name of the file we should be searching
sub getWorkingFileName {
    return @postTree[@postTree-1];
}










