/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

  1. from bgenOutput import *
  2. from bgenType import *
  3. from bgenVariable import *
  4. Error = "bgenGenerator.Error"
  5. DEBUG=0
  6. # Strings to specify argument transfer modes in generator calls
  7. IN = "in"
  8. OUT = "out"
  9. INOUT = IN_OUT = "in-out"
  10. class BaseFunctionGenerator:
  11. def __init__(self, name, condition=None, callname=None, modifiers=None):
  12. if DEBUG: print "<--", name
  13. self.name = name
  14. if callname:
  15. self.callname = callname
  16. else:
  17. self.callname = name
  18. self.prefix = name
  19. self.objecttype = "PyObject" # Type of _self argument to function
  20. self.condition = condition
  21. self.modifiers = modifiers
  22. def setprefix(self, prefix):
  23. self.prefix = prefix
  24. def checkgenerate(self):
  25. return True
  26. def generate(self):
  27. if not self.checkgenerate():
  28. return
  29. if DEBUG: print "-->", self.name
  30. if self.condition:
  31. Output()
  32. Output(self.condition)
  33. self.functionheader()
  34. self.functionbody()
  35. self.functiontrailer()
  36. if self.condition:
  37. Output("#endif")
  38. def functionheader(self):
  39. Output()
  40. Output("static PyObject *%s_%s(%s *_self, PyObject *_args)",
  41. self.prefix, self.name, self.objecttype)
  42. OutLbrace()
  43. Output("PyObject *_res = NULL;")
  44. def functionbody(self):
  45. Output("/* XXX To be provided */")
  46. def functiontrailer(self):
  47. OutRbrace()
  48. def reference(self, name = None):
  49. if not self.checkgenerate():
  50. return
  51. if name is None:
  52. name = self.name
  53. docstring = self.docstring()
  54. if self.condition:
  55. Output()
  56. Output(self.condition)
  57. Output("{\"%s\", (PyCFunction)%s_%s, 1,", name, self.prefix, self.name)
  58. Output(" PyDoc_STR(%s)},", stringify(docstring))
  59. if self.condition:
  60. Output("#endif")
  61. def docstring(self):
  62. return None
  63. def __cmp__(self, other):
  64. if not hasattr(other, 'name'):
  65. return cmp(id(self), id(other))
  66. return cmp(self.name, other.name)
  67. _stringify_map = {'\n': '\\n', '\t': '\\t', '\r': '\\r', '\b': '\\b',
  68. '\e': '\\e', '\a': '\\a', '\f': '\\f', '"': '\\"'}
  69. def stringify(str):
  70. if str is None: return "NULL"
  71. res = '"'
  72. map = _stringify_map
  73. for c in str:
  74. if map.has_key(c): res = res + map[c]
  75. elif ' ' <= c <= '~': res = res + c
  76. else: res = res + '\\%03o' % ord(c)
  77. res = res + '"'
  78. return res
  79. class ManualGenerator(BaseFunctionGenerator):
  80. def __init__(self, name, body, condition=None):
  81. BaseFunctionGenerator.__init__(self, name, condition=condition)
  82. self.body = body
  83. def functionbody(self):
  84. Output("%s", self.body)
  85. def setselftype(self, selftype, itselftype):
  86. self.objecttype = selftype
  87. self.itselftype = itselftype
  88. class FunctionGenerator(BaseFunctionGenerator):
  89. def __init__(self, returntype, name, *argumentList, **conditionlist):
  90. BaseFunctionGenerator.__init__(self, name, **conditionlist)
  91. self.returntype = returntype
  92. self.argumentList = []
  93. self.setreturnvar()
  94. self.parseArgumentList(argumentList)
  95. self.prefix = "XXX" # Will be changed by setprefix() call
  96. self.itselftype = None # Type of _self->ob_itself, if defined
  97. def setreturnvar(self):
  98. if self.returntype:
  99. self.rv = self.makereturnvar()
  100. self.argumentList.append(self.rv)
  101. else:
  102. self.rv = None
  103. def makereturnvar(self):
  104. return Variable(self.returntype, "_rv", OutMode)
  105. def setselftype(self, selftype, itselftype):
  106. self.objecttype = selftype
  107. self.itselftype = itselftype
  108. def parseArgumentList(self, argumentList):
  109. iarg = 0
  110. for type, name, mode in argumentList:
  111. iarg = iarg + 1
  112. if name is None: name = "_arg%d" % iarg
  113. arg = Variable(type, name, mode)
  114. self.argumentList.append(arg)
  115. def docstring(self):
  116. input = []
  117. output = []
  118. for arg in self.argumentList:
  119. if arg.flags == ErrorMode or arg.flags == SelfMode:
  120. continue
  121. if arg.type is None:
  122. str = 'void'
  123. else:
  124. if hasattr(arg.type, 'typeName'):
  125. typeName = arg.type.typeName
  126. if typeName is None: # Suppressed type
  127. continue
  128. else:
  129. typeName = "?"
  130. print "Nameless type", arg.type
  131. str = typeName + ' ' + arg.name
  132. if arg.mode in (InMode, InOutMode):
  133. input.append(str)
  134. if arg.mode in (InOutMode, OutMode):
  135. output.append(str)
  136. if not input:
  137. instr = "()"
  138. else:
  139. instr = "(%s)" % ", ".join(input)
  140. if not output or output == ["void"]:
  141. outstr = "None"
  142. else:
  143. outstr = "(%s)" % ", ".join(output)
  144. return instr + " -> " + outstr
  145. def functionbody(self):
  146. self.declarations()
  147. self.precheck()
  148. self.getargs()
  149. self.callit()
  150. self.checkit()
  151. self.returnvalue()
  152. def declarations(self):
  153. for arg in self.argumentList:
  154. arg.declare()
  155. def getargs(self):
  156. sep = ",\n" + ' '*len("if (!PyArg_ParseTuple(")
  157. fmt, lst = self.getargsFormatArgs(sep)
  158. Output("if (!PyArg_ParseTuple(_args, \"%s\"%s))", fmt, lst)
  159. IndentLevel()
  160. Output("return NULL;")
  161. DedentLevel()
  162. for arg in self.argumentList:
  163. if arg.flags == SelfMode:
  164. continue
  165. if arg.mode in (InMode, InOutMode):
  166. arg.getargsCheck()
  167. def getargsFormatArgs(self, sep):
  168. fmt = ""
  169. lst = ""
  170. for arg in self.argumentList:
  171. if arg.flags == SelfMode:
  172. continue
  173. if arg.mode in (InMode, InOutMode):
  174. arg.getargsPreCheck()
  175. fmt = fmt + arg.getargsFormat()
  176. args = arg.getargsArgs()
  177. if args:
  178. lst = lst + sep + args
  179. return fmt, lst
  180. def precheck(self):
  181. pass
  182. def beginallowthreads(self):
  183. pass
  184. def endallowthreads(self):
  185. pass
  186. def callit(self):
  187. args = ""
  188. s = "%s%s(" % (self.getrvforcallit(), self.callname)
  189. sep = ",\n" + ' '*len(s)
  190. for arg in self.argumentList:
  191. if arg is self.rv:
  192. continue
  193. s = arg.passArgument()
  194. if args: s = sep + s
  195. args = args + s
  196. self.beginallowthreads()
  197. Output("%s%s(%s);",
  198. self.getrvforcallit(), self.callname, args)
  199. self.endallowthreads()
  200. def getrvforcallit(self):
  201. if self.rv:
  202. return "%s = " % self.rv.name
  203. else:
  204. return ""
  205. def checkit(self):
  206. for arg in self.argumentList:
  207. arg.errorCheck()
  208. def returnvalue(self):
  209. sep = ",\n" + ' '*len("return Py_BuildValue(")
  210. fmt, lst = self.mkvalueFormatArgs(sep)
  211. if fmt == "":
  212. Output("Py_INCREF(Py_None);")
  213. Output("_res = Py_None;");
  214. else:
  215. Output("_res = Py_BuildValue(\"%s\"%s);", fmt, lst)
  216. tmp = self.argumentList[:]
  217. tmp.reverse()
  218. for arg in tmp:
  219. if not arg: continue
  220. arg.cleanup()
  221. Output("return _res;")
  222. def mkvalueFormatArgs(self, sep):
  223. fmt = ""
  224. lst = ""
  225. for arg in self.argumentList:
  226. if not arg: continue
  227. if arg.flags == ErrorMode: continue
  228. if arg.mode in (OutMode, InOutMode):
  229. arg.mkvaluePreCheck()
  230. fmt = fmt + arg.mkvalueFormat()
  231. lst = lst + sep + arg.mkvalueArgs()
  232. return fmt, lst
  233. class MethodGenerator(FunctionGenerator):
  234. def parseArgumentList(self, args):
  235. a0, args = args[0], args[1:]
  236. t0, n0, m0 = a0
  237. if m0 != InMode:
  238. raise ValueError, "method's 'self' must be 'InMode'"
  239. self.itself = Variable(t0, "_self->ob_itself", SelfMode)
  240. self.argumentList.append(self.itself)
  241. FunctionGenerator.parseArgumentList(self, args)
  242. def _test():
  243. void = None
  244. eggs = FunctionGenerator(void, "eggs",
  245. (stringptr, 'cmd', InMode),
  246. (int, 'x', InMode),
  247. (double, 'y', InOutMode),
  248. (int, 'status', ErrorMode),
  249. )
  250. eggs.setprefix("spam")
  251. print "/* START */"
  252. eggs.generate()
  253. if __name__ == "__main__":
  254. _test()