PATCH: glu32 generation

Marcus Meissner marcus at jet.franken.de
Thu Apr 26 16:34:16 CDT 2001


Hi,

This patch adds automatic generation of glu32 on compile time.

It uses a C parser for the <GL/glu.h> file, with (if possible) cross
checking against libGLU.so.

The parser and .spec/.c generator is done mostly generic, so we can
use it for opengl itself later too (but not completely).

I had to enlarge the arg types size of winebuild, since some of the
functions use a lot of doubles.

If GL/glu.h or -lGLU is not present nearly empty glu32.spec and glu.c
are generated.

Verified against some graphic demos using GLU32.DLL.

Ciao, Marcus

Changelog:
	Create a GLU32.DLL on compile time by parsing GL/glu.h and
	libGLU.so, create an empty one if the latter are not present.
	

Index: configure.in
===================================================================
RCS file: /home/wine/wine/configure.in,v
retrieving revision 1.195
diff -u -r1.195 configure.in
--- configure.in	2001/04/16 19:36:12	1.195
+++ configure.in	2001/04/26 19:46:56
@@ -280,6 +280,10 @@
 
 	    if test "$wine_cv_opengl_version_OK" = "yes" -a \( "$wine_cv_opengl_version_threadsafe" = "no" -o $OPENGL = "yes" \)
             then
+		AC_CHECK_LIB(GLU,gluLookAt,
+			X_PRE_LIBS="$X_PRE_LIBS -lGLU"
+			,,
+			$X_LIBS -lGL -lXext -lX11 -lm $X_EXTRA_LIBS)
 		dnl Check for the presence of the library
 		AC_CHECK_LIB(GL,glXCreateContext,
 			     X_PRE_LIBS="$X_PRE_LIBS -lGL"
Index: tools/Makefile.in
===================================================================
RCS file: /home/wine/wine/tools/Makefile.in,v
retrieving revision 1.13
diff -u -r1.13 Makefile.in
--- tools/Makefile.in	2001/03/19 19:19:23	1.13
+++ tools/Makefile.in	2001/04/26 19:46:56
@@ -4,10 +4,10 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 
-PROGRAMS = makedep fnt2bdf bin2res
+PROGRAMS = makedep fnt2bdf bin2res genglu32
 MODULE   = none
 
-C_SRCS = makedep.c fnt2bdf.c bin2res.c
+C_SRCS = makedep.c fnt2bdf.c bin2res.c genglu32.c
 
 SUBDIRS = \
 	cvdump \
@@ -34,6 +34,9 @@
 
 makedep: makedep.o
 	$(CC) $(CFLAGS) -o makedep makedep.o
+
+genglu32: genglu32.o
+	$(CC) $(CFLAGS) -o genglu32 genglu32.o
 
 fnt2bdf: fnt2bdf.o
 	$(CC) $(CFLAGS) -o fnt2bdf fnt2bdf.o
Index: tools/winebuild/build.h
===================================================================
RCS file: /home/wine/wine/tools/winebuild/build.h,v
retrieving revision 1.16
diff -u -r1.16 build.h
--- tools/winebuild/build.h	2001/02/13 02:06:38	1.16
+++ tools/winebuild/build.h	2001/04/26 19:46:58
@@ -73,7 +73,7 @@
 typedef struct
 {
     int  n_args;
-    char arg_types[17];
+    char arg_types[20];
 } ORD_FUNCTION;
 
 typedef struct
Index: dlls/opengl32/.cvsignore
===================================================================
RCS file: /home/wine/wine/dlls/opengl32/.cvsignore,v
retrieving revision 1.2
diff -u -r1.2 .cvsignore
--- dlls/opengl32/.cvsignore	2000/11/30 19:57:37	1.2
+++ dlls/opengl32/.cvsignore	2001/04/26 19:46:58
@@ -1,2 +1,4 @@
 *.spec.c
 Makefile
+glue32.spec
+glu.c
Index: dlls/opengl32/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/opengl32/Makefile.in,v
retrieving revision 1.4
diff -u -r1.4 Makefile.in
--- dlls/opengl32/Makefile.in	2000/08/14 14:42:42	1.4
+++ dlls/opengl32/Makefile.in	2001/04/26 19:46:58
@@ -3,14 +3,23 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = opengl32
+ALTNAMES  = glu32
 SOVERSION = 1.0
 IMPORTS   = x11drv kernel32
 
+GEN_C_SRCS = glu.c
 C_SRCS = \
 	wgl.c \
 	opengl_norm.c \
 	opengl_ext.c
 
 @MAKE_DLL_RULES@
+
+glu32.spec glu.c: $(TOPOBJDIR)/tools/genglu32
+	$(TOPOBJDIR)/tools/genglu32 $(X_CFLAGS) $(X_LIBS) $(XLIB) GLU
+
+
+$(TOPOBJDIR)/tools/genglu32:
+	cd $(TOPOBJDIR)/tools && $(MAKE) genglu32
 
 ### Dependencies:
Index: tools/genglu32.c
--- tools/genglu32.c	Aug  5 15:06:39 1999
+++ tools/genglu32.c	Thu Apr 26 20:31:05 2001
@@ -0,0 +1,287 @@
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+char **funs;
+int nroffuns=0;
+
+char **regfuns;
+int nrofregfuns=0;
+
+char **includes;
+int nrofincludes;
+
+char **libs;
+int nroflibs;
+
+void
+push_include(char *include) {
+    includes = (char**)realloc(includes,sizeof(char*)*(nrofincludes+1));
+    includes[nrofincludes++] = strdup(include);
+}
+
+void
+push_lib(char *lib) {
+    libs = (char**)realloc(libs,sizeof(char*)*(nroflibs+1));
+    libs[nroflibs++] = strdup(lib);
+}
+
+void
+output_specline(FILE *spec,char *funname,char *funargs) {
+    char *s = funargs;
+    fprintf(spec,"@ stdcall %s(",funname);
+    while (*s) {
+	switch (*s) {
+	    case 'l': fprintf(spec,"long");break;
+	    case 'd': fprintf(spec,"double");break;
+	    case 'p': fprintf(spec,"ptr");break;
+	}
+	if (s[1]) fprintf(spec," ");
+	s++;
+    }
+    fprintf(spec,") wine_%s\n",funname);
+}
+
+
+void
+output_funline(FILE *cfile,char *funname,char *funargs) {
+    char *s;
+    int argnr;
+
+    fprintf(cfile,"extern int %s(",funname);
+    s = funargs; argnr=0;
+    while (*s) {
+	switch (*s) {
+	    case 'p': fprintf(cfile,"void *arg%d",argnr);break;
+	    case 'l': fprintf(cfile,"int arg%d",argnr);break;
+	    case 'd': fprintf(cfile,"double arg%d",argnr);break;
+	}
+	if (s[1]) fprintf(cfile,",");
+	argnr++;
+	s++;
+    }
+    fprintf(cfile,");\n");
+    fprintf(cfile,"int WINAPI wine_%s(",funname);
+    s = funargs; argnr=0;
+    while (*s) {
+	switch (*s) {
+	    case 'p': fprintf(cfile,"void *arg%d",argnr);break;
+	    case 'l': fprintf(cfile,"int arg%d",argnr);break;
+	    case 'd': fprintf(cfile,"double arg%d",argnr);break;
+	}
+	if (s[1]) fprintf(cfile,",");
+	argnr++;
+	s++;
+    }
+    fprintf(cfile,") {\n");
+    fprintf(cfile,"	return %s(",funname);
+    s = funargs; argnr=0;
+    while (*s++) {
+	fprintf(cfile,"arg%d",argnr++);
+	if (*s) fprintf(cfile,",");
+    }
+    fprintf(cfile,");\n}\n\n");
+}
+
+char
+lookup_type(const char* arg) {
+    while (isspace(*arg)) arg++;
+    if (!*arg) return 0;
+    if (strchr(arg,'*')) return 'p';
+    if (strchr(arg,'[')) return 'p';
+    if (strstr(arg,"GLdouble")) return 'd';
+    if (strstr(arg,"GLint")) return 'l';
+    if (strstr(arg,"GLboolean")) return 'l';
+    if (strstr(arg,"GLenum")) return 'l';
+    if (strstr(arg,"GLsizei")) return 'l';
+    if (strstr(arg,"void")) return 0;
+
+
+    /* UNCLEAR */
+    if (strstr(arg,"GLfloat")) return 'l';
+
+    fprintf(stderr,"Unsupported argument |%s|\n",arg);
+    return 'l';
+}
+
+void
+try_parse_syms(char *libname) {
+    FILE	*syms;
+    char	lib[200],buf[200];
+    struct	stat stbuf;
+    int		i;
+
+
+    for (i=0;i<nroflibs;i++) {
+    	sprintf(lib,"%s/%s",libs[i],libname);
+        if (-1!=stat(lib,&stbuf))
+	    break;
+    }
+    if (i==nroflibs) return; /* ignore this failure */
+    sprintf(buf,"nm %s",lib);
+    syms = popen(buf,"r");
+    if (!syms)
+	return;
+
+    while (fgets(buf,sizeof(buf),syms)) {
+	char *s;
+	char t;
+
+	s = strchr(buf,'\n');if (s) *s='\0';
+
+	s = strchr(buf,' ');
+	if (!s) continue;
+	s++;
+	t = *s++;
+	s++;
+	if ((t == 't') || (t == 'T')) {
+	    regfuns = (char**)realloc(regfuns,sizeof(char*)*(nrofregfuns+1));
+	    regfuns[nrofregfuns++] = strdup(s);
+	}
+    }
+    pclose(syms);
+}
+
+void usage(char **argv) {
+	fprintf(stderr,"Usage: %s -I... -L... -l... <libname>\n",argv[0]);
+	fprintf(stderr,"Possible libnames: GLU\n");
+}
+
+int
+main(int argc, char **argv) {
+    FILE	*gluh = NULL;
+    char	buf[200],*xlib=NULL;
+    FILE	*spec,*cfile;
+    char	*libname,*headername;
+    int		i,havexlib = 0;
+
+    push_include("/usr/include");
+    push_include("/usr/X11R6/include");
+    push_lib("/usr/X11R6/lib");
+    push_lib("/usr/lib");
+
+    /* look for the library we want to extract */
+    for (i=1;i<argc;i++) {
+	if (argv[i][0]!='-') {
+	    if (xlib) {
+		fprintf(stderr,"Bad argument: %s\n",argv[i]);
+		usage(argv);
+		exit(1);
+	    }
+	    xlib = argv[i];
+	}
+    }
+    if (!xlib) {
+	fprintf(stderr,"Error: No library specified.\n");
+	usage(argv);
+	exit(1);
+    }
+    /* look through the options for include paths and library paths */
+    for (i=1;i<argc;i++) {
+	if (argv[i][0]=='-') {
+	    switch (argv[i][1]) {
+	    case 'I': push_include(argv[i]+2);break;
+	    case 'L': push_lib(argv[i]+2);break;
+	    case 'l': if (strstr(argv[i]+2,xlib)==argv[i]+2) havexlib=1;break;
+	    default : fprintf(stderr,"Unhandled option %s\n",argv[i]);break;
+	    }
+	}
+    }
+    if (!strcmp(xlib,"GLU")) {
+	libname	= "libGLU.so";
+	headername = "GL/glu.h";
+
+        spec = fopen("glu32.spec","w");
+        cfile = fopen("glu.c","w"); 
+    } else {
+	fprintf(stderr,"Usage: %s GLU\n",argv[0]);
+	exit(1);
+    }
+
+    if (!spec || !cfile) {
+	fprintf(stderr,"Error: Could not open output files.\n");
+	exit(1);
+    }
+
+    try_parse_syms(libname);
+
+    for (i=0;i<nrofincludes;i++) {
+	char inc[200];
+
+	sprintf(inc,"%s/%s",includes[i],headername);
+	gluh = fopen(inc,"r");
+	if (gluh)
+	    break;
+    }
+    fprintf(spec,"name glu32\ntype win32\nimport x11drv\n");
+    fprintf(cfile,"#include \"winbase.h\"\n");
+    /* Only do the part below if we have both -lGLU and GL/glu.h, 
+     * otherwise generate empty glu32.spec/glu.c 
+     */
+    if (gluh && havexlib) {
+	while (fgets(buf,sizeof(buf),gluh)) {
+	    if (strstr(buf,"GLUAPI ")==buf) {
+		char *fun = strstr(buf," GLAPIENTRY glu");
+		char funargs[20],*funarg,funname[200];
+		char	*s;
+		int		i;
+		if (!fun) continue;
+
+		fun+=strlen(" GLAPIENTRY ");
+		funarg = funargs;
+
+		s=strchr(fun,'(');
+		if (!s)
+		    continue;
+		*s=0;
+		strcpy(funname,fun);
+
+		for (i=0;i<nroffuns;i++) {
+		    if (!strcmp(fun,funs[i]))
+			break;
+		}
+		if (i!=nroffuns) continue;
+		if (funs) 
+		    funs = (char**)realloc(funs,sizeof(char*)*(nroffuns+1));
+		else
+		    funs = (char**)malloc(sizeof(char*));
+
+		if (nrofregfuns) {
+		    for (i=0;i<nrofregfuns;i++)
+			if (!strcmp(regfuns[i],fun))
+			    break;
+		    if (i==nrofregfuns) {
+			fprintf(stderr,"Warning: Found %s in header, but not in library!\n",fun);
+			continue;
+		    }
+		}
+		funs[nroffuns++]=strdup(fun);
+		s++;
+		do {
+		    char *t;
+		    do {
+			char c;
+			t = strchr(s,',');
+			if (t) *t='\0';
+			c = lookup_type(s);
+			if (c) *funarg++=c;
+			if (t) s=t+1;
+		    } while (t);
+		    if (strchr(s,';'))
+			break;
+		} while ((s=fgets(buf,sizeof(buf),gluh)));
+		*funarg='\0';
+		output_specline(spec,funname,funargs);
+		output_funline(cfile,funname,funargs);
+	    }
+	}
+    }
+    fprintf(spec,"@ stub gluCheckExtension\n");
+    fclose(spec);
+    fclose(cfile);
+    return 0;
+}




More information about the wine-patches mailing list