#########################################################################
# VRGL	   Beta Release v0.1                                            #
# Willem de Jonge (willem@argcargv.com)                                 #
# 2003                                                                  #
# 								        #
#  VRGL makes it possible to use off-axis projections with Unreal	#
# Tournament 2003. In principle, VRGL is generic and can also be used	#
# with other OpenGL applications to get an off-axis frustum.  Copyright #
# (C) 2004 Willem de Jonge willem@argcargv.com				#
# 									#
#  VRGL makes it possible to use off-axis projections with Unreal       #
# Tournament 2003. In principle, VRGL is generic and can also be used   #
# with other OpenGL applications to get an off-axis frustum.  Copyright #
# (C) 2004 Willem de Jonge willem@argcargv.com			        #
# 								        #
# This library is free software; you can redistribute it and/or modify	#
# it under the terms of the GNU Lesser General Public License as	#
# published by the Free Software Foundation; either version 2.1 of the	#
# License, or (at your option) any later version.			#
# 									#
# This library is distributed in the hope that it will be useful, but	#
# WITHOUT ANY WARRANTY; without even the implied warranty of		#
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU	#
# Lesser General Public License for more details.			#
# 									#
# You should have received a copy of the GNU Lesser General Public	#
# License along with this library; if not, write to the Free Software	#
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307	#
# USA									#
# 									#
#########################################################################

# read table with functions for which to generate stubs
open(AUTOSTUBS, "<autostubs.txt");
while(<AUTOSTUBS>)
{
	$line = $_;
	chomp($line);
	$autostubs{$line} = 'yes';
}
close( AUTOSTUBS );

# read table with funtions which will be replaced
open(REPLACED, "<replaced.txt");
while(<REPLACED>)
{
	$line = $_;
	chomp($line);
	$replaced{$line} = 'yes';
}
close( REPLACED );

# open exports file and write header
open( EXPORTS, ">exports.def" ) or die "$0: $!";
print EXPORTS
	"LIBRARY opengl32.dll\n".
	"EXPORTS\n";

# open stubs file and wite header
open( STUBS, ">glstubs.cpp" ) or die "$0: $!";
print STUBS
	"// this file was automatically generated DO NOT EDIT!\n".
	"// CaveUTGL - Willem de Jonge (willem\@argcargv.com) - 2003\n".
	"#include \"CaveUTGl.h\"\n".
	"#include \"GL/gl.h\"\n".
	"#include \"gljumptable.h\"\n".
	"\n";

# open jumptable header file and wite header
open( JUMPTABLEH, ">gljumptable.h" ) or die "$0: $!";
print JUMPTABLEH
	"// this file was automatically generated DO NOT EDIT!\n".
	"// CaveUTGL - Willem de Jonge (willem\@argcargv.com) - 2003\n".
	"#ifndef GLJUMPTABLE_H\n".
	"#define GLJUMPTABLE_H\n".
	"#include \"GL/gl.h\"\n".
	"\n".
	"class GLJumpTable\n".
	"{\n".
	"public:\n".
	"	bool init();\n";

# open jumptable implementation file and wite header
open( JUMPTABLEI, ">gljumptable.cpp" ) or die "$0: $!";
print JUMPTABLEI
	"// this file was automatically generated DO NOT EDIT!\n".
	"// CaveUTGL - Willem de Jonge (willem\@argcargv.com) - 2003\n".
	"#include \"gljumptable.h\"\n".
	"\n".
	"bool GLJumpTable::init()\n".
	"{\n".
	"	bool result = true;\n";

# handle gl functions
sub genFuncs
{
my $hdr = shift(@_);
while ($hdr =~ m/^GLAPI\s((\s|\w|\*)+)\sGLAPIENTRY\s+((\w)+)\(([\s\w,\*{$}]+)\);/mg)
{
	$raw    = $&;
	$name   = $3;
	$params = $5;
	$return = $1;
	
	# skip all sorts of exotic ones
	if ( !exists($autostubs{$name}) ) { next };
	
	# cleanup params section (delete new lines and white space)
	$params =~ s/(\n|\r|\f)//mg;
	$params =~ s/\s+/ /mg;
	
	print ('raw: ',    $raw,    "\n");
	print ('name: ',   $name,   "\n");
	print ('params: ', $params, "\n");
	print ('return: ', $return, "\n");

	# write JUMPTABLEH member
	print JUMPTABLEH "	$return (GLAPIENTRY *$name) ($params);\n";
	
	# write JUMPTABLEI function init
	print JUMPTABLEI
		"	if (!getFunction(\"$name\", (void**)&$name)) return false;\n";
		
	# write export definition
	print EXPORTS "   $name\n";
	
	# write stub function if not a funtion that has been replaced
	if ( !exists($replaced{$name}) )
	{
		print STUBS
			"GLAPI $return GLAPIENTRY $name($params)\n".
			"{\n";
			
		# do init for wgl funtions
		if ($name =~ m/wgl/)
		{
			print STUBS
				"    dllInit();\n";
		}
		
		if ($return eq "void")
		{
			print STUBS
				"    glJump.$name(";
		}
		else
		{
			print STUBS
				"    return glJump.$name(";
		}
			
		@par = split "," , $params;
		foreach $pair (@par)
		{
			$pair =~ m/([\s\w]+\s\*?\*?)(\w+)\s*/;
			
			$ptype = $1;
			$pname = $2;
			print "param name: $pname\n";
			print "param type: $ptype\n";
			
			if ( $pair ne $par[0] ) { print STUBS ", " };
			print STUBS $pname;
		};
			
		print STUBS
			");\n".
			"}\n";
	};
	print ('cleaned params: ', $params, "\n");
};
}

# read entire gl header file into $hdr
$file = 'GL/gl.h';
open( INPUT, $file ) or die "$0: $!";
$hdr = do { local $/; <INPUT> };
close( INPUT );

genFuncs $hdr ;

# read entire wgl header file into $hdr
$file = 'GL/wgl.h';
open( INPUT, $file ) or die "$0: $!";
$hdr = do { local $/; <INPUT> };
close( INPUT );

genFuncs $hdr ;

print JUMPTABLEI
	"	return true;\n".
	"};\n";
	
close( JUMPTABLEI );

print JUMPTABLEH
	"\n".
	"private:\n".
	"	bool getFunction(const char* name, void** fptr);\n".
	"};\n".
	"extern GLJumpTable glJump;\n".
	"#endif\n";
	
close( JUMPTABLEH );

close( EXPORTS );
close( STUBS );
