+#!/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()