/Tools/bgen/bgen/bgenGenerator.py
http://unladen-swallow.googlecode.com/ · Python · 302 lines · 253 code · 48 blank · 1 comment · 60 complexity · b39ae914f3d2298b61dfd055d0745cc4 MD5 · raw file
- from bgenOutput import *
- from bgenType import *
- from bgenVariable import *
- Error = "bgenGenerator.Error"
- DEBUG=0
- # Strings to specify argument transfer modes in generator calls
- IN = "in"
- OUT = "out"
- INOUT = IN_OUT = "in-out"
- class BaseFunctionGenerator:
- def __init__(self, name, condition=None, callname=None, modifiers=None):
- if DEBUG: print "<--", name
- self.name = name
- if callname:
- self.callname = callname
- else:
- self.callname = name
- self.prefix = name
- self.objecttype = "PyObject" # Type of _self argument to function
- self.condition = condition
- self.modifiers = modifiers
- def setprefix(self, prefix):
- self.prefix = prefix
- def checkgenerate(self):
- return True
- def generate(self):
- if not self.checkgenerate():
- return
- if DEBUG: print "-->", self.name
- if self.condition:
- Output()
- Output(self.condition)
- self.functionheader()
- self.functionbody()
- self.functiontrailer()
- if self.condition:
- Output("#endif")
- def functionheader(self):
- Output()
- Output("static PyObject *%s_%s(%s *_self, PyObject *_args)",
- self.prefix, self.name, self.objecttype)
- OutLbrace()
- Output("PyObject *_res = NULL;")
- def functionbody(self):
- Output("/* XXX To be provided */")
- def functiontrailer(self):
- OutRbrace()
- def reference(self, name = None):
- if not self.checkgenerate():
- return
- if name is None:
- name = self.name
- docstring = self.docstring()
- if self.condition:
- Output()
- Output(self.condition)
- Output("{\"%s\", (PyCFunction)%s_%s, 1,", name, self.prefix, self.name)
- Output(" PyDoc_STR(%s)},", stringify(docstring))
- if self.condition:
- Output("#endif")
- def docstring(self):
- return None
- def __cmp__(self, other):
- if not hasattr(other, 'name'):
- return cmp(id(self), id(other))
- return cmp(self.name, other.name)
- _stringify_map = {'\n': '\\n', '\t': '\\t', '\r': '\\r', '\b': '\\b',
- '\e': '\\e', '\a': '\\a', '\f': '\\f', '"': '\\"'}
- def stringify(str):
- if str is None: return "NULL"
- res = '"'
- map = _stringify_map
- for c in str:
- if map.has_key(c): res = res + map[c]
- elif ' ' <= c <= '~': res = res + c
- else: res = res + '\\%03o' % ord(c)
- res = res + '"'
- return res
- class ManualGenerator(BaseFunctionGenerator):
- def __init__(self, name, body, condition=None):
- BaseFunctionGenerator.__init__(self, name, condition=condition)
- self.body = body
- def functionbody(self):
- Output("%s", self.body)
- def setselftype(self, selftype, itselftype):
- self.objecttype = selftype
- self.itselftype = itselftype
- class FunctionGenerator(BaseFunctionGenerator):
- def __init__(self, returntype, name, *argumentList, **conditionlist):
- BaseFunctionGenerator.__init__(self, name, **conditionlist)
- self.returntype = returntype
- self.argumentList = []
- self.setreturnvar()
- self.parseArgumentList(argumentList)
- self.prefix = "XXX" # Will be changed by setprefix() call
- self.itselftype = None # Type of _self->ob_itself, if defined
- def setreturnvar(self):
- if self.returntype:
- self.rv = self.makereturnvar()
- self.argumentList.append(self.rv)
- else:
- self.rv = None
- def makereturnvar(self):
- return Variable(self.returntype, "_rv", OutMode)
- def setselftype(self, selftype, itselftype):
- self.objecttype = selftype
- self.itselftype = itselftype
- def parseArgumentList(self, argumentList):
- iarg = 0
- for type, name, mode in argumentList:
- iarg = iarg + 1
- if name is None: name = "_arg%d" % iarg
- arg = Variable(type, name, mode)
- self.argumentList.append(arg)
- def docstring(self):
- input = []
- output = []
- for arg in self.argumentList:
- if arg.flags == ErrorMode or arg.flags == SelfMode:
- continue
- if arg.type is None:
- str = 'void'
- else:
- if hasattr(arg.type, 'typeName'):
- typeName = arg.type.typeName
- if typeName is None: # Suppressed type
- continue
- else:
- typeName = "?"
- print "Nameless type", arg.type
- str = typeName + ' ' + arg.name
- if arg.mode in (InMode, InOutMode):
- input.append(str)
- if arg.mode in (InOutMode, OutMode):
- output.append(str)
- if not input:
- instr = "()"
- else:
- instr = "(%s)" % ", ".join(input)
- if not output or output == ["void"]:
- outstr = "None"
- else:
- outstr = "(%s)" % ", ".join(output)
- return instr + " -> " + outstr
- def functionbody(self):
- self.declarations()
- self.precheck()
- self.getargs()
- self.callit()
- self.checkit()
- self.returnvalue()
- def declarations(self):
- for arg in self.argumentList:
- arg.declare()
- def getargs(self):
- sep = ",\n" + ' '*len("if (!PyArg_ParseTuple(")
- fmt, lst = self.getargsFormatArgs(sep)
- Output("if (!PyArg_ParseTuple(_args, \"%s\"%s))", fmt, lst)
- IndentLevel()
- Output("return NULL;")
- DedentLevel()
- for arg in self.argumentList:
- if arg.flags == SelfMode:
- continue
- if arg.mode in (InMode, InOutMode):
- arg.getargsCheck()
- def getargsFormatArgs(self, sep):
- fmt = ""
- lst = ""
- for arg in self.argumentList:
- if arg.flags == SelfMode:
- continue
- if arg.mode in (InMode, InOutMode):
- arg.getargsPreCheck()
- fmt = fmt + arg.getargsFormat()
- args = arg.getargsArgs()
- if args:
- lst = lst + sep + args
- return fmt, lst
- def precheck(self):
- pass
- def beginallowthreads(self):
- pass
- def endallowthreads(self):
- pass
- def callit(self):
- args = ""
- s = "%s%s(" % (self.getrvforcallit(), self.callname)
- sep = ",\n" + ' '*len(s)
- for arg in self.argumentList:
- if arg is self.rv:
- continue
- s = arg.passArgument()
- if args: s = sep + s
- args = args + s
- self.beginallowthreads()
- Output("%s%s(%s);",
- self.getrvforcallit(), self.callname, args)
- self.endallowthreads()
- def getrvforcallit(self):
- if self.rv:
- return "%s = " % self.rv.name
- else:
- return ""
- def checkit(self):
- for arg in self.argumentList:
- arg.errorCheck()
- def returnvalue(self):
- sep = ",\n" + ' '*len("return Py_BuildValue(")
- fmt, lst = self.mkvalueFormatArgs(sep)
- if fmt == "":
- Output("Py_INCREF(Py_None);")
- Output("_res = Py_None;");
- else:
- Output("_res = Py_BuildValue(\"%s\"%s);", fmt, lst)
- tmp = self.argumentList[:]
- tmp.reverse()
- for arg in tmp:
- if not arg: continue
- arg.cleanup()
- Output("return _res;")
- def mkvalueFormatArgs(self, sep):
- fmt = ""
- lst = ""
- for arg in self.argumentList:
- if not arg: continue
- if arg.flags == ErrorMode: continue
- if arg.mode in (OutMode, InOutMode):
- arg.mkvaluePreCheck()
- fmt = fmt + arg.mkvalueFormat()
- lst = lst + sep + arg.mkvalueArgs()
- return fmt, lst
- class MethodGenerator(FunctionGenerator):
- def parseArgumentList(self, args):
- a0, args = args[0], args[1:]
- t0, n0, m0 = a0
- if m0 != InMode:
- raise ValueError, "method's 'self' must be 'InMode'"
- self.itself = Variable(t0, "_self->ob_itself", SelfMode)
- self.argumentList.append(self.itself)
- FunctionGenerator.parseArgumentList(self, args)
- def _test():
- void = None
- eggs = FunctionGenerator(void, "eggs",
- (stringptr, 'cmd', InMode),
- (int, 'x', InMode),
- (double, 'y', InOutMode),
- (int, 'status', ErrorMode),
- )
- eggs.setprefix("spam")
- print "/* START */"
- eggs.generate()
- if __name__ == "__main__":
- _test()