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