#!D:\Perl\bin\Perl.exe -ws

# t2docgen.pl - sporadic - sporadic@linux.wku.edu
# Version: Beta 1.2
#
# quick hack for parsing out datablock properties and functions
# from t2 .cs and .gui files.  i'll clean it up later and add 
# support for linking to property definitions once i think of a 
# decent methodology for doing so.
# -sporadic
#
# Usage:
#   ./t2parse.pl <dir>
#
#	Unzip your .vl2 files (i.e. scripts.vl2) and pass the extracted
#	directory as a an agrument.  If a directory is not specified, it 
#	will use your current directory.  Two html files will be created.
#	datablocks.html and functions.html
#
#  Changes:
#  	Beta 1.3
#  	  - added package parsing
#  	  - added links for source files
#  	  - changed the function parsing around a little. it tries to
#  	    split out public and object functions (?this right?)
# 	Beta 1.2
# 	  - added parsing of classes to dervied datablocks
#
#  Known issues:
#  	- the datablock parsing is done in a hash, and therefore each datablock
#  	  listed is unique.  so, if a duplicate name comes up, the class shwon
#  	  for it is replicated.  but, the file the duplicated datablock is in will 
#  	  be shown in the right hand column of datablocks.html.  this does not
#  	  effect classes.html - it uses a different hash for class / datablock 
# 	  parsing.
#

use strict;
use File::Find;


# global html stuff 
my $th1_color = '#FFFF66';
my $th2_color = '#FFCC66';
my $th3_color = '#FFAA66';
my $td1_color = '#66CCFF';
my $td2_color = '#CCCCFF';
my $tr_color = '#66CCFF';
my $file_classes = 'classes.html';
my $file_datablocks = 'datablocks.html';
my $file_functions = 'functions.html';
my $file_packages = 'packages.html';
my $header = '';
my $footer = '';

# setup the html header
$header = $header . "<a name=ToP></a>\n";
$header = $header . "[<a href=$file_classes> CLASSES </a>|";
$header = $header . "<a href=$file_datablocks> DATABLOCKS </a>|";
$header = $header . "<a href=$file_functions> FUNCTIONS </a>|";
$header = $header . "<a href=$file_packages> PACKAGES </a>]";

#setup the html footer
$footer = $footer . "<br><i>generated by t2docgen - ";
$footer = $footer . "<a href=mailto:sporadic\@linux.wku.edu>";
$footer = $footer . "sporadic\@linux.wku.edu</a></i>\n";
$footer = $footer . "<br><center><a href=#ToP>[Go to top of page]</a></center>\n";
$footer = $footer . "</body></html>";

# other globals 
my %class = '';
my %datablock = '';
my %block_by_class = '';
my %p_function = '';
my %o_function = '';
my %package = '';
my $count = 0;

# called by find();
sub wanted  {
	if ((/^.*\.cs$/) || (/^.*\.gui$/))  {
		&parse ($_);
	}
}

sub parse  {
	my $file = $_[0];
	my @row = '';
	my @props = '';
	my $prop = '';
	my $data = '';
	my $block = '';
	my $object = '';
	my $func = '';

	print ("  -$file\n");

	open (FILE, $file) or
		die ("Failed to open $file\n");
	@row = <FILE>;
	close (FILE);

	$count = 0;
	while ($row[$count] ne '')  {
		$data = $row[$count];
		# search for datablocks
		if ($data =~ /^datablock\s/)  {
			$block = $data;
			$data =~ s/^datablock\s+(\w+?)\s*\(.*/$1/;
			$block =~ s/^datablock\s.+\(\s*(.*)\s*\).*/$1/;
			chomp ($data);
			chomp ($block);
			if ($datablock{$block}{$data} eq '')  {
				$datablock{$block}{$data} = $File::Find::name;
			}  else  {
				$datablock{$block}{$data} = 
					$datablock{$block}{$data} . " $File::Find::name";
			}
			$block_by_class{$data}{$block} += 1;
			$count++;
			# parse out the properties
			@props = &parse_prop (@row);
			foreach $prop (@props)  {
				$class{$data}{$prop} += 1;
			}
		# search for functions
		}  elsif ($data =~ /^function\s/)  {
			$data =~ s/^function\s+(.*\)).*/$1/;
			chomp ($data);
			$count++;
			if ($data =~ /::/)  {
				($object, $func) = split (/::/, $data);
				if ($o_function{$object}{$func} eq '')  {
					$o_function{$object}{$func} = $File::Find::name;
				}  else  {
					$o_function{$object}{$func} = 
						$o_function{$object}{$func} . " $File::Find::name";
				}
			}  else  {
				if ($p_function{$data} eq '')  {
					$p_function{$data} = $File::Find::name;
				}  else  {
					$p_function{$data} = 
						$p_function{$data} . " $File::Find::name";
				}
			}
		}  elsif ($data =~ /^package\s/)  {
			$data =~ s/^package\s+(.*)\s*\{.*/$1/;
			chomp ($data);
			$count++;
			if ($package{$data} eq '')  {
				$package{$data} = $File::Find::name;
			}  else  {
				$package{$data} = $package{$data} . " $File::Find::name";
			}
		}  else  {
			$count++;
		}
	}
}

sub parse_prop  {
	my @row = @_;
	my @props = '';
	my $prop = '';
	my $index = 0;

	while ($row[$count] ne '' && $row[$count] !~ /};/)  {
		$prop = $row[$count];
		if ($prop =~ /.*=.*;/ && $prop !~ /^\s*\/\//)  {
			$prop =~ s/^\s*(.+?)\s*=.*/$1/;
			#remove array index	
			$prop =~ s/\[.*\]/\[\]/;
			chomp ($prop);
			#print ("$prop\n");
			$props[$index] = $prop;
			$index++;
		}
		$count++;
	}
	return @props;
}

sub print_class_text  {
	my $data = '';
	my $prop = '';

	foreach $data (sort keys (%class))  {
		print ("\n--$data:\n");
		foreach $prop (sort keys %{$class{$data}})  {
			print ("  $prop -");
			print ("  $class{$data}{$prop}\n");
		}
		#printf ("$class:$datablock{$class}\n");
	}
}

sub print_class_html  {
	my $data = '';
	my $prop = '';
	my $block = '';
	my $column = 1;
	my $num_columns = 4;
	my $class_count = 0;
	my $datablock_count = 0;

	print ("Generating class file: $file_classes\n");

	open (FILE, ">$file_classes") or
		die ("Failed to create $file_classes\n");

	print FILE ("<head><title>t2 classes</title></head>\n");
	print FILE ("<body bgcolor=#FFFFFF>\n");
	print FILE ("$header");
	print FILE ("<h1><code>t2 classes</code></h1>\n");
	print FILE ("<table width=100% border=0>\n");
	print FILE ("<tr><th bgcolor=$th1_color colspan=$num_columns>Classes</th></tr>\n");
	print FILE ("<tr bgcolor=$tr_color>\n");

	foreach $data (sort keys (%class))  {
		print FILE ("\t<td><a href=#$data>$data</a></td>\n");
		if ($column == $num_columns)  {
			print FILE ("</tr><tr bgcolor=$tr_color>\n");
			$column = 1;
		}  else  {
			$column++;
		}
		$class_count++;
	}
	print FILE ("</tr>\n");
	print FILE ("</table><hr>\n");

	foreach $data (sort keys (%class))  {
		print FILE ("<table width=100% border=0>\n");
		print FILE ("<tr><th bgcolor=$th1_color colspan=$num_columns>");
		print FILE ("<a name=$data>$data</a></th></tr>\n");

		print FILE ("<tr><th bgcolor=$th2_color colspan=$num_columns>Derived Datablocks</tr>");
		print FILE ("<tr bgcolor=$tr_color>\n");
		$column = 1;
		foreach $block (sort keys %{$block_by_class{$data}})  {
			print FILE ("\t<td><a href=$file_datablocks#$block>$block</a></td>\n");
			if ($column == $num_columns)  {
				print FILE ("</tr><tr bgcolor=$tr_color>\n");
				$column = 1;
			}  else  {
				$column++;
			}
			$datablock_count++;
		}

		print FILE ("<tr><th bgcolor=$th2_color colspan=$num_columns>Properties</tr>");
		print FILE ("<tr bgcolor=$tr_color>\n");
		$column = 1;
		foreach $prop (sort keys %{$class{$data}})  {
			print FILE ("\t<td>$prop</td>\n");
			if ($column == $num_columns)  {
				print FILE ("</tr><tr bgcolor=$tr_color>\n");
				$column = 1;
			}  else  {
				$column++;
			}
		}
		print FILE ("</tr>\n");
		print FILE ("</table><hr>\n");
	}

	print FILE ("<code>$class_count classes found.</code>\n");
	print FILE ("<br><code>$datablock_count derived datablocks found.</code>\n");
	print FILE ("$footer");
	
	close (FILE);
}

sub print_func_text  {
	my $func = '';

	foreach $func (sort keys (%p_function))  {
		print ("$func: $p_function{$func}\n");
	}
}

sub print_func_html  {
	my $object = '';
	my $func = '';
	my $count = 0;
	my @files = '';
	my $link = '';

	print ("Generating function file: $file_functions\n");

	open (FILE, ">$file_functions") or
		die ("Failed to create $file_functions\n");

	print FILE ("<head><title>t2 functions</title></head>\n");
	print FILE ("<body bgcolor=#FFFFFF>\n");
	print FILE ("$header");
	print FILE ("<h1><code>t2 functions</code></h1>\n");
	
	print FILE ("<table width=100% border=0>\n");
	print FILE ("<tr><th bgcolor=$th1_color colspan=2>Public Functions</th></tr>\n");
	print FILE ("<tr>\n");
	print FILE ("<th bgcolor=$th2_color>Function</th>\n");
	print FILE ("<th bgcolor=$th2_color>File(s)</th></tr>\n");
	foreach $func (sort keys (%p_function))  {
		@files = split (/ /, $p_function{$func});
		print FILE ("<tr><td bgcolor=$td1_color>$func</td>");
		print FILE ("<td bgcolor=$td2_color>");
		foreach $link (@files)  {
			print FILE ("<a href=$link>$link</a><br>");
		}
		print FILE ("</td></tr>\n");
		$count++;
	}
	print FILE ("</table>\n");
	print FILE ("<br>\n");

	print FILE ("<table width=100% border=0>\n");
	print FILE ("<tr><th bgcolor=$th1_color colspan=2>Object Functions [click for datablock reference</th></tr>\n");
	print FILE ("<tr>\n");
	print FILE ("<th bgcolor=$th2_color>Function</th>\n");
	print FILE ("<th bgcolor=$th2_color>File(s)</th></tr>\n");
	foreach $object (sort keys (%o_function))  {
		print FILE ("<tr><th bgcolor=$th3_color colspan=2>");
		print FILE ("<a href=$file_datablocks#$object name=$object>$object</a></th></tr>\n");
		foreach $func (sort keys (%{$o_function{$object}}))  {
			@files = split (/ /, $o_function{$object}{$func});
			print FILE ("<tr><td bgcolor=$td1_color>$func</td>");
			print FILE ("<td bgcolor=$td2_color>\n");
			foreach $link (@files)  {
				print FILE ("<a href=$link>$link</a><br>");
			}
			print FILE ("</td></tr>\n");
			$count++;
		}
	}
	print FILE ("</table>\n");
	print FILE ("<code>$count functions found.</code>\n");
	print FILE ("$footer");
}

sub print_datablock_text  {
	my $sub = '';

	foreach $sub (sort keys (%datablock))  {
		print ("$sub: $datablock{$sub}\n");
	}
}

sub print_datablock_html  {
	my $block = '';
	my $data = '';
	my $count = 0;
	my @files = '';
	my $link = '';

	print ("Generating datablock file: $file_datablocks\n");

	open (FILE, ">$file_datablocks") or
		die ("Failed to create $file_datablocks\n");

	print FILE ("<head><title>t2 datablocks</title></head>\n");
	print FILE ("<body bgcolor=#FFFFFF>\n");
	print FILE ("$header");
	print FILE ("<h1><code>t2 datablocks</code></h1>\n");
	print FILE ("<table width=100% border=0><tr>\n");
	print FILE ("<th bgcolor=$th1_color>Datablock</th>\n");
	print FILE ("<th bgcolor=$th1_color>Class</th>\n");
	print FILE ("<th bgcolor=$th1_color>File(s)</th></tr>\n");

	foreach $block (sort keys (%datablock))  {
		foreach $data (sort keys (%{$datablock{$block}}))  {
			@files = split (/ /, $datablock{$block}{$data});
			print FILE ("<tr>\n");
			print FILE ("<td bgcolor=$td1_color><a href=$file_functions#$block name=$block>$block</a></td>");
			print FILE ("<td bgcolor=$td2_color><a href=$file_classes#$data>$data</a></td>");
			print FILE ("<td bgcolor=$td2_color>");
			foreach $link (@files)  {
				print FILE ("<a href=$link>$link</a>");	
			}
			print FILE ("</td></tr>\n");
			$count++;
		}
	}
	print FILE ("</table>\n");
	print FILE ("<code>$count datablocks found.</code>\n");
	print FILE ("$footer");
}

sub print_package_text  {
	my $pack = '';

	foreach $pack (sort keys (%package))  {
		print ("$pack: $package{$pack}\n");
	}
}

sub print_package_html  {
	my $pack = '';
	my $count = 0;
	my @files = '';
	my $link = '';

	print ("Generating package file: $file_packages\n");

	open (FILE, ">$file_packages") or
		die ("Failed to create $file_packages\n");

	print FILE ("<head><title>t2 packages</title></head>\n");
	print FILE ("<body bgcolor=#FFFFFF>\n");
	print FILE ("$header");
	print FILE ("<h1><code>t2 packages</code></h1>\n");
	print FILE ("<table width=100% border=0><tr>\n");
	print FILE ("<th bgcolor=$th1_color>Package [click for datablock reference]</th>\n");
	print FILE ("<th bgcolor=$th1_color>File(s)</th></tr>\n");

	foreach $pack (sort keys (%package))  {
		@files = split (/ /, $package{$pack});
		print FILE ("<tr><td bgcolor=$td1_color><a href=$file_functions#$pack name=$pack>$pack</td>");
		print FILE ("<td bgcolor=$td2_color>");
		foreach $link (@files)  {
			print FILE ("<a href=$link>$link</a>");	
		}
		print FILE ("</td></tr>\n");
		$count++;
	}
	print FILE ("</table>\n");
	print FILE ("<code>$count packages found.</code>\n");
	print FILE ("$footer");
}

sub print_all_text  {
	&print_class_text();
	&print_func_text();
	&print_subclass_text();
	&print_package_text();

}

sub print_all_html  {
	&print_class_html();
	&print_func_html();
	&print_datablock_html();
	&print_package_html();
}

#################
#
# Main Shiznit
#
#################

my $path = '.';

if ($ARGV[0])  {
	$path = $ARGV[0];
}

print ("Parsing .cs files in $path\n");
find (\&wanted, $path);

#&print_all_text();
&print_all_html();
#%print_class_text();
#&print_class_html();
#&print_datablock_text();
#&print_datablock_html();
#&print_func_text();
#&print_func_html();
#&print_package_text();
#&print_package_html();

print ("Done.\n");

