From 65892e28812cc06cceba26c22caca6e6b83960e0 Mon Sep 17 00:00:00 2001
From: Carl Worth <cworth@cworth.org>
Date: Mon, 10 Jun 2013 14:40:43 -0700
Subject: [PATCH] Add a new GLWRAP_DEFER_WITH_RETURN macro.

This allows for the elimination of some code duplication from our
implementation of glXGetPrcAddressARB. The previous implementation
duplicated code from glwrap_lookup simply because the GLWRAP_DEFER
macro did not provide access to the return value of the wrapped
function.

With the new macro, (very much like GLWRAP_DEFER but accepting a
parameter for a variable to accept the return value), we can eliminate
this code duplication.

Of course, our symbol-extraction script is now a bit more complicated
since it has to find occurrences of DEFER_WITH_RETURN in addition to
occurrences of DEFER, and pull out the function name as the second
argument rather than the first.
---
 extract-wrapped-symbols | 11 ++++++++---
 glwrap.h                |  8 ++++++++
 glxwrap.c               | 23 +++++++----------------
 3 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/extract-wrapped-symbols b/extract-wrapped-symbols
index 2b9f76a..8cdd035 100755
--- a/extract-wrapped-symbols
+++ b/extract-wrapped-symbols
@@ -8,12 +8,16 @@
 # libfips, while all other symbols are private.
 
 # We have two different patterns for identifying wrapped
-# functions. The first is a call to a macro ending in "DEFER" (such as
-# DEFER or TIMED_DEFER). In this case, the first argument to the macro
-# is the name of the wrapped function.
+# functions. The first is a call to one of the DEFER macros
+# (GLWRAP_DEFER, TIMED_DEFER, WGLWRAP_DEFER_WITH_RETURN, etc.). In
+# this case, the name of the wrapped function appears as the first or
+# second argument to the macro, (second for the case of of
+# _WITH_RETURN macro).
 
 deferred=`grep 'DEFER[ (]*e*gl' $@ | sed -s 's/.*DEFER *(\([^,)]*\).*/\1/'`
 
+deferred_return=`grep 'DEFER_WITH_RETURN *([^,]*, *e*gl' $@ | sed -s 's/.*DEFER_WITH_RETURN *([^,]*, *\([^,)]*\).*/\1/'`
+
 # The second-case is functions for which we either implement or call
 # the underlying "real" function. In these cases, the code uses the
 # convention of having a function or a function-pointer with a name of
@@ -32,6 +36,7 @@ global:
 EOF
 
 echo "$deferred
+$deferred_return
 $wrapped" | sort | uniq | sed -e 's/\(.*\)/	\1;/'
 
 cat <<EOF
diff --git a/glwrap.h b/glwrap.h
index 9195007..bd2e265 100644
--- a/glwrap.h
+++ b/glwrap.h
@@ -37,4 +37,12 @@ glwrap_lookup (char *name);
 	real_ ## function(__VA_ARGS__); 			\
 } while (0);
 
+/* As GLWRAP_DEFER, but also set 'ret' to the return value */
+#define GLWRAP_DEFER_WITH_RETURN(ret, function,...) do {	\
+	static typeof(&function) real_ ## function;		\
+	if (! real_ ## function)				\
+		real_ ## function = glwrap_lookup (#function);	\
+	(ret) = real_ ## function(__VA_ARGS__); 		\
+} while (0);
+
 #endif
diff --git a/glxwrap.c b/glxwrap.c
index 6da42e6..84bf485 100644
--- a/glxwrap.c
+++ b/glxwrap.c
@@ -45,24 +45,15 @@ glXSwapBuffers (Display *dpy, GLXDrawable drawable)
  */
 void (*glXGetProcAddressARB (const GLubyte *func))(void)
 {
-	void *ptr;
-	static typeof(&glXGetProcAddressARB) glxwrap_real_glXGetProcAddressARB = NULL;
-	char *name = "glXGetProcAddressARB";
-
-	if (! glxwrap_real_glXGetProcAddressARB) {
-		glxwrap_real_glXGetProcAddressARB = glwrap_lookup (name);
-		if (! glxwrap_real_glXGetProcAddressARB) {
-			fprintf (stderr, "Error: Failed to find function %s.\n",
-				 name);
-			return NULL;
-		}
-	}
+	void *ret;
 
 	/* If our library has this symbol, that's what we want to give. */
-	ptr = dlwrap_real_dlsym (NULL, (const char *) func);
-	if (ptr)
-		return ptr;
+	ret = dlwrap_real_dlsym (NULL, (const char *) func);
+	if (ret)
+		return ret;
 
 	/* Otherwise, just defer to the real glXGetProcAddressARB. */
-	return glxwrap_real_glXGetProcAddressARB (func);
+	GLWRAP_DEFER_WITH_RETURN (ret, glXGetProcAddressARB, func);
+
+	return ret;
 }
-- 
2.45.2