Thomas Sondergaard's API tracer
diff --git a/progs/tools/trace/gltrace.py b/progs/tools/trace/gltrace.py
new file mode 100644
index 0000000..973881a
--- /dev/null
+++ b/progs/tools/trace/gltrace.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2006  Thomas Sondergaard
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# Authors:
+#    Thomas Sondergaard <ts@medical-insight.com>
+
+import gl_XML, glX_XML, glX_proto_common, license
+import sys, getopt, copy, string
+
+def create_argument_string(parameters):
+	"""Create a parameter string from a list of gl_parameters."""
+
+	list = []
+	for p in parameters:
+		list.append( p.name )
+	#if len(list) == 0: list = ["void"]
+
+	return string.join(list, ", ")
+
+def create_logfunc_string(func, name):
+	"""Create a parameter string from a list of gl_parameters."""
+
+	list = []
+	list.append('"gl' + name + '("')
+	sep = None
+	for p in func.parameters:
+		if (sep):
+			list.append(sep)
+		list.append( p.name )
+		sep = '", "'
+	list.append('");"')
+	#if len(list) == 0: list = ["void"]
+
+	return "if (config.logCalls) GLTRACE_LOG(" + string.join(list, " << ")+");";
+
+class PrintGltrace(glX_proto_common.glx_print_proto): #(gl_XML.gl_print_base):
+	def __init__(self):
+		gl_XML.gl_print_base.__init__(self)
+
+		self.name = "gltrace.py"
+		self.license = license.bsd_license_template % ( \
+"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
+		#self.header_tag = "_INDIRECT_H_"
+
+		self.last_category = ""
+		return
+
+
+	def printRealHeader(self):
+		print """/**
+ * \\file
+ * gl and glX wrappers for tracing
+ *
+ * \\author Thomas Sondergaard <ts@medical-insight.com>
+ */
+"""
+		#self.printVisibility( "HIDDEN", "hidden" )
+		#self.printFastcall()
+		#self.printNoinline()
+
+		print """
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <GL/glu.h>
+#include <dlfcn.h>
+#include "gltrace_support.h"
+
+using namespace gltrace;
+
+static GLenum real_glGetError() {
+  static GLenum (*real_func)(void) = 0;
+  if (!real_func) real_func = (GLenum (*)(void)) dlsym(RTLD_NEXT, "glGetError");
+  return real_func();
+}
+
+bool betweenGLBeginEnd = false;
+
+extern "C" {
+
+
+__GLXextFuncPtr real_glXGetProcAddressARB(const GLubyte *func_name) {
+  static __GLXextFuncPtr (*real_func)(const GLubyte *func_name) = 0;
+  if (!real_func) real_func = (__GLXextFuncPtr (*)(const GLubyte *func_name)) dlsym(RTLD_NEXT, "glXGetProcAddressARB");
+
+  return real_func(func_name);
+}
+
+__GLXextFuncPtr glXGetProcAddressARB(const GLubyte *func_name_ubyte) {
+  std::string func_name =
+    std::string("gltrace_")+reinterpret_cast<const char*>(func_name_ubyte);
+  
+  __GLXextFuncPtr f = (__GLXextFuncPtr) dlsym(RTLD_DEFAULT, func_name.c_str());
+  if (!f) {
+    GLTRACE_LOG("warning: Could not resolve '" << func_name << "' - function will not be intercepted");
+    return real_glXGetProcAddressARB(func_name_ubyte);
+  }
+  return f;
+}
+
+"""
+
+	def printRealFooter(self):
+		print "} // Extern \"C\""
+
+	def printBody(self, api):
+		for func in api.functionIterateGlx():
+			for func_name in func.entry_points:
+				functionPrefix = ""
+				use_dlsym = True
+				if (api.get_category_for_name(func.name)[1] != None):
+					functionPrefix = "gltrace_"
+					use_dlsym = False
+				
+				print '%s %sgl%s(%s) {' % (func.return_type, functionPrefix, func_name, func.get_parameter_string())
+				if (use_dlsym):
+					print '  static %s (*real_func)(%s) = 0;' % (func.return_type, func.get_parameter_string())
+					print '  if (!real_func) real_func = (%s (*)(%s)) dlsym(RTLD_NEXT, "gl%s");' % (func.return_type, func.get_parameter_string(), func_name)
+				else: # use glXGetProcAddressArb
+					print '  static %s (*real_func)(%s) = 0;' % (func.return_type, func.get_parameter_string())
+					print '  if (!real_func) real_func = (%s (*)(%s)) real_glXGetProcAddressARB((GLubyte *)"gl%s");' % (func.return_type, func.get_parameter_string(), func_name)
+				print '  ' + create_logfunc_string(func, func_name)
+				if (func.return_type == "void"):
+					print '  real_func(%s);' % (create_argument_string(func.parameters))
+				else:
+					print '  %s retval = real_func(%s);' % (func.return_type, create_argument_string(func.parameters))
+				if (func.name == "Begin"):
+					print '  betweenGLBeginEnd = true;'
+				elif (func.name == "End"):
+					print '  betweenGLBeginEnd = false;'
+				print '  if (!betweenGLBeginEnd && config.checkErrors) {'
+				print '    GLenum res;'
+				print '    while ((res = real_glGetError ()) != GL_NO_ERROR) '
+				print '      GLTRACE_LOG("OpenGL Error (" << res << "): <" << gluErrorString(res) << "> at " << gltrace::getStackTrace());'
+				print '  }'
+				if (func.return_type != "void"):
+					print "  return retval;"
+				print '}'
+
+
+def show_usage():
+	print "Usage: %s [-f input_file_name] [-m output_mode] [-d]" % sys.argv[0]
+	print "    -m output_mode   Output mode can be one of 'proto', 'init_c' or 'init_h'."
+	print "    -d               Enable extra debug information in the generated code."
+	sys.exit(1)
+
+
+if __name__ == '__main__':
+	file_name = "gl_API.xml"
+
+	try:
+		(args, trail) = getopt.getopt(sys.argv[1:], "f:d")
+	except Exception,e:
+		show_usage()
+
+	debug = 0
+	for (arg,val) in args:
+		if arg == "-f":
+			file_name = val
+		elif arg == "-d":
+			debug = 1
+
+	printer = PrintGltrace()
+
+	printer.debug = debug
+	api = gl_XML.parse_GL_API( file_name, glX_XML.glx_item_factory() )
+
+	printer.Print( api )