blob: af8e904bc9686b0ea85fec73a4c437a199b56b29 [file] [log] [blame]
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()