]> git.tdb.fi Git - gldbg.git/blobdiff - genwrap.py
Initial revision
[gldbg.git] / genwrap.py
diff --git a/genwrap.py b/genwrap.py
new file mode 100755 (executable)
index 0000000..35e3439
--- /dev/null
@@ -0,0 +1,325 @@
+#!/usr/bin/python
+# $Id$
+
+import sys
+import os
+
+outdir="gensrc"
+
+typemap = {}
+for line in open("gl.tm"):
+       if line[0]=='#':
+               continue
+       parts = [p.strip() for p in line.split(',')]
+       typemap[parts[0]] = parts[3]
+typemap["void"] = "void"
+
+def getparam(func, name):
+       for p in func[2]:
+               if p[0]==name:
+                       return p
+
+funcs = []
+cur_func = None
+for line in open("gl.spec"):
+       if line[0]=='#' or line.find(':')>=0:
+               continue
+       elif line[0]=='\t' and cur_func:
+               parts = line.split()
+               if parts[0]=="return":
+                       cur_func[1] = typemap[parts[1]]
+               elif parts[0]=="param":
+                       p = getparam(cur_func, parts[1])
+                       p[2] = parts[2]
+                       p[1] = typemap[parts[2]]
+                       if parts[4]=="array":
+                               p[1] += " *"
+                               if parts[3]=="in":
+                                       p[1] = "const "+p[1]
+                               s = parts[5][1:-1]
+                               if s.isdigit():
+                                       p[3] = int(s)
+                               elif s=="":
+                                       p[3] = "~"
+                               else:
+                                       p[3] = s
+       else:
+               paren = line.find('(')
+               if paren>0:
+                       cparen = line.rfind(')')
+                       if cparen>paren+1:
+                               args = line[paren+1:cparen].split(", ")
+                       else:
+                               args = []
+                       cur_func = [line[:paren], None, [[a, None, None, 0] for a in args]]
+                       funcs.append(cur_func)
+
+fmtmap = {"GLenum":"%#x",
+       "GLboolean":"%i",
+       "GLbitfield":"%#x",
+       "GLbyte":"%i",
+       "GLshort":"%i",
+       "GLint":"%i",
+       "GLubyte":"%u",
+       "GLushort":"%u",
+       "GLuint":"%u",
+       "GLsizei":"%i",
+       "GLfloat":"%f",
+       "GLclampf":"%f",
+       "GLdouble":"%lf",
+       "GLclampd":"%lf",
+       "const GLubyte *":"%s",
+       "GLchar *":"%s",
+       "GLcharARB *":"%s",
+       "GLvoid*":"%p",
+       "GLsizeiptr":"%p",
+       "GLsizeiptrARB":"%p",
+       "GLintptr":"%p",
+       "GLintptrARB":"%p",
+       "GLhandleARB":"%i",
+       "GLhalfNV":"%#x",
+       "GLuint64EXT":"%lld"}
+
+iomap = {"GLenum":"int",
+       "GLboolean":"char",
+       "GLbitfield":"int",
+       "GLbyte":"char",
+       "GLshort":"short",
+       "GLint":"int",
+       "GLubyte":"char",
+       "GLushort":"short",
+       "GLuint":"int",
+       "GLsizei":"int",
+       "GLfloat":"float",
+       "GLclampf":"float",
+       "GLdouble":"double",
+       "GLclampd":"double",
+       "const GLubyte *":"string",
+       "GLchar *":"string",
+       "GLcharARB *":"string",
+       "GLvoid*":"pointer",
+       "GLsizeiptr":"int",
+       "GLsizeiptrARB":"int",
+       "GLintptr":"int",
+       "GLintptrARB":"int",
+       "GLhandleARB":"int",
+       "GLhalfNV":"short",
+       "GLuint64EXT":"longlong"}
+
+def basetype(type, is_array):
+       if type.startswith("const "):
+               type = type[6:]
+       if is_array and type.endswith(" *"):
+               type = type[:-2]
+       return type
+
+def compsize(func, size, ptype):
+       if not size:
+               return
+
+       res = ""
+       have_type = False
+       for c in size.split('/'):
+               p = getparam(func, c)
+               if not p:
+                       return
+
+               if res:
+                       res += "*"
+
+               cn = p[2]
+               if cn.endswith(("EXT", "ARB", "SGI", "IBM", "ATI")):
+                       cn = cn[:-3]
+               elif cn.endswith("SGIX"):
+                       cn = cn[:-4]
+               elif cn.endswith(("NV", "HP")):
+                       cn = cn[:-2]
+               if cn.endswith("Type"):
+                       res += "typesize(%s)"%p[0]
+                       have_type = True
+               elif cn.endswith("Format"):
+                       res += "formatsize(%s)"%p[0]
+               elif cn.endswith(("Parameter", "ParameterPName", "ParameterName")) or cn=="GetPName":
+                       res += "paramsize(%s)"%p[0]
+               elif cn=="MapTarget":
+                       res += "mapsize(%s)"%p[0]
+               elif (cn=="SizeI" or cn.endswith("Int32")) and p[3]==0:
+                       res += p[0]
+               else:
+                       return
+       if not have_type:
+               res += "*sizeof(%s)"%ptype
+       return res
+
+def getfmt(param):
+       ptype = basetype(param[1], param[3]!=0)
+       if param[3]:
+               if type(param[3])==int:
+                       return ("{%s}"%(", ".join([fmtmap[ptype]]*param[3])), ", ".join("%s[%d]"%(param[0], i) for i in range(param[3])))
+               else:
+                       return ("%p", param[0])
+       else:
+               return (fmtmap[ptype], param[0])
+
+def getwrite(func, param):
+       ptype = basetype(param[1], param[3]!=0)
+       if param[3]:
+               if type(param[3])==int:
+                       size = "%d*sizeof(%s)"%(param[3], ptype)
+               elif param[3].startswith("COMPSIZE("):
+                       size = compsize(func, param[3][9:-1], ptype)
+                       if not size:
+                               print "Compsize '%s' for function '%s' failed"%(param[3][9:-1], func[0])
+                               return ("pointer", None)
+               elif param[3]=="~" and (param[2]=="charARB" or param[2]=="Char"):
+                       return ("string", None)
+               else:
+                       s = getparam(func, param[3].split('*')[0])
+                       if s and (s[2]=="SizeI" or s[2].endswith("Int32")) and s[3]==0:
+                               size = "%s*sizeof(%s)"%(param[3], ptype)
+                               if func[0].startswith("Uniform") and func[0][8]!='u' and func[0][7].isdigit():
+                                       size += "*%s"%func[0][7]
+                       else:
+                               print "Could not determine size for array parameter '%s[%s]' of function '%s'"%(param[0], param[3], func[0])
+                               return ("pointer", None)
+               return ("data", size)
+       else:
+               return (iomap[ptype], None)
+
+def getread(func, param):
+       ptype = basetype(param[1], param[3]!=0)
+       if param[3]:
+               return ("data", "(const void **)")
+       else:
+               return (iomap[ptype], "")
+
+# Write out function enums
+
+out = open(os.path.join(outdir, "functions.enum"), "w");
+out.write("""enum Function
+{
+       FUNC_NONE,
+""")
+for f in funcs:
+       out.write("\tFUNC_%s,\n"%f[0].upper())
+out.write("};\n")
+out.close()
+
+# Write out wrapper functions for transmitting side
+
+out = open(os.path.join(outdir, "glwrap.funcs"), "w");
+for f in funcs:
+       out.write("%s GLAPIENTRY gl%s(%s)\n{\n"%(f[1], f[0], ", ".join("%s %s"%(p[1], p[0]) for p in f[2])))
+
+       out.write("\tstatic %s (*orig)(%s) = NULL;\n"%(f[1], ", ".join(p[1] for p in f[2])))
+       if f[1]!="void":
+               out.write("\t%s ret;\n"%f[1])
+       out.write("\tif(!orig)\n\t\torig = glsym(\"gl%s\");\n"%f[0])
+
+       out.write("\t")
+       if f[1]!="void":
+               out.write("ret = ")
+       out.write("orig(%s);\n"%(", ".join(p[0] for p in f[2])))
+
+       out.write("\tbegin_packet(FUNC_%s);\n"%f[0].upper())
+       if f[1]!="void":
+               out.write("\twrite_%s(ret);\n"%iomap[f[1]])
+       for p in f[2]:
+               (t, s) = getwrite(f, p)
+               out.write("\twrite_%s(%s"%(t, p[0]))
+               if s:
+                       out.write(", %s"%s)
+               out.write(");\n")
+       out.write("\tsend_packet();\n")
+
+       if f[1]!="void":
+               out.write("\treturn ret;\n")
+       out.write("}\n\n")
+out.close()
+
+# Write out decoder stuff
+
+out = open(os.path.join(outdir, "gldecoder.struct"), "w")
+out.write("typedef struct sGlDecoder\n{\n")
+out.write("\tvoid *user_data;\n")
+out.write("\tvoid (*destroy)(void *);\n")
+for f in funcs:
+       out.write("\tvoid (*%s)(void *"%f[0])
+       if f[1]!="void":
+               out.write(", %s"%f[1])
+       if f[2]:
+               out.write(", %s"%(", ".join(p[1] for p in f[2])))
+       out.write(");\n")
+out.write("} GlDecoder;\n")
+
+out = open(os.path.join(outdir, "gldecoder.funcs"), "w")
+for f in funcs:
+       out.write("static unsigned decode_%s(GlDecoder *dec, const char *data, unsigned len)\n{\n"%(f[0]))
+       out.write("\tunsigned pos = 0;\n")
+       if f[1]!="void":
+               out.write("\t%s ret;\n"%f[1])
+       for p in f[2]:
+               out.write("\t%s arg_%s;\n"%(p[1], p[0]))
+       if f[1]!="void":
+               out.write("\tpos += read_%s(&ret, data+pos, len);\n"%iomap[f[1]])
+       for p in f[2]:
+               (t, c) = getread(f, p)
+               out.write("\tpos += read_%s(%s&arg_%s, data+pos, len-pos);\n"%(t, c, p[0]))
+       out.write("\tif(dec->%s)\n"%f[0])
+       out.write("\t\tdec->%s(dec->user_data"%f[0])
+       if f[1]!="void":
+               out.write(", ret")
+       if f[2]:
+               out.write(", %s"%(", ".join("arg_"+p[0] for p in f[2])))
+       out.write(");\n")
+       out.write("\treturn pos;\n")
+       out.write("}\n\n")
+
+out.write("""unsigned gldecoder_decode(GlDecoder *dec, const char *data, unsigned len)
+{
+       unsigned pos = 0;
+       short func;
+
+       pos += read_short(&func, data, len);
+       switch(func)
+       {
+""")
+for f in funcs:
+       out.write("\t\tcase FUNC_%s: pos += decode_%s(dec, data+pos, len); break;\n"%(f[0].upper(), f[0]))
+out.write("""  }
+
+       return pos;
+}
+""")
+out.close()
+
+# Write out print stuff
+
+out = open(os.path.join(outdir, "glprint.funcs"), "w")
+for f in funcs:
+       out.write("static void print_%s(void *user_data"%f[0])
+       if f[1]!="void":
+               out.write(", %s ret"%f[1])
+       if f[2]:
+               out.write(", %s"%(", ".join("%s %s"%(p[1], p[0]) for p in f[2])))
+       out.write(")\n{\n")
+       out.write("\tGlPrintData *gpd = (GlPrintData *)user_data;\n")
+
+       m = [getfmt(p) for p in f[2]]
+       out.write("\tsnprintf(gpd->buffer, gpd->bufsize, \"%s(%s)"%(f[0], ", ".join(p[0] for p in m)))
+       if f[1]!="void":
+               out.write(" = %s"%fmtmap[f[1]])
+       out.write("\"")
+       if m:
+               out.write(", %s"%(", ".join(p[1] for p in m)))
+       if f[1]!="void":
+               out.write(", ret")
+       out.write(");\n")
+
+       out.write("}\n\n")
+
+out.write("static void init_print(GlDecoder *dec)\n{\n")
+for f in funcs:
+       out.write("\tdec->%s = print_%s;\n"%(f[0], f[0]))
+out.write("}\n")
+out.close()