LuaGlueGen.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. #!/usr/bin/python
  2. # Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  3. # All rights reserved.
  4. # Code licensed under the BSD License.
  5. # http://www.anki3d.org/LICENSE
  6. import os
  7. import optparse
  8. import xml.etree.ElementTree as et
  9. # Globals
  10. identation_level = 0
  11. out_file = None
  12. def parse_commandline():
  13. """ Parse the command line arguments """
  14. parser = optparse.OptionParser(usage="usage: %prog [options]", description="Create LUA bindings using XML")
  15. parser.add_option("-i",
  16. "--input",
  17. dest="inp",
  18. type="string",
  19. help="specify the XML files to parse. Seperate with :")
  20. (options, args) = parser.parse_args()
  21. if not options.inp:
  22. parser.error("argument is missing")
  23. return options.inp.split(":")
  24. def type_sig(value):
  25. """ Calculate the signature of a type """
  26. return hash(value)
  27. def get_base_fname(path):
  28. """ From path/to/a/file.ext return the "file" """
  29. return os.path.splitext(os.path.basename(path))[0]
  30. def wglue(txt):
  31. """ Write glue code to the output """
  32. global out_file
  33. global identation_level
  34. out_file.write("%s%s\n" % ("\t" * identation_level, txt))
  35. def ident(number):
  36. """ Increase or recrease identation for the wglue """
  37. global identation_level
  38. identation_level += number
  39. def type_is_bool(type):
  40. """ Check if a type is boolean """
  41. return type == "Bool" or type == "bool"
  42. def type_is_number(type):
  43. """ Check if a type is number """
  44. numbers = [
  45. "U8", "U16", "U32", "U64", "I8", "I16", "I32", "I64", "U", "I", "PtrSize", "F32", "F64", "int", "unsigned",
  46. "unsigned int", "short", "unsigned short", "uint", "float", "double"
  47. ]
  48. it_is = False
  49. for num in numbers:
  50. if num == type:
  51. it_is = True
  52. break
  53. return it_is
  54. def parse_type_decl(arg_txt):
  55. """ Parse an arg text """
  56. tokens = arg_txt.split(" ")
  57. tokens_size = len(tokens)
  58. type = tokens[tokens_size - 1]
  59. type_len = len(type)
  60. is_ptr = False
  61. is_ref = False
  62. if type[type_len - 1] == "&":
  63. is_ref = True
  64. elif type[type_len - 1] == "*":
  65. is_ptr = True
  66. if is_ref or is_ptr:
  67. type = type[:-1]
  68. is_const = False
  69. if tokens[0] == "const":
  70. is_const = True
  71. return (type, is_ref, is_ptr, is_const)
  72. def ret(ret_el):
  73. """ Push return value """
  74. if ret_el is None:
  75. wglue("return 0;")
  76. return
  77. wglue("// Push return value")
  78. type_txt = ret_el.text
  79. (type, is_ref, is_ptr, is_const) = parse_type_decl(type_txt)
  80. if is_ptr:
  81. wglue("if(ANKI_UNLIKELY(ret == nullptr))")
  82. wglue("{")
  83. ident(1)
  84. wglue("lua_pushstring(l, \"Glue code returned nullptr\");")
  85. wglue("return -1;")
  86. ident(-1)
  87. wglue("}")
  88. wglue("")
  89. if type_is_bool(type):
  90. wglue("lua_pushboolean(l, ret);")
  91. elif type_is_number(type):
  92. wglue("lua_pushnumber(l, lua_Number(ret));")
  93. elif type == "char" or type == "CString":
  94. wglue("lua_pushstring(l, &ret[0]);")
  95. elif type == "Error":
  96. wglue("if(ANKI_UNLIKELY(ret))")
  97. wglue("{")
  98. ident(1)
  99. wglue("lua_pushstring(l, \"Glue code returned an error\");")
  100. wglue("return -1;")
  101. ident(-1)
  102. wglue("}")
  103. wglue("")
  104. wglue("lua_pushnumber(l, lua_Number(!!ret));")
  105. else:
  106. if is_ptr or is_ref:
  107. wglue("voidp = lua_newuserdata(l, sizeof(LuaUserData));")
  108. wglue("ud = static_cast<LuaUserData*>(voidp);")
  109. wglue("luaL_setmetatable(l, \"%s\");" % type)
  110. wglue("extern LuaUserDataTypeInfo luaUserDataTypeInfo%s;" % type)
  111. if is_ptr:
  112. wglue("ud->initPointed(&luaUserDataTypeInfo%s, ret);" % type)
  113. elif is_ref:
  114. wglue("ud->initPointed(&luaUserDataTypeInfo%s, &ret);" % type)
  115. else:
  116. wglue("size = LuaUserData::computeSizeForGarbageCollected<%s>();" % type)
  117. wglue("voidp = lua_newuserdata(l, size);")
  118. wglue("luaL_setmetatable(l, \"%s\");" % type)
  119. wglue("ud = static_cast<LuaUserData*>(voidp);")
  120. wglue("extern LuaUserDataTypeInfo luaUserDataTypeInfo%s;" % type)
  121. wglue("ud->initGarbageCollected(&luaUserDataTypeInfo%s);" % type)
  122. wglue("::new(ud->getData<%s>()) %s(std::move(ret));" % (type, type))
  123. wglue("")
  124. wglue("return 1;")
  125. def arg(arg_txt, stack_index, index):
  126. """ Write the pop code for a single argument """
  127. (type, is_ref, is_ptr, is_const) = parse_type_decl(arg_txt)
  128. if type_is_bool(type) or type_is_number(type):
  129. wglue("%s arg%d;" % (type, index))
  130. wglue("if(ANKI_UNLIKELY(LuaBinder::checkNumber(l, %d, arg%d)))" % (stack_index, index))
  131. wglue("{")
  132. ident(1)
  133. wglue("return -1;")
  134. ident(-1)
  135. wglue("}")
  136. elif type == "char" or type == "CString":
  137. wglue("const char* arg%d;" % index)
  138. wglue("if(ANKI_UNLIKELY(LuaBinder::checkString(l, %d, arg%d)))" % (stack_index, index))
  139. wglue("{")
  140. ident(1)
  141. wglue("return -1;")
  142. ident(-1)
  143. wglue("}")
  144. else:
  145. wglue("extern LuaUserDataTypeInfo luaUserDataTypeInfo%s;" % type)
  146. wglue("if(ANKI_UNLIKELY(LuaBinder::checkUserData(l, %d, luaUserDataTypeInfo%s, ud)))" % (stack_index, type))
  147. wglue("{")
  148. ident(1)
  149. wglue("return -1;")
  150. ident(-1)
  151. wglue("}")
  152. wglue("")
  153. wglue("%s* iarg%d = ud->getData<%s>();" % (type, index, type))
  154. if is_ptr:
  155. wglue("%s arg%d(iarg%d);" % (arg_txt, index, index))
  156. else:
  157. wglue("%s arg%d(*iarg%d);" % (arg_txt, index, index))
  158. def args(args_el, stack_index):
  159. """ Write the pop code for argument parsing and return the arg list """
  160. if args_el is None:
  161. return ""
  162. wglue("// Pop arguments")
  163. arg_index = 0
  164. # Do the work
  165. args_str = ""
  166. arg_index = 0
  167. for arg_el in args_el.iter("arg"):
  168. arg(arg_el.text, stack_index, arg_index)
  169. args_str += "arg%d, " % arg_index
  170. wglue("")
  171. stack_index += 1
  172. arg_index += 1
  173. if len(args_str) > 0:
  174. args_str = args_str[:-2]
  175. return args_str
  176. def count_args(args_el):
  177. """ Count the number of arguments """
  178. if args_el is None:
  179. return 0
  180. count = 0
  181. for arg_el in args_el.iter("arg"):
  182. count += 1
  183. return count
  184. def check_args(args_el, bias):
  185. """ Check number of args. Call that first because it throws error """
  186. if args_el is not None:
  187. count = bias + count_args(args_el)
  188. else:
  189. count = bias
  190. wglue("if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, %d)))" % count)
  191. wglue("{")
  192. ident(1)
  193. wglue("return -1;")
  194. ident(-1)
  195. wglue("}")
  196. wglue("")
  197. def get_meth_alias(meth_el):
  198. """ Return the method alias """
  199. meth_name = meth_el.get("name")
  200. if meth_name == "operator+":
  201. meth_alias = "__add"
  202. elif meth_name == "operator-":
  203. meth_alias = "__sub"
  204. elif meth_name == "operator*":
  205. meth_alias = "__mul"
  206. elif meth_name == "operator/":
  207. meth_alias = "__div"
  208. elif meth_name == "operator==":
  209. meth_alias = "__eq"
  210. elif meth_name == "operator<":
  211. meth_alias = "__lt"
  212. elif meth_name == "operator<=":
  213. meth_alias = "__le"
  214. elif meth_name == "operator>":
  215. meth_alias = "__gt"
  216. elif meth_name == "operator>=":
  217. meth_alias = "__ge"
  218. elif meth_name == "operator=":
  219. meth_alias = "copy"
  220. else:
  221. meth_alias = meth_name
  222. meth_alias_txt = meth_el.get("alias")
  223. if meth_alias_txt is not None:
  224. meth_alias = meth_alias_txt
  225. return meth_alias
  226. def write_local_vars():
  227. wglue("LuaUserData* ud;")
  228. wglue("(void)ud;")
  229. wglue("void* voidp;")
  230. wglue("(void)voidp;")
  231. wglue("PtrSize size;")
  232. wglue("(void)size;")
  233. wglue("")
  234. def method(class_name, meth_el):
  235. """ Handle a method """
  236. meth_name = meth_el.get("name")
  237. meth_alias = get_meth_alias(meth_el)
  238. wglue("/// Pre-wrap method %s::%s." % (class_name, meth_name))
  239. wglue("static inline int pwrap%s%s(lua_State* l)" % (class_name, meth_alias))
  240. wglue("{")
  241. ident(1)
  242. write_local_vars()
  243. check_args(meth_el.find("args"), 1)
  244. # Get this pointer
  245. wglue("// Get \"this\" as \"self\"")
  246. wglue("if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfo%s, ud))" % class_name)
  247. wglue("{")
  248. ident(1)
  249. wglue("return -1;")
  250. ident(-1)
  251. wglue("}")
  252. wglue("")
  253. wglue("%s* self = ud->getData<%s>();" % (class_name, class_name))
  254. wglue("")
  255. args_str = args(meth_el.find("args"), 2)
  256. # Return value
  257. ret_txt = None
  258. ret_el = meth_el.find("return")
  259. if ret_el is not None:
  260. ret_txt = ret_el.text
  261. # Method call
  262. wglue("// Call the method")
  263. call = meth_el.find("overrideCall")
  264. if call is not None:
  265. call = call.text
  266. if call is not None:
  267. wglue("%s" % call)
  268. else:
  269. if ret_txt is None:
  270. wglue("self->%s(%s);" % (meth_name, args_str))
  271. else:
  272. wglue("%s ret = self->%s(%s);" % (ret_txt, meth_name, args_str))
  273. wglue("")
  274. ret(ret_el)
  275. ident(-1)
  276. wglue("}")
  277. wglue("")
  278. # Write the actual function
  279. wglue("/// Wrap method %s::%s." % (class_name, meth_name))
  280. wglue("static int wrap%s%s(lua_State* l)" % (class_name, meth_alias))
  281. wglue("{")
  282. ident(1)
  283. wglue("int res = pwrap%s%s(l);" % (class_name, meth_alias))
  284. wglue("if(res >= 0)")
  285. wglue("{")
  286. ident(1)
  287. wglue("return res;")
  288. ident(-1)
  289. wglue("}")
  290. wglue("")
  291. wglue("lua_error(l);")
  292. wglue("return 0;")
  293. ident(-1)
  294. wglue("}")
  295. wglue("")
  296. def static_method(class_name, meth_el):
  297. """ Handle a static method """
  298. meth_name = meth_el.get("name")
  299. meth_alias = get_meth_alias(meth_el)
  300. wglue("/// Pre-wrap static method %s::%s." % (class_name, meth_name))
  301. wglue("static inline int pwrap%s%s(lua_State* l)" % (class_name, meth_alias))
  302. wglue("{")
  303. ident(1)
  304. write_local_vars()
  305. check_args(meth_el.find("args"), 0)
  306. # Args
  307. args_str = args(meth_el.find("args"), 1)
  308. # Return value
  309. ret_txt = None
  310. ret_el = meth_el.find("return")
  311. if ret_el is not None:
  312. ret_txt = ret_el.text
  313. # Method call
  314. wglue("// Call the method")
  315. if ret_txt is None:
  316. wglue("%s::%s(%s);" % (class_name, meth_name, args_str))
  317. else:
  318. wglue("%s ret = %s::%s(%s);" % (ret_txt, class_name, meth_name, args_str))
  319. wglue("")
  320. ret(ret_el)
  321. ident(-1)
  322. wglue("}")
  323. wglue("")
  324. # Write the actual function
  325. wglue("/// Wrap static method %s::%s." % (class_name, meth_name))
  326. wglue("static int wrap%s%s(lua_State* l)" % (class_name, meth_alias))
  327. wglue("{")
  328. ident(1)
  329. wglue("int res = pwrap%s%s(l);" % (class_name, meth_alias))
  330. wglue("if(res >= 0)")
  331. wglue("{")
  332. ident(1)
  333. wglue("return res;")
  334. ident(-1)
  335. wglue("}")
  336. wglue("")
  337. wglue("lua_error(l);")
  338. wglue("return 0;")
  339. ident(-1)
  340. wglue("}")
  341. wglue("")
  342. def constructor(constr_el, class_name, constructor_idx):
  343. """ Handle constructor """
  344. wglue("/// Pre-wrap constructor for %s." % (class_name))
  345. wglue("static inline int pwrap%sCtor%d(lua_State* l)" % (class_name, constructor_idx))
  346. wglue("{")
  347. ident(1)
  348. write_local_vars()
  349. check_args(constr_el.find("args"), 0)
  350. # Args
  351. args_str = args(constr_el.find("args"), 1)
  352. # Create new userdata
  353. wglue("// Create user data")
  354. wglue("size = LuaUserData::computeSizeForGarbageCollected<%s>();" % class_name)
  355. wglue("voidp = lua_newuserdata(l, size);")
  356. wglue("luaL_setmetatable(l, luaUserDataTypeInfo%s.m_typeName);" % class_name)
  357. wglue("ud = static_cast<LuaUserData*>(voidp);")
  358. wglue("extern LuaUserDataTypeInfo luaUserDataTypeInfo%s;" % class_name)
  359. wglue("ud->initGarbageCollected(&luaUserDataTypeInfo%s);" % class_name)
  360. wglue("::new(ud->getData<%s>()) %s(%s);" % (class_name, class_name, args_str))
  361. wglue("")
  362. wglue("return 1;")
  363. ident(-1)
  364. wglue("}")
  365. wglue("")
  366. def constructors(constructors_el, class_name):
  367. """ Wrap all constructors """
  368. idx = 0
  369. func_names_and_arg_counts = []
  370. # Create the pre-wrap C functions
  371. for constructor_el in constructors_el.iter("constructor"):
  372. arg_count = count_args(constructor_el.find("args"))
  373. # Iterate all arg counts and make sure there are no duplicates
  374. for i in range(idx):
  375. if func_names_and_arg_counts[i][1] == arg_count:
  376. raise Exception("Every constructor overload should have a unique arg count. class: %s" % class_name)
  377. constructor(constructor_el, class_name, idx)
  378. func_names_and_arg_counts.append(["pwrap%sCtor%d" % (class_name, idx), arg_count])
  379. idx += 1
  380. if idx == 0:
  381. raise Exception("Found no <constructor>")
  382. # Create the landing function
  383. wglue("/// Wrap constructors for %s." % class_name)
  384. wglue("static int wrap%sCtor(lua_State* l)" % class_name)
  385. wglue("{")
  386. ident(1)
  387. if idx == 1:
  388. wglue("int res = pwrap%sCtor0(l);" % class_name)
  389. else:
  390. wglue("// Chose the right overload")
  391. wglue("const int argCount = lua_gettop(l);")
  392. wglue("int res = 0;")
  393. wglue("switch(argCount)")
  394. wglue("{")
  395. for name_and_arg_count in func_names_and_arg_counts:
  396. func_name = name_and_arg_count[0]
  397. arg_count = name_and_arg_count[1]
  398. wglue("case %d:" % arg_count)
  399. wglue("res = %s(l); break;" % func_name)
  400. wglue("default:")
  401. wglue("lua_pushfstring(l, \"Wrong overloaded new. Wrong number of arguments: %d\", argCount);")
  402. wglue("res = -1;")
  403. wglue("}")
  404. wglue("")
  405. wglue("if(res >= 0)")
  406. wglue("{")
  407. ident(1)
  408. wglue("return res;")
  409. ident(-1)
  410. wglue("}")
  411. wglue("")
  412. wglue("lua_error(l);")
  413. wglue("return 0;")
  414. ident(-1)
  415. wglue("}")
  416. wglue("")
  417. def destructor(class_name):
  418. """ Create a destructor """
  419. wglue("/// Wrap destructor for %s." % (class_name))
  420. wglue("static int wrap%sDtor(lua_State* l)" % class_name)
  421. wglue("{")
  422. ident(1)
  423. write_local_vars()
  424. check_args(None, 1)
  425. wglue("if(ANKI_UNLIKELY(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfo%s, ud)))" % class_name)
  426. wglue("{")
  427. ident(1)
  428. wglue("return -1;")
  429. ident(-1)
  430. wglue("}")
  431. wglue("")
  432. wglue("if(ud->isGarbageCollected())")
  433. wglue("{")
  434. ident(1)
  435. wglue("%s* inst = ud->getData<%s>();" % (class_name, class_name))
  436. wglue("inst->~%s();" % class_name)
  437. ident(-1)
  438. wglue("}")
  439. wglue("")
  440. wglue("return 0;")
  441. ident(-1)
  442. wglue("}")
  443. wglue("")
  444. def class_(class_el):
  445. """ Create a class """
  446. class_name = class_el.get("name")
  447. # Write serializer
  448. serialize = class_el.get("serialize") is not None and class_el.get("serialize") == "true"
  449. if serialize:
  450. # Serialize
  451. serialize_cb_name = "serialize%s" % class_name
  452. wglue("/// Serialize %s" % class_name)
  453. wglue("static void %s(LuaUserData& self, void* data, PtrSize& size)" % serialize_cb_name)
  454. wglue("{")
  455. ident(1)
  456. wglue("%s* obj = self.getData<%s>();" % (class_name, class_name))
  457. wglue("obj->serialize(data, size);")
  458. ident(-1)
  459. wglue("}")
  460. wglue("")
  461. # Deserialize
  462. deserialize_cb_name = "deserialize%s" % class_name
  463. wglue("/// De-serialize %s" % class_name)
  464. wglue("static void %s(const void* data, LuaUserData& self)" % deserialize_cb_name)
  465. wglue("{")
  466. ident(1)
  467. wglue("ANKI_ASSERT(data);")
  468. wglue("%s* obj = self.getData<%s>();" % (class_name, class_name))
  469. wglue("::new(obj) %s();" % class_name)
  470. wglue("obj->deserialize(data);")
  471. ident(-1)
  472. wglue("}")
  473. wglue("")
  474. else:
  475. serialize_cb_name = "nullptr"
  476. deserialize_cb_name = "nullptr"
  477. # Write the type info
  478. wglue("LuaUserDataTypeInfo luaUserDataTypeInfo%s = {" % class_name)
  479. ident(1)
  480. wglue("%d, \"%s\", LuaUserData::computeSizeForGarbageCollected<%s>(), %s, %s" %
  481. (type_sig(class_name), class_name, class_name, serialize_cb_name, deserialize_cb_name))
  482. ident(-1)
  483. wglue("};")
  484. wglue("")
  485. # Specialize the getDataTypeInfoFor
  486. wglue("template<>")
  487. wglue("const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<%s>()" % class_name)
  488. wglue("{")
  489. ident(1)
  490. wglue("return luaUserDataTypeInfo%s;" % class_name)
  491. ident(-1)
  492. wglue("}")
  493. wglue("")
  494. # Constructor declarations
  495. has_constructor = False
  496. constructors_el = class_el.find("constructors")
  497. if constructors_el is not None:
  498. has_constructor = True
  499. constructors(constructors_el, class_name)
  500. # Destructor declarations
  501. if has_constructor:
  502. destructor(class_name)
  503. # Methods LUA C functions declarations
  504. meth_names_aliases = []
  505. meths_el = class_el.find("methods")
  506. if meths_el is not None:
  507. for meth_el in meths_el.iter("method"):
  508. is_static = meth_el.get("static")
  509. is_static = is_static is not None and is_static == "1"
  510. if is_static:
  511. static_method(class_name, meth_el)
  512. else:
  513. method(class_name, meth_el)
  514. meth_name = meth_el.get("name")
  515. meth_alias = get_meth_alias(meth_el)
  516. meth_names_aliases.append([meth_name, meth_alias, is_static])
  517. # Start class declaration
  518. wglue("/// Wrap class %s." % class_name)
  519. wglue("static inline void wrap%s(lua_State* l)" % class_name)
  520. wglue("{")
  521. ident(1)
  522. wglue("LuaBinder::createClass(l, &luaUserDataTypeInfo%s);" % class_name)
  523. # Register constructor
  524. if has_constructor:
  525. wglue("LuaBinder::pushLuaCFuncStaticMethod(l, luaUserDataTypeInfo%s.m_typeName, \"new\", wrap%sCtor);" %
  526. (class_name, class_name))
  527. # Register destructor
  528. if has_constructor:
  529. wglue("LuaBinder::pushLuaCFuncMethod(l, \"__gc\", wrap%sDtor);" % class_name)
  530. # Register methods
  531. if len(meth_names_aliases) > 0:
  532. for meth_name_alias in meth_names_aliases:
  533. meth_alias = meth_name_alias[1]
  534. is_static = meth_name_alias[2]
  535. if is_static:
  536. wglue("LuaBinder::pushLuaCFuncStaticMethod(l, luaUserDataTypeInfo%s.m_typeName, \"%s\", wrap%s%s);" %
  537. (class_name, meth_alias, class_name, meth_alias))
  538. else:
  539. wglue("LuaBinder::pushLuaCFuncMethod(l, \"%s\", wrap%s%s);" % (meth_alias, class_name, meth_alias))
  540. wglue("lua_settop(l, 0);")
  541. ident(-1)
  542. wglue("}")
  543. wglue("")
  544. def function(func_el):
  545. """ Handle a plain function """
  546. func_name = func_el.get("name")
  547. func_alias = get_meth_alias(func_el)
  548. wglue("/// Pre-wrap function %s." % func_name)
  549. wglue("static inline int pwrap%s(lua_State* l)" % func_alias)
  550. wglue("{")
  551. ident(1)
  552. write_local_vars()
  553. check_args(func_el.find("args"), 0)
  554. # Args
  555. args_str = args(func_el.find("args"), 1)
  556. # Return value
  557. ret_txt = None
  558. ret_el = func_el.find("return")
  559. if ret_el is not None:
  560. ret_txt = ret_el.text
  561. # Call
  562. wglue("// Call the function")
  563. call = func_el.find("overrideCall")
  564. if call is not None:
  565. call = call.text
  566. if call is not None:
  567. wglue("%s" % call)
  568. else:
  569. if ret_txt is None:
  570. wglue("%s(%s);" % (func_name, args_str))
  571. else:
  572. wglue("%s ret = %s(%s);" % (ret_txt, func_name, args_str))
  573. wglue("")
  574. ret(ret_el)
  575. ident(-1)
  576. wglue("}")
  577. wglue("")
  578. # Write the actual function
  579. wglue("/// Wrap function %s." % func_name)
  580. wglue("static int wrap%s(lua_State* l)" % func_alias)
  581. wglue("{")
  582. ident(1)
  583. wglue("int res = pwrap%s(l);" % func_alias)
  584. wglue("if(res >= 0)")
  585. wglue("{")
  586. ident(1)
  587. wglue("return res;")
  588. ident(-1)
  589. wglue("}")
  590. wglue("")
  591. wglue("lua_error(l);")
  592. wglue("return 0;")
  593. ident(-1)
  594. wglue("}")
  595. wglue("")
  596. def main():
  597. """ Main function """
  598. global out_file
  599. filenames = parse_commandline()
  600. for filename in filenames:
  601. out_filename = get_base_fname(filename) + ".cpp"
  602. out_file = open(out_filename, "w")
  603. tree = et.parse(filename)
  604. root = tree.getroot()
  605. # Head
  606. head = root.find("head")
  607. if head is not None:
  608. wglue("%s" % head.text)
  609. wglue("")
  610. # Classes
  611. class_names = []
  612. for cls in root.iter("classes"):
  613. for cl in cls.iter("class"):
  614. class_(cl)
  615. class_names.append(cl.get("name"))
  616. # Functions
  617. func_names = []
  618. for fs in root.iter("functions"):
  619. for f in fs.iter("function"):
  620. function(f)
  621. func_names.append(f.get("name"))
  622. # Wrap function
  623. wglue("/// Wrap the module.")
  624. wglue("void wrapModule%s(lua_State* l)" % get_base_fname(filename))
  625. wglue("{")
  626. ident(1)
  627. for class_name in class_names:
  628. wglue("wrap%s(l);" % class_name)
  629. for func_name in func_names:
  630. wglue("LuaBinder::pushLuaCFunc(l, \"%s\", wrap%s);" % (func_name, func_name))
  631. ident(-1)
  632. wglue("}")
  633. wglue("")
  634. # Tail
  635. tail = root.find("tail")
  636. if tail is not None:
  637. wglue("%s" % tail.text)
  638. wglue("")
  639. out_file.close()
  640. if __name__ == "__main__":
  641. main()