]> git.tdb.fi Git - gldbg.git/blobdiff - genwrap.py
Enhance the object-orientedness of genwrap.py
[gldbg.git] / genwrap.py
index f507ce2aab80c792bf2d3656e47b6a41ee68da62..81c4e33f8a285bba41d5d65b2cf8979962aacce0 100755 (executable)
@@ -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]
@@ -65,9 +80,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,7 +105,15 @@ 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):
+                       self.ctype = typemap[(self.type, self.direction, self.kind)][0]
                        self.base_ctype = self.ctype
                        if self.kind=="value":
                                if self.base_ctype.startswith("const "):
@@ -102,21 +123,14 @@ class Function:
                                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:
-                               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)
+                                       self.csize = self.func.compsize(self.size[9:-1], self.base_ctype)
                                elif self.size=="" and (self.type=="charARB" or self.type=="Char"):
                                        self.csize = "strlen"
                                else:
@@ -145,16 +159,131 @@ 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 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, self.name, param.name, param.type))
+                               return
+               if not have_type:
+                       res += "*sizeof(%s)"%param.ctype
+               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 = []
+
+               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
+                       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:
+                                       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.spec = None
+               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.spec = 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 +297,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 +313,17 @@ 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
-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
+template = Template(sys.argv[1])
+for i in sys.argv[2:]:
+       files = Files(i)
 
-               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")
+       typemap = Typemap(files.typemap)
+       iomap = IOmap(files.iomap)
+       functions = read_spec(files.spec, files.prefix)
+       functions = [f for f in functions if f.name not in files.ignore_funcs and f.category not in files.ignore_categs]
+       for f in functions:
+               f.finalize()
 
-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)
+       template.process(functions)