]> git.tdb.fi Git - gldbg.git/commitdiff
Rewrite genwrap.py to use external templates for more flexibility
authorMikko Rasa <tdb@tdb.fi>
Mon, 12 Oct 2009 09:10:47 +0000 (09:10 +0000)
committerMikko Rasa <tdb@tdb.fi>
Mon, 12 Oct 2009 09:10:47 +0000 (09:10 +0000)
Makefile
genwrap.py
gl.io [new file with mode: 0644]
source/functions.enum.t [new file with mode: 0644]
source/gldecoder.funcs.t [new file with mode: 0644]
source/gldecoder.struct.t [new file with mode: 0644]
source/glprint.funcs.t [new file with mode: 0644]
source/glwrap.funcs.t [new file with mode: 0644]

index 736f05ab4028b8afbe84b571b5ccfd5b7c9d4452..33a2f4e824f0f0a09f0d9ef9a719a40a666e2477 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -35,8 +35,11 @@ source/commandinterpreter.o: source/commandinterpreter.cpp source/gldbg.h
 source/process.o: source/process.cpp source/process.h
        $(CXX) -c $(CXXFLAGS) $(CXXFLAGS_gldbg) -o $@ $<
 
-gensrc/functions.enum gensrc/gldecoder.funcs gensrc/gldecoder.struct gensrc/glwrap.funcs gensrc/glprint.funcs: gensrc/.created genwrap.py gl.spec gl.tm
-       python ./genwrap.py
+gensrc/%: source/%.t gensrc/.created genwrap.py
+       python ./genwrap.py $< >$@
+
+#gensrc/functions.enum gensrc/gldecoder.funcs gensrc/gldecoder.struct gensrc/glwrap.funcs gensrc/glprint.funcs: gensrc/.created genwrap.py gl.spec gl.tm
+#      python ./genwrap.py
 
 gensrc/.created:
        mkdir -p gensrc
index c388f7c2856243549201cfad75d32ee276ada26d..f507ce2aab80c792bf2d3656e47b6a41ee68da62 100755 (executable)
 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=="" or (len(parts)>=7 and parts[6]=="retained"):
-                                       p[3] = "~"
-                               else:
-                                       p[3] = s
+def strip_name(name):
+       """Strips any vendor suffix and GL prefix from a name (but not GLX prefix)"""
+
+       suffix = ""
+       if name.endswith(" *"):
+               suffix = " *"
+               name = name[:-2]
+       elif name.endswith("Pointer"):
+               suffix = "Pointer"
+               name = name[:-7]
+
+       prefix = ""
+       if name.startswith("const "):
+               prefix = "const "
+               name = name[6:]
+
+       if name.startswith("GL") and not name.startswith("GLX"):
+               name = name[2:]
+       if name.endswith(("EXT", "ARB", "SGI", "IBM", "ATI")):
+               return prefix+name[:-3]+suffix
+       elif name.endswith("SGIX"):
+               return prefix+name[:-4]+suffix
+       elif name.endswith(("NV", "HP")):
+               return prefix+name[:-2]+suffix
        else:
-               paren = line.find('(')
-               if paren>0:
-                       cparen = line.rfind(')')
-                       if cparen>paren+1:
-                               args = line[paren+1:cparen].split(", ")
+               return prefix+name+suffix
+
+
+class Typemap:
+       def __init__(self, fn):
+               self.map = {}
+               for line in open(fn):
+                       if line[0]=='#':
+                               continue
+                       parts = [p.strip() for p in line.split(',')]
+                       if parts[3]=="*":
+                               parts[3] = parts[0]
+                       elif parts[3][-1]=='*' and parts[3][-2]!=' ':
+                               parts[3] = parts[3][:-1]+" *"
+                       self.map[tuple(parts[0:3])] = tuple(parts[3:6])
+
+       def wildcard_match(self, a, b):
+               if a=="*" or b=="*":
+                       return True
+               return a==b
+
+       def __getitem__(self, key):
+               return self.map[(key[0], "*", "*")]
+               for k, v in self.map.iteritems():
+                       if strip_name(k[0])==strip_name(key[0]) and self.wildcard_match(k[1], key[1]) and self.wildcard_match(k[2], key[2]):
+                               return v
+               raise KeyError, key
+
+       def update(self, other):
+               self.map.update(other.map)
+
+
+class IOmap:
+       def __init__(self, fn):
+               self.map = {}
+               self.map["void"] = None
+               for line in open(fn):
+                       if line[0]=='#':
+                               continue
+                       parts = [p.strip() for p in line.split(',')]
+                       self.map[parts[0]] = tuple(parts[1:])
+
+       def __getitem__(self, key):
+               return self.map[strip_name(key)]
+
+
+class Function:
+       class Parameter:
+               def __init__(self, func, name):
+                       self.func = func
+                       self.name = name
+                       self.type = None
+                       self.direction = "in"
+                       self.kind = "value"
+                       self.size = None
+                       self.ctype = None
+                       self.csize = None
+                       self.io = None
+
+               def set_type(self, type, dir, kind):
+                       self.type = type
+                       self.direction = dir
+                       self.kind = kind
+                       self.ctype = typemap[(type, dir, kind)][0]
+                       self.base_ctype = self.ctype
+                       if self.kind=="value":
+                               if self.base_ctype.startswith("const "):
+                                       self.base_ctype = self.base_ctype[6:]
+                               self.io = iomap[self.base_ctype]
+                       else:
+                               if self.direction=="in":
+                                       self.ctype = "const "+self.ctype
+                               self.ctype = self.ctype+" *"
+                       #print "%s | %s | %s | %s | %s"%(self.func.name, self.name, self.type, self.ctype, self.base_ctype)
+
+               def set_size(self, size):
+                       if type(size)==str and size.isdigit():
+                               self.size = int(size)
                        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":"%g",
-       "GLclampf":"%g",
-       "GLdouble":"%lg",
-       "GLclampd":"%lg",
-       "const GLubyte *":"%s",
-       "GLchar *":"%s",
-       "GLcharARB *":"%s",
-       "GLvoid*":"%p",
-       "GLsizeiptr":"%d",
-       "GLsizeiptrARB":"%d",
-       "GLintptr":"%d",
-       "GLintptrARB":"%d",
-       "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):
+                               self.size = size
+
+               def finalize(self):
+                       if self.kind=="array":
+                               self.csize = None
+                               if type(self.size)==int:
+                                       self.csize = "%d*sizeof(%s)"%(self.size, self.base_ctype)
+                               elif self.size.startswith("COMPSIZE("):
+                                       self.csize = compsize(self.func, self.size[9:-1], self.base_ctype)
+                               elif self.size=="" and (self.type=="charARB" or self.type=="Char"):
+                                       self.csize = "strlen"
+                               else:
+                                       s = self.func.get_param(self.size.split('*')[0])
+                                       if (s.type=="SizeI" or s.type.endswith("Int32") or s.type.startswith("BufferSize")) and s.kind=="value":
+                                               self.csize = "%s*sizeof(%s)"%(self.size, self.base_ctype)
+                                               if self.func.name.startswith("Uniform") and self.func.name[7].isdigit():
+                                                       self.csize += "*%s"%func.name[7]
+                                       if not self.csize:
+                                               sys.stderr.write("Could not determine size for array parameter '%s[%s]' of function '%s'\n"%(self.name, self.size, self.func.name))
+                       elif self.kind=="reference":
+                               self.csize = "sizeof(%s)"%self.base_ctype
+
+       def __init__(self, name, pnames):
+               self.name = name
+               self.ret = Function.Parameter(self, "ret")
+               self.params = [Function.Parameter(self, n) for n in pnames]
+               self.category = None
+
+       def get_param(self, pname):
+               for p in self.params:
+                       if p.name==pname:
+                               return p
+               raise KeyError, pname
+
+       def set_category(self, cat):
+               self.category = cat
+
+       def finalize(self):
+               for p in self.params:
+                       p.finalize()
+
+
+def read_spec(fn, prefix):
+       funcs = []
+       cur_func = None
+       for line in open(fn):
+               if line[0]=='#' or line.find(':')>=0:
+                       continue
+               elif line[0]=='\t' and cur_func:
+                       parts = line.split()
+                       if parts[0]=="return":
+                               cur_func.ret.set_type(parts[1], "out", "value")
+                       elif parts[0]=="param":
+                               bracket = parts[4].find('[')
+                               if bracket>=0:
+                                       parts.insert(5, parts[4][bracket:])
+                                       parts[4] = parts[4][:bracket]
+
+                               param = cur_func.get_param(parts[1])
+                               param.set_type(parts[2], parts[3], parts[4])
+                               if len(parts)>=6:
+                                       param.set_size(parts[5][1:-1])
+                       elif parts[0]=="category":
+                               cur_func.set_category(parts[1])
+                       elif parts[0]=="glxvendorglx" and cur_func.category=="glx":
+                               cur_func.set_category("glxext")
+               else:
+                       paren = line.find('(')
+                       if paren>0:
+                               cparen = line.rfind(')')
+                               if cparen>paren+1:
+                                       pnames = [n.strip() for n in line[paren+1:cparen].split(",")]
+                               else:
+                                       pnames = []
+                               cur_func = Function(prefix+line[:paren], pnames)
+                               funcs.append(cur_func)
+       for f in funcs:
+               f.finalize()
+       return funcs
+
+typemap = None
+iomap = None
+functions = []
+sections = []
+
+def add_section(text, literal):
+       global sections
+
+       if literal:
+               sections.append(text)
+       else:
+               sections.append(compile(text, "-", "exec"))
+
+def read_template(fn):
+       global typemap
+       global iomap
+       global functions
+
+       literal = True
+       text = ""
+       for line in open(fn):
+               if line[0]=='#':
+                       continue
+               elif line[0]=='^':
+                       parts = line[1:].split()
+                       if parts[0]=="typemap":
+                               typemap = Typemap(parts[1])
+                       elif parts[0]=="iomap":
+                               iomap = IOmap(parts[1])
+                       elif parts[0]=="spec":
+                               functions = read_spec(parts[2], parts[1])
+               elif line[0]==':':
+                       if not literal and text:
+                               add_section(text, literal)
+                               text = ""
+                       text += line[1:]
+                       literal = True
+               else:
+                       if literal and text:
+                               add_section(text, literal)
+                               text = ""
+                       text += line
+                       literal = False
+       if text:
+               add_section(text, literal)
+
+def compsize(func, size, btype):
        if not size:
                return
 
        res = ""
        have_type = False
-       for c in size.split('/'):
-               p = getparam(func, c)
-               if not p:
+       for c in size.replace(',', '/').split('/'):
+               param = func.get_param(c)
+               if not param:
+                       sys.stderr.write("Compsize '%s' for function '%s' failed: No parameter '%s'\n"%(size, func.name, c))
                        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]
+               cn = strip_name(param.type)
                if cn.endswith("Type"):
-                       res += "typesize(%s)"%p[0]
+                       res += "typesize(%s)"%param.name
                        have_type = True
                elif cn.endswith("Format"):
-                       res += "formatsize(%s)"%p[0]
+                       res += "formatsize(%s)"%param.name
                elif cn.endswith(("Parameter", "ParameterPName", "ParameterName")) or cn=="GetPName":
-                       res += "paramsize(%s)"%p[0]
+                       res += "paramsize(%s)"%param.name
                elif cn=="MapTarget":
-                       res += "mapsize(%s)"%p[0]
-               elif (cn=="SizeI" or cn.endswith("Int32")) and p[3]==0:
-                       res += p[0]
+                       res += "mapsize(%s)"%param.name
+               elif (cn=="SizeI" or cn.endswith("Int32")) and not param.size:
+                       res += param.name
                else:
+                       sys.stderr.write("Compsize '%s' for function '%s' failed: Parameter '%s' has unknown type '%s'\n"%(size, func.name, param.name, param.type))
                        return
        if not have_type:
-               res += "*sizeof(%s)"%ptype
+               res += "*sizeof(%s)"%param.ctype
        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 getrwinfo(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, "void **")
-               elif param[3]=="~":
-                       if param[2]=="charARB" or param[2]=="Char":
-                               return ("string", None, "const unsigned char **")
-                       else:
-                               return ("pointer", None, "void **")
-               else:
-                       s = getparam(func, param[3].split('*')[0])
-                       if s and (s[2]=="SizeI" or s[2].endswith("Int32") or s[2].startswith("BufferSize")) 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, "void **")
-               return ("data", size, "const void **")
+read_template(sys.argv[1])
+
+def write(str, *args):
+       sys.stdout.write(str%args)
+
+def writeln(str, *args):
+       sys.stdout.write(str%args+"\n")
+
+for sect in sections:
+       if type(sect)==str:
+               print sect
        else:
-               return (iomap[ptype], None, None)
-
-# 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 APIENTRY 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, c) = getrwinfo(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)\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);\n"%iomap[f[1]])
-       for p in f[2]:
-               (t, s, c) = getrwinfo(f, p)
-               if c:
-                       c="(%s)"%c
-               else:
-                       c=""
-               out.write("\tpos += read_%s(%s&arg_%s, data+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("""static int decode_func(GlDecoder *dec, short func, const char *data)
-{
-       switch(func)
-       {
-""")
-for f in funcs:
-       out.write("\t\tcase FUNC_%s: return decode_%s(dec, data);\n"%(f[0].upper(), f[0]))
-out.write("""  }
-
-       return -1;
-}
-""")
-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()
+               for func in functions:
+                       globals = {
+                               "w": write,
+                               "wl": writeln,
+                               "func": func,
+                               "ret": func.ret,
+                               "params": func.params
+                       }
+                       eval(sect, globals)
diff --git a/gl.io b/gl.io
new file mode 100644 (file)
index 0000000..85c9aaf
--- /dev/null
+++ b/gl.io
@@ -0,0 +1,24 @@
+enum, int, %#x
+boolean, char, %i
+bitfield, int, %#x
+byte, char, %i
+ubyte, char, %u
+short, short, %i
+ushort, short, %u
+int, int, %i
+uint, int, %u
+unsigned int, int, %u
+sizei, int, %i
+intptr, int, %i
+sizeiptr, int, %i
+handle, int, %i
+int64_t, longlong, %lli
+uint64, longlong, %llu
+half, short, %#x
+float, float, %g
+clampf, float, %g
+double, double, %g
+clampd, double, %g
+ubyte *, string, %s
+char *, string, %s
+void *, pointer, %p
diff --git a/source/functions.enum.t b/source/functions.enum.t
new file mode 100644 (file)
index 0000000..92fef70
--- /dev/null
@@ -0,0 +1,9 @@
+# $Id$
+^typemap gl.tm
+^iomap gl.io
+^spec gl gl.spec
+:enum Function
+:{
+:      FUNC_NONE,
+wl('   FUNC_%s,', func.name.upper())
+:};
diff --git a/source/gldecoder.funcs.t b/source/gldecoder.funcs.t
new file mode 100644 (file)
index 0000000..055a272
--- /dev/null
@@ -0,0 +1,37 @@
+# $Id$
+^typemap gl.tm
+^iomap gl.io
+^spec gl gl.spec
+wl('static unsigned decode_%s(GlDecoder *dec, const char *data)', func.name)
+wl('{')
+wl('   unsigned pos = 0;')
+if ret.ctype!="void":
+       wl('    %s ret;', ret.ctype)
+for p in params:
+       wl('    %s p_%s;', p.ctype, p.name)
+if ret.ctype!="void":
+       wl('    pos += read_%s(&ret, data+pos);', ret.io[0])
+for p in params:
+       if p.kind=="value":
+               wl('    pos += read_%s(&p_%s, data+pos);', p.io[0], p.name)
+       elif p.csize:
+               wl('    pos += read_data((const void **)&p_%s, data+pos);', p.name)
+       else:
+               wl('    pos += read_pointer((void **)&p_%s, data+pos);', p.name)
+wl('   if(dec->%s)', func.name)
+w('            dec->%s(dec->user_data', func.name)
+if ret.ctype!="void":
+       w(', ret')
+for p in params:
+       w(', p_%s', p.name)
+wl(');')
+wl('   return pos;')
+wl('}')
+:static int decode_func(GlDecoder *dec, short func, const char *data)
+:{
+:      switch(func)
+:      {
+wl('   case FUNC_%s: return decode_%s(dec, data);', func.name.upper(), func.name)
+:      default: return -1;
+:      }
+:}
diff --git a/source/gldecoder.struct.t b/source/gldecoder.struct.t
new file mode 100644 (file)
index 0000000..e4cf5c6
--- /dev/null
@@ -0,0 +1,15 @@
+# $Id$
+^typemap gl.tm
+^iomap gl.io
+^spec gl gl.spec
+:typedef struct sGlDecoder
+:{
+:      void *user_data;
+:      void (*destroy)(void *);
+w('    void (*%s)(void *', func.name)
+if ret.ctype!="void":
+       w(', %s', ret.ctype)
+for p in params:
+       w(', %s', p.ctype)
+wl(');')
+:} GlDecoder;
diff --git a/source/glprint.funcs.t b/source/glprint.funcs.t
new file mode 100644 (file)
index 0000000..927fa36
--- /dev/null
@@ -0,0 +1,36 @@
+# $Id$
+^typemap gl.tm
+^iomap gl.io
+^spec gl gl.spec
+w('static void print_%s(void *user_data', func.name)
+if ret.ctype!="void":
+       w(', %s ret', ret.ctype)
+for p in params:
+       w(', %s %s', p.ctype, p.name)
+wl(')')
+wl('{')
+wl('   GlPrintData *gpd = (GlPrintData *)user_data;')
+w('    snprintf(gpd->buffer, gpd->bufsize, "%s(', func.name)
+first = True
+for p in params:
+       if not first:
+               w(', ')
+       if p.kind=="value":
+               w("%s", p.io[1])
+       else:
+               w("%%p")
+       first = False
+w(')')
+if ret.ctype!="void":
+       w(' = %s', ret.io[1])
+w('"')
+for p in params:
+       w(', %s', p.name)
+if ret.ctype!="void":
+       w(', ret')
+wl(');')
+wl('}')
+:static void init_print(GlDecoder *dec)
+:{
+wl('   dec->%s = print_%s;', func.name, func.name)
+:}
diff --git a/source/glwrap.funcs.t b/source/glwrap.funcs.t
new file mode 100644 (file)
index 0000000..108f329
--- /dev/null
@@ -0,0 +1,29 @@
+# $Id$
+^typemap gl.tm
+^iomap gl.io
+^spec gl gl.spec
+wl('%s APIENTRY %s(%s)', ret.ctype, func.name, ", ".join([p.ctype+" "+p.name for p in params]))
+wl('{')
+wl('   static %s (*orig)(%s);', ret.ctype, ", ".join([p.ctype for p in params]))
+if ret.ctype!='void':
+       wl('  %s ret;', ret.ctype)
+wl('   if(!orig)')
+wl('           orig = glsym("%s");', func.name)
+w('    ')
+if ret.ctype!='void':
+       w('ret = ')
+wl('orig(%s);', ", ".join([p.name for p in params]))
+wl('   begin_packet(FUNC_%s);', func.name.upper())
+if ret.ctype!='void':
+       wl('  write_%s(ret);', ret.io[0])
+for p in params:
+       if p.kind=="value":
+               wl('    write_%s(%s);', p.io[0], p.name)
+       elif p.csize:
+               wl('    write_data(%s, %s);', p.name, p.csize)
+       else:
+               wl('    write_pointer(%s);', p.name)
+wl('   send_packet();')
+if ret.ctype!='void':
+       wl('    return ret;')
+wl('}')