X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=genwrap.py;h=07dd914f09d20b9a5bcda4adf6fa2000f33caf52;hb=03c86c2f632b642aa94f721e326787e91aa69c25;hp=f507ce2aab80c792bf2d3656e47b6a41ee68da62;hpb=2e4973ec66cd8ae12d4253e3c3ad9e36a8a4bca6;p=gldbg.git diff --git a/genwrap.py b/genwrap.py index f507ce2..07dd914 100755 --- a/genwrap.py +++ b/genwrap.py @@ -4,6 +4,23 @@ import sys import os +class InputFile: + def __init__(self, fn): + self.file = open(fn) + + def __iter__(self): + for l in self.file: + h = l.find("#") + if h==0 or (h>0 and l[h-1].isspace()): + l = l[:h] + + l = l.rstrip() + if not l: + continue + + yield l + + def strip_name(name): """Strips any vendor suffix and GL prefix from a name (but not GLX prefix)""" @@ -35,9 +52,7 @@ def strip_name(name): class Typemap: def __init__(self, fn): self.map = {} - for line in open(fn): - if line[0]=='#': - continue + for line in InputFile(fn): parts = [p.strip() for p in line.split(',')] if parts[3]=="*": parts[3] = parts[0] @@ -51,11 +66,13 @@ class Typemap: 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 + try: + return self.map[(key[0], "*", "*")] + except KeyError: + 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) @@ -65,9 +82,7 @@ class IOmap: def __init__(self, fn): self.map = {} self.map["void"] = None - for line in open(fn): - if line[0]=='#': - continue + for line in InputFile(fn): parts = [p.strip() for p in line.split(',')] self.map[parts[0]] = tuple(parts[1:]) @@ -92,39 +107,52 @@ class Function: self.type = type self.direction = dir self.kind = kind - self.ctype = typemap[(type, dir, kind)][0] + + def set_size(self, size): + if type(size)==str and size.isdigit(): + self.size = int(size) + else: + self.size = size + + def derive_ctype(self): + m = typemap[(self.type, self.direction, self.kind)] + self.ctype = m[0] + if m[1]!="*": + self.direction = m[1] + if m[2]!="*": + self.kind = m[2] 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) + self.io = iomap[self.base_ctype] - def set_size(self, size): - if type(size)==str and size.isdigit(): - self.size = int(size) - else: - self.size = size - - def finalize(self): - if self.kind=="array": + def derive_csize(self): + if self.kind=="array" and self.size is not None: 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" + self.csize = self.func.compsize(self.size[9:-1], self.base_ctype) + elif self.size=="pname": + self.csize = "paramsize(pname)*sizeof(%s)"%self.base_ctype 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 (s.type=="SizeI" or s.type.endswith("Int32") or s.type.startswith("BufferSize")): + if s.kind=="value": + self.csize = "%s"%self.size + if self.func.name.startswith("glUniformMatrix") and self.func.name[16]!='x': + self.csize += "*%d"%(int(self.func.name[15])**2) + elif self.func.name.startswith("glUniform") and self.func.name[9].isdigit(): + self.csize += "*%s"%self.func.name[9] + if strip_name(self.base_ctype)!="void": + self.csize += "*sizeof(%s)"%self.base_ctype + elif s.kind=="array" and s.size==1: + self.csize = "*%s"%s.name 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": @@ -145,16 +173,138 @@ class Function: def set_category(self, cat): self.category = cat + def compsize(self, size, btype): + if not size: + return + + res = "" + have_type = False + for c in size.replace(',', '/').split('/'): + param = self.get_param(c) + if not param: + sys.stderr.write("Compsize '%s' for function '%s' failed: No parameter '%s'\n"%(size, self.name, c)) + return + + if res: + res += "*" + + cn = strip_name(param.type) + if cn.endswith("Type"): + res += "typesize(%s)"%param.name + have_type = True + elif cn.endswith("Format"): + res += "formatsize(%s)"%param.name + elif param.name=="pname" or cn.endswith("Parameter") or (param.name=="target" and cn=="enum"): + res += "paramsize(%s)"%param.name + elif param.name=="buffer" and cn=="enum": + res += "buffersize(%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, self.name, param.name, param.type)) + return + if not have_type: + res += "*sizeof(%s)"%btype + return res + def finalize(self): + self.ret.derive_ctype() for p in self.params: - p.finalize() + p.derive_ctype() + for p in self.params: + p.derive_csize() + + +class Template: + def __init__(self, fn): + self.sections = [] + self.handcode = [] + + literal = True + text = "" + for line in InputFile(fn): + if line[0]==':': + if not literal and text: + self.add_section(text, literal) + text = "" + text += line[1:]+"\n" + literal = True + elif line[0]=='!': + parts = line[1:].split() + if parts[0]=="handcode": + self.handcode.append(parts[1]) + else: + if literal and text: + self.add_section(text, literal) + text = "" + text += line+"\n" + literal = False + if text: + self.add_section(text, literal) + + def add_section(self, text, literal): + if literal: + self.sections.append(text) + else: + self.sections.append(compile(text, "-", "exec")) + + def write(self, str, *args): + sys.stdout.write(str%args) + + def writeln(self, str, *args): + sys.stdout.write(str%args+"\n") + + def process(self, functions): + for sect in self.sections: + if type(sect)==str: + print sect + else: + for func in functions: + if func.name in self.handcode: + continue + globals = { + "w": self.write, + "wl": self.writeln, + "func": func, + "ret": func.ret, + "params": func.params + } + eval(sect, globals) + + +class Files: + def __init__(self, fn): + self.typemap = None + self.iomap = None + self.specs = [] + self.prefix = None + self.ignore_categs = [] + self.ignore_funcs = [] + + for line in InputFile(fn): + parts = line.split() + if parts[0]=="typemap": + self.typemap = parts[1] + elif parts[0]=="iomap": + self.iomap = parts[1] + elif parts[0]=="spec": + self.specs.append(parts[1]) + elif parts[0]=="prefix": + self.prefix = parts[1] + elif parts[0]=="ignore": + if parts[1]=="category": + self.ignore_categs.append(parts[2]) + elif parts[1]=="function": + self.ignore_funcs.append(parts[2]) + else: + sys.stderr.write("Unknown keyword '%s'\n", parts[0]) def read_spec(fn, prefix): funcs = [] cur_func = None - for line in open(fn): - if line[0]=='#' or line.find(':')>=0: + for line in InputFile(fn): + if line.find(':')>=0: continue elif line[0]=='\t' and cur_func: parts = line.split() @@ -168,7 +318,7 @@ def read_spec(fn, prefix): param = cur_func.get_param(parts[1]) param.set_type(parts[2], parts[3], parts[4]) - if len(parts)>=6: + if len(parts)==6 or (len(parts)>6 and parts[6]!="retained"): param.set_size(parts[5][1:-1]) elif parts[0]=="category": cur_func.set_category(parts[1]) @@ -184,108 +334,21 @@ def read_spec(fn, prefix): pnames = [] cur_func = Function(prefix+line[:paren], pnames) funcs.append(cur_func) - for f in funcs: - f.finalize() return funcs -typemap = None -iomap = None +template = Template(sys.argv[1]) 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.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 = strip_name(param.type) - if cn.endswith("Type"): - res += "typesize(%s)"%param.name - have_type = True - elif cn.endswith("Format"): - res += "formatsize(%s)"%param.name - elif cn.endswith(("Parameter", "ParameterPName", "ParameterName")) or cn=="GetPName": - res += "paramsize(%s)"%param.name - elif cn=="MapTarget": - 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)"%param.ctype - return res - -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: - for func in functions: - globals = { - "w": write, - "wl": writeln, - "func": func, - "ret": func.ret, - "params": func.params - } - eval(sect, globals) +for i in sys.argv[2:]: + files = Files(i) + + typemap = Typemap(files.typemap) + iomap = IOmap(files.iomap) + for s in files.specs: + funcs = read_spec(s, files.prefix) + funcs = [f for f in funcs if f.name not in files.ignore_funcs and f.category not in files.ignore_categs] + for f in funcs: + f.finalize() + names = [f.name for f in funcs] + functions = [f for f in functions if f.name not in names]+funcs + +template.process(functions)