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)"""
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]
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)
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:])
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":
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()
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])
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)