#!/usr/local/bin/perl

# Usage: objctree [options] [files]

# Configuration parameters

require "pwd.pl";

&initpwd;

$CPP = 'cc -E';

# Process switches

while ($ARGV[0] =~ /^-/) {
	$_ = shift;
	if (/^-D(.*)/) {
		$defines .= "-D" . ($1 ? $1 : shift);
	}
	elsif (/^-I(.*)/) {
		$includes .= "-I" . ($1 ? $1 : shift);
	}
	elsif (/^-o(.*)/) {
		$outfile = ($1 ? $1 : shift);
	}
	elsif (/^-r(.*)/) {
		$rootclass = ($1 ? $1 : shift);
	}
	else {
		shift;
	}
}

if (-e "./sym" && -d "./sym") {
	open(ALLHEADERS ,">./sym/classtree.h") || die "Can't open ./sym/classtree.h: $!\n";
	$allheadersfile = "./sym/classtree.h";
	foreach $file (@ARGV) {
		print ALLHEADERS "#import \"../".$file."\"\n";
	}
	$cppcommand = "$CPP -O -g -Wall -ObjC $defines $includes $allheadersfile|";
} 
else {
	system("mkdir /tmp/".$ENV{USER});
	open(ALLHEADERS ,">/tmp/$ENV{USER}/classtree.h") || die "Can't open /tmp/$ENV{USER}/classtree.h: $!\n";
	$allheadersfile = "/tmp/".$ENV{USER}."/classtree.h";
	foreach $file (@ARGV) {
		print ALLHEADERS "#import \"".$file."\"\n";
	}
	$cppcommand = "$CPP -O -g -Wall -ObjC $defines $includes -I$ENV{PWD} $allheadersfile|";
}
close ALLHEADERS;

open(CPP,$cppcommand) || die "Can't run cpp: $!\n";
	
while (<CPP>) {
	next unless /^\@interface/;
	($junk,$child,$parent,$trash) = split(/[ \t\n:]+/,$_,4);
	if ($parent) {
		if (! $hierarchy{$parent} || ! ($hierarchy{$parent} =~ /$child/)) {
				$hierarchy{$parent} .= $child . ",";
		}
	}
}
close CPP;

if ($outfile) {
	open(RESULT, ">$outfile") || die "Can't open classtree: $!\n";
} else {
	open(RESULT, ">classtree") || die "Can't open classtree: $!\n";
}


if ($rootclass) {
	&printTree($rootclass);
} else {
	&printTree("Object");
}

print RESULT "\n";

close RESULT;

sub printTree {
	local($name) = @_;
	local($child);
	local(@children);
	
	if ($hierarchy{$name}) {
		@children = split(/,/,$hierarchy{$name});
		print RESULT "{", $name;
		foreach $child (@children) {
			print RESULT ", ";
			&printTree($child);
		}
		print RESULT "}";
	}
	else {
		print RESULT $name;
	}
}
	
	
	

