| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893 |
- #!/usr/bin/python
- # Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
- # All rights reserved.
- # Code licensed under the BSD License.
- # http://www.anki3d.org/LICENSE
- import os
- import optparse
- import xml.etree.ElementTree as et
- # Globals
- g_identation_level = 0
- g_out_file = None
- g_enum_names = []
- def parse_commandline():
- """ Parse the command line arguments """
- parser = optparse.OptionParser(usage="usage: %prog [options]", description="Create LUA bindings using XML")
- parser.add_option("-i",
- "--input",
- dest="inp",
- type="string",
- help="specify the XML files to parse. Seperate with :")
- (options, args) = parser.parse_args()
- if not options.inp:
- parser.error("argument is missing")
- return options.inp.split(":")
- def type_sig(value):
- """ Calculate the signature of a type """
- if not isinstance(value, str):
- raise Exception("Expecting string")
- return hash(value)
- def get_base_fname(path):
- """ From path/to/a/file.ext return the "file" """
- return os.path.splitext(os.path.basename(path))[0]
- def wglue(txt):
- """ Write glue code to the output """
- global g_out_file
- global g_identation_level
- g_out_file.write("%s%s\n" % ("\t" * g_identation_level, txt))
- def ident(number):
- """ Increase or recrease identation for the wglue """
- global g_identation_level
- g_identation_level += number
- def type_is_bool(type):
- """ Check if a type is boolean """
- return type == "Bool" or type == "bool"
- def type_is_enum(type):
- """ Check if a type string is an enum """
- global g_enum_names
- return type in g_enum_names
- def type_is_number(type):
- """ Check if a type is number """
- numbers = [
- "U8", "U16", "U32", "U64", "I8", "I16", "I32", "I64", "U", "I", "PtrSize", "F32", "F64", "int", "unsigned",
- "unsigned int", "short", "unsigned short", "uint", "float", "double"
- ]
- it_is = False
- for num in numbers:
- if num == type:
- it_is = True
- break
- return it_is
- def parse_type_decl(arg_txt):
- """ Parse an arg text """
- tokens = arg_txt.split(" ")
- tokens_size = len(tokens)
- type = tokens[tokens_size - 1]
- type_len = len(type)
- is_ptr = False
- is_ref = False
- if type[type_len - 1] == "&":
- is_ref = True
- elif type[type_len - 1] == "*":
- is_ptr = True
- if is_ref or is_ptr:
- type = type[:-1]
- is_const = False
- if tokens[0] == "const":
- is_const = True
- return (type, is_ref, is_ptr, is_const)
- def ret(ret_el):
- """ Push return value """
- if ret_el is None:
- wglue("return 0;")
- return
- wglue("// Push return value")
- type_txt = ret_el.text
- (type, is_ref, is_ptr, is_const) = parse_type_decl(type_txt)
- if is_ptr:
- if ret_el.get("canBeNullptr") is not None and ret_el.get("canBeNullptr") == "1":
- can_be_nullptr = True
- else:
- can_be_nullptr = False
- wglue("if(ret == nullptr) [[unlikely]]")
- wglue("{")
- ident(1)
- if can_be_nullptr:
- wglue("lua_pushnil(l);")
- wglue("return 1;")
- else:
- wglue("lua_pushstring(l, \"Glue code returned nullptr\");")
- wglue("return -1;")
- ident(-1)
- wglue("}")
- wglue("")
- if type_is_bool(type):
- wglue("lua_pushboolean(l, ret);")
- elif type_is_number(type):
- wglue("lua_pushnumber(l, lua_Number(ret));")
- elif type == "char" or type == "CString":
- wglue("lua_pushstring(l, &ret[0]);")
- elif type == "Error":
- wglue("if(ret) [[unlikely]]")
- wglue("{")
- ident(1)
- wglue("lua_pushstring(l, \"Glue code returned an error\");")
- wglue("return -1;")
- ident(-1)
- wglue("}")
- wglue("")
- wglue("lua_pushnumber(l, lua_Number(!!ret));")
- else:
- if is_ptr or is_ref:
- wglue("voidp = lua_newuserdata(l, sizeof(LuaUserData));")
- wglue("ud = static_cast<LuaUserData*>(voidp);")
- wglue("luaL_setmetatable(l, \"%s\");" % type)
- wglue("extern LuaUserDataTypeInfo luaUserDataTypeInfo%s;" % type)
- if is_ptr:
- wglue("ud->initPointed(&luaUserDataTypeInfo%s, ret);" % type)
- elif is_ref:
- wglue("ud->initPointed(&luaUserDataTypeInfo%s, &ret);" % type)
- else:
- wglue("size = LuaUserData::computeSizeForGarbageCollected<%s>();" % type)
- wglue("voidp = lua_newuserdata(l, size);")
- wglue("luaL_setmetatable(l, \"%s\");" % type)
- wglue("ud = static_cast<LuaUserData*>(voidp);")
- wglue("extern LuaUserDataTypeInfo luaUserDataTypeInfo%s;" % type)
- wglue("ud->initGarbageCollected(&luaUserDataTypeInfo%s);" % type)
- wglue("::new(ud->getData<%s>()) %s(std::move(ret));" % (type, type))
- wglue("")
- wglue("return 1;")
- def arg(arg_txt, stack_index, index):
- """ Write the pop code for a single argument """
- (type, is_ref, is_ptr, is_const) = parse_type_decl(arg_txt)
- if type_is_bool(type) or type_is_number(type):
- wglue("%s arg%d;" % (type, index))
- wglue("if(LuaBinder::checkNumber(l, %d, arg%d)) [[unlikely]]" % (stack_index, index))
- wglue("{")
- ident(1)
- wglue("return -1;")
- ident(-1)
- wglue("}")
- elif type == "char" or type == "CString":
- wglue("const char* arg%d;" % index)
- wglue("if(LuaBinder::checkString(l, %d, arg%d)) [[unlikely]]" % (stack_index, index))
- wglue("{")
- ident(1)
- wglue("return -1;")
- ident(-1)
- wglue("}")
- elif type_is_enum(type):
- wglue("lua_Number arg%dTmp;" % index)
- wglue("if(LuaBinder::checkNumber(l, %d, arg%dTmp)) [[unlikely]]" % (stack_index, index))
- wglue("{")
- ident(1)
- wglue("return -1;")
- ident(-1)
- wglue("}")
- wglue("const %s arg%d = %s(arg%dTmp);" % (type, index, type, index))
- else:
- # Must be user type
- wglue("extern LuaUserDataTypeInfo luaUserDataTypeInfo%s;" % type)
- wglue("if(LuaBinder::checkUserData(l, %d, luaUserDataTypeInfo%s, ud)) [[unlikely]]" % (stack_index, type))
- wglue("{")
- ident(1)
- wglue("return -1;")
- ident(-1)
- wglue("}")
- wglue("")
- wglue("%s* iarg%d = ud->getData<%s>();" % (type, index, type))
- if is_ptr:
- wglue("%s arg%d(iarg%d);" % (arg_txt, index, index))
- else:
- wglue("%s arg%d(*iarg%d);" % (arg_txt, index, index))
- def args(args_el, stack_index):
- """ Write the pop code for argument parsing and return the arg list """
- if args_el is None:
- return ""
- wglue("// Pop arguments")
- arg_index = 0
- # Do the work
- args_str = ""
- arg_index = 0
- for arg_el in args_el.iter("arg"):
- arg(arg_el.text, stack_index, arg_index)
- args_str += "arg%d, " % arg_index
- wglue("")
- stack_index += 1
- arg_index += 1
- if len(args_str) > 0:
- args_str = args_str[:-2]
- return args_str
- def count_args(args_el):
- """ Count the number of arguments """
- if args_el is None:
- return 0
- count = 0
- for arg_el in args_el.iter("arg"):
- count += 1
- return count
- def check_args(args_el, bias):
- """ Check number of args. Call that first because it throws error """
- if args_el is not None:
- count = bias + count_args(args_el)
- else:
- count = bias
- wglue("if(LuaBinder::checkArgsCount(l, %d)) [[unlikely]]" % count)
- wglue("{")
- ident(1)
- wglue("return -1;")
- ident(-1)
- wglue("}")
- wglue("")
- def get_meth_alias(meth_el):
- """ Return the method alias """
- meth_name = meth_el.get("name")
- if meth_name == "operator+":
- meth_alias = "__add"
- elif meth_name == "operator-":
- meth_alias = "__sub"
- elif meth_name == "operator*":
- meth_alias = "__mul"
- elif meth_name == "operator/":
- meth_alias = "__div"
- elif meth_name == "operator==":
- meth_alias = "__eq"
- elif meth_name == "operator<":
- meth_alias = "__lt"
- elif meth_name == "operator<=":
- meth_alias = "__le"
- elif meth_name == "operator>":
- meth_alias = "__gt"
- elif meth_name == "operator>=":
- meth_alias = "__ge"
- elif meth_name == "operator=":
- meth_alias = "copy"
- else:
- meth_alias = meth_name
- meth_alias_txt = meth_el.get("alias")
- if meth_alias_txt is not None:
- meth_alias = meth_alias_txt
- return meth_alias
- def write_local_vars():
- wglue("[[maybe_unused]] LuaUserData* ud;")
- wglue("[[maybe_unused]] void* voidp;")
- wglue("[[maybe_unused]] PtrSize size;")
- wglue("")
- def method(class_name, meth_el):
- """ Handle a method """
- meth_name = meth_el.get("name")
- meth_alias = get_meth_alias(meth_el)
- wglue("/// Pre-wrap method %s::%s." % (class_name, meth_name))
- wglue("static inline int pwrap%s%s(lua_State* l)" % (class_name, meth_alias))
- wglue("{")
- ident(1)
- write_local_vars()
- check_args(meth_el.find("args"), 1)
- # Get this pointer
- wglue("// Get \"this\" as \"self\"")
- wglue("if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfo%s, ud))" % class_name)
- wglue("{")
- ident(1)
- wglue("return -1;")
- ident(-1)
- wglue("}")
- wglue("")
- wglue("%s* self = ud->getData<%s>();" % (class_name, class_name))
- wglue("")
- args_str = args(meth_el.find("args"), 2)
- # Return value
- ret_txt = None
- ret_el = meth_el.find("return")
- if ret_el is not None:
- ret_txt = ret_el.text
- # Method call
- wglue("// Call the method")
- call = meth_el.find("overrideCall")
- if call is not None:
- call = call.text
- if call is not None:
- wglue("%s" % call)
- else:
- if ret_txt is None:
- wglue("self->%s(%s);" % (meth_name, args_str))
- else:
- wglue("%s ret = self->%s(%s);" % (ret_txt, meth_name, args_str))
- wglue("")
- ret(ret_el)
- ident(-1)
- wglue("}")
- wglue("")
- # Write the actual function
- wglue("/// Wrap method %s::%s." % (class_name, meth_name))
- wglue("static int wrap%s%s(lua_State* l)" % (class_name, meth_alias))
- wglue("{")
- ident(1)
- wglue("int res = pwrap%s%s(l);" % (class_name, meth_alias))
- wglue("if(res >= 0)")
- wglue("{")
- ident(1)
- wglue("return res;")
- ident(-1)
- wglue("}")
- wglue("")
- wglue("lua_error(l);")
- wglue("return 0;")
- ident(-1)
- wglue("}")
- wglue("")
- def static_method(class_name, meth_el):
- """ Handle a static method """
- meth_name = meth_el.get("name")
- meth_alias = get_meth_alias(meth_el)
- wglue("/// Pre-wrap static method %s::%s." % (class_name, meth_name))
- wglue("static inline int pwrap%s%s(lua_State* l)" % (class_name, meth_alias))
- wglue("{")
- ident(1)
- write_local_vars()
- check_args(meth_el.find("args"), 0)
- # Args
- args_str = args(meth_el.find("args"), 1)
- # Return value
- ret_txt = None
- ret_el = meth_el.find("return")
- if ret_el is not None:
- ret_txt = ret_el.text
- # Method call
- wglue("// Call the method")
- if ret_txt is None:
- wglue("%s::%s(%s);" % (class_name, meth_name, args_str))
- else:
- wglue("%s ret = %s::%s(%s);" % (ret_txt, class_name, meth_name, args_str))
- wglue("")
- ret(ret_el)
- ident(-1)
- wglue("}")
- wglue("")
- # Write the actual function
- wglue("/// Wrap static method %s::%s." % (class_name, meth_name))
- wglue("static int wrap%s%s(lua_State* l)" % (class_name, meth_alias))
- wglue("{")
- ident(1)
- wglue("int res = pwrap%s%s(l);" % (class_name, meth_alias))
- wglue("if(res >= 0)")
- wglue("{")
- ident(1)
- wglue("return res;")
- ident(-1)
- wglue("}")
- wglue("")
- wglue("lua_error(l);")
- wglue("return 0;")
- ident(-1)
- wglue("}")
- wglue("")
- def constructor(constr_el, class_name, constructor_idx):
- """ Handle constructor """
- wglue("/// Pre-wrap constructor for %s." % (class_name))
- wglue("static inline int pwrap%sCtor%d(lua_State* l)" % (class_name, constructor_idx))
- wglue("{")
- ident(1)
- write_local_vars()
- check_args(constr_el.find("args"), 0)
- # Args
- args_str = args(constr_el.find("args"), 1)
- # Create new userdata
- wglue("// Create user data")
- wglue("size = LuaUserData::computeSizeForGarbageCollected<%s>();" % class_name)
- wglue("voidp = lua_newuserdata(l, size);")
- wglue("luaL_setmetatable(l, luaUserDataTypeInfo%s.m_typeName);" % class_name)
- wglue("ud = static_cast<LuaUserData*>(voidp);")
- wglue("extern LuaUserDataTypeInfo luaUserDataTypeInfo%s;" % class_name)
- wglue("ud->initGarbageCollected(&luaUserDataTypeInfo%s);" % class_name)
- wglue("::new(ud->getData<%s>()) %s(%s);" % (class_name, class_name, args_str))
- wglue("")
- wglue("return 1;")
- ident(-1)
- wglue("}")
- wglue("")
- def constructors(constructors_el, class_name):
- """ Wrap all constructors """
- idx = 0
- func_names_and_arg_counts = []
- # Create the pre-wrap C functions
- for constructor_el in constructors_el.iter("constructor"):
- arg_count = count_args(constructor_el.find("args"))
- # Iterate all arg counts and make sure there are no duplicates
- for i in range(idx):
- if func_names_and_arg_counts[i][1] == arg_count:
- raise Exception("Every constructor overload should have a unique arg count. class: %s" % class_name)
- constructor(constructor_el, class_name, idx)
- func_names_and_arg_counts.append(["pwrap%sCtor%d" % (class_name, idx), arg_count])
- idx += 1
- if idx == 0:
- raise Exception("Found no <constructor>")
- # Create the landing function
- wglue("/// Wrap constructors for %s." % class_name)
- wglue("static int wrap%sCtor(lua_State* l)" % class_name)
- wglue("{")
- ident(1)
- if idx == 1:
- wglue("int res = pwrap%sCtor0(l);" % class_name)
- else:
- wglue("// Chose the right overload")
- wglue("const int argCount = lua_gettop(l);")
- wglue("int res = 0;")
- wglue("switch(argCount)")
- wglue("{")
- for name_and_arg_count in func_names_and_arg_counts:
- func_name = name_and_arg_count[0]
- arg_count = name_and_arg_count[1]
- wglue("case %d:" % arg_count)
- wglue("res = %s(l); break;" % func_name)
- wglue("default:")
- wglue("lua_pushfstring(l, \"Wrong overloaded new. Wrong number of arguments: %d\", argCount);")
- wglue("res = -1;")
- wglue("}")
- wglue("")
- wglue("if(res >= 0)")
- wglue("{")
- ident(1)
- wglue("return res;")
- ident(-1)
- wglue("}")
- wglue("")
- wglue("lua_error(l);")
- wglue("return 0;")
- ident(-1)
- wglue("}")
- wglue("")
- def destructor(class_name):
- """ Create a destructor """
- wglue("/// Wrap destructor for %s." % (class_name))
- wglue("static int wrap%sDtor(lua_State* l)" % class_name)
- wglue("{")
- ident(1)
- write_local_vars()
- check_args(None, 1)
- wglue("if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfo%s, ud)) [[unlikely]]" % class_name)
- wglue("{")
- ident(1)
- wglue("return -1;")
- ident(-1)
- wglue("}")
- wglue("")
- wglue("if(ud->isGarbageCollected())")
- wglue("{")
- ident(1)
- wglue("%s* inst = ud->getData<%s>();" % (class_name, class_name))
- wglue("inst->~%s();" % class_name)
- ident(-1)
- wglue("}")
- wglue("")
- wglue("return 0;")
- ident(-1)
- wglue("}")
- wglue("")
- def class_(class_el):
- """ Create a class """
- class_name = class_el.get("name")
- # Write serializer
- serialize = class_el.get("serialize") is not None and class_el.get("serialize") == "true"
- if serialize:
- # Serialize
- serialize_cb_name = "serialize%s" % class_name
- wglue("/// Serialize %s" % class_name)
- wglue("static void %s(LuaUserData& self, void* data, PtrSize& size)" % serialize_cb_name)
- wglue("{")
- ident(1)
- wglue("%s* obj = self.getData<%s>();" % (class_name, class_name))
- wglue("obj->serialize(data, size);")
- ident(-1)
- wglue("}")
- wglue("")
- # Deserialize
- deserialize_cb_name = "deserialize%s" % class_name
- wglue("/// De-serialize %s" % class_name)
- wglue("static void %s(const void* data, LuaUserData& self)" % deserialize_cb_name)
- wglue("{")
- ident(1)
- wglue("ANKI_ASSERT(data);")
- wglue("%s* obj = self.getData<%s>();" % (class_name, class_name))
- wglue("::new(obj) %s();" % class_name)
- wglue("obj->deserialize(data);")
- ident(-1)
- wglue("}")
- wglue("")
- else:
- serialize_cb_name = "nullptr"
- deserialize_cb_name = "nullptr"
- # Write the type info
- wglue("LuaUserDataTypeInfo luaUserDataTypeInfo%s = {" % class_name)
- ident(1)
- wglue("%d, \"%s\", LuaUserData::computeSizeForGarbageCollected<%s>(), %s, %s" %
- (type_sig(class_name), class_name, class_name, serialize_cb_name, deserialize_cb_name))
- ident(-1)
- wglue("};")
- wglue("")
- # Specialize the getDataTypeInfoFor
- wglue("template<>")
- wglue("const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<%s>()" % class_name)
- wglue("{")
- ident(1)
- wglue("return luaUserDataTypeInfo%s;" % class_name)
- ident(-1)
- wglue("}")
- wglue("")
- # Constructor declarations
- has_constructor = False
- constructors_el = class_el.find("constructors")
- if constructors_el is not None:
- has_constructor = True
- constructors(constructors_el, class_name)
- # Destructor declarations
- if has_constructor:
- destructor(class_name)
- # Methods LUA C functions declarations
- meth_names_aliases = []
- meths_el = class_el.find("methods")
- if meths_el is not None:
- for meth_el in meths_el.iter("method"):
- is_static = meth_el.get("static")
- is_static = is_static is not None and is_static == "1"
- if is_static:
- static_method(class_name, meth_el)
- else:
- method(class_name, meth_el)
- meth_name = meth_el.get("name")
- meth_alias = get_meth_alias(meth_el)
- meth_names_aliases.append([meth_name, meth_alias, is_static])
- # Start class declaration
- wglue("/// Wrap class %s." % class_name)
- wglue("static inline void wrap%s(lua_State* l)" % class_name)
- wglue("{")
- ident(1)
- wglue("LuaBinder::createClass(l, &luaUserDataTypeInfo%s);" % class_name)
- # Register constructor
- if has_constructor:
- wglue("LuaBinder::pushLuaCFuncStaticMethod(l, luaUserDataTypeInfo%s.m_typeName, \"new\", wrap%sCtor);" %
- (class_name, class_name))
- # Register destructor
- if has_constructor:
- wglue("LuaBinder::pushLuaCFuncMethod(l, \"__gc\", wrap%sDtor);" % class_name)
- # Register methods
- if len(meth_names_aliases) > 0:
- for meth_name_alias in meth_names_aliases:
- meth_alias = meth_name_alias[1]
- is_static = meth_name_alias[2]
- if is_static:
- wglue("LuaBinder::pushLuaCFuncStaticMethod(l, luaUserDataTypeInfo%s.m_typeName, \"%s\", wrap%s%s);" %
- (class_name, meth_alias, class_name, meth_alias))
- else:
- wglue("LuaBinder::pushLuaCFuncMethod(l, \"%s\", wrap%s%s);" % (meth_alias, class_name, meth_alias))
- wglue("lua_settop(l, 0);")
- ident(-1)
- wglue("}")
- wglue("")
- def function(func_el):
- """ Handle a plain function """
- func_name = func_el.get("name")
- func_alias = get_meth_alias(func_el)
- wglue("/// Pre-wrap function %s." % func_name)
- wglue("static inline int pwrap%s(lua_State* l)" % func_alias)
- wglue("{")
- ident(1)
- write_local_vars()
- check_args(func_el.find("args"), 0)
- # Args
- args_str = args(func_el.find("args"), 1)
- # Return value
- ret_txt = None
- ret_el = func_el.find("return")
- if ret_el is not None:
- ret_txt = ret_el.text
- # Call
- wglue("// Call the function")
- call = func_el.find("overrideCall")
- if call is not None:
- call = call.text
- if call is not None:
- wglue("%s" % call)
- else:
- if ret_txt is None:
- wglue("%s(%s);" % (func_name, args_str))
- else:
- wglue("%s ret = %s(%s);" % (ret_txt, func_name, args_str))
- wglue("")
- ret(ret_el)
- ident(-1)
- wglue("}")
- wglue("")
- # Write the actual function
- wglue("/// Wrap function %s." % func_name)
- wglue("static int wrap%s(lua_State* l)" % func_alias)
- wglue("{")
- ident(1)
- wglue("int res = pwrap%s(l);" % func_alias)
- wglue("if(res >= 0)")
- wglue("{")
- ident(1)
- wglue("return res;")
- ident(-1)
- wglue("}")
- wglue("")
- wglue("lua_error(l);")
- wglue("return 0;")
- ident(-1)
- wglue("}")
- wglue("")
- def enum(enum_el):
- enum_name = enum_el.get("name")
- # Write the type info
- wglue("LuaUserDataTypeInfo luaUserDataTypeInfo%s = {" % enum_name)
- ident(1)
- wglue("%d, \"%s\", 0, nullptr, nullptr" % (type_sig(enum_name), enum_name))
- ident(-1)
- wglue("};")
- wglue("")
- # Specialize the getDataTypeInfoFor
- wglue("template<>")
- wglue("const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<%s>()" % enum_name)
- wglue("{")
- ident(1)
- wglue("return luaUserDataTypeInfo%s;" % enum_name)
- ident(-1)
- wglue("}")
- wglue("")
- # Start declaration
- wglue("/// Wrap enum %s." % enum_name)
- wglue("static inline void wrap%s(lua_State* l)" % enum_name)
- wglue("{")
- ident(1)
- wglue("lua_newtable(l);") # Push new table
- wglue("lua_setglobal(l, luaUserDataTypeInfo%s.m_typeName);" % enum_name) # Pop and make global
- wglue("lua_getglobal(l, luaUserDataTypeInfo%s.m_typeName);" % enum_name) # Push the table again
- wglue("")
- # Now the table is at the top of the stack
- for enumerant_el in enum_el.iter("enumerant"):
- enumerant_name = enumerant_el.get("name")
- wglue("lua_pushstring(l, \"%s\");" % enumerant_name) # Push key
- wglue("ANKI_ASSERT(%s(lua_Number(%s::%s)) == %s::%s && \"Can't map the enumerant to a lua_Number\");" %
- (enum_name, enum_name, enumerant_name, enum_name, enumerant_name))
- wglue("lua_pushnumber(l, lua_Number(%s::%s));" % (enum_name, enumerant_name)) # Push value
- wglue("lua_settable(l, -3);") # Do table[key]=value and pop 2. The table is at the top of the stack
- wglue("")
- # Done
- wglue("lua_settop(l, 0);")
- ident(-1)
- wglue("}")
- wglue("")
- def main():
- """ Main function """
- global g_out_file
- filenames = parse_commandline()
- for filename in filenames:
- out_filename = get_base_fname(filename) + ".cpp"
- g_out_file = open(out_filename, "w", newline="\n")
- tree = et.parse(filename)
- root = tree.getroot()
- # Head
- head = root.find("head")
- if head is not None:
- wglue("%s" % head.text)
- wglue("")
- # Enums (First because others use the g_enum_names)
- global g_enum_names
- for enums in root.iter("enums"):
- for enum_el in enums.iter("enum"):
- enum(enum_el)
- g_enum_names.append(enum_el.get("name"))
- # Classes
- class_names = []
- for cls in root.iter("classes"):
- for cl in cls.iter("class"):
- class_(cl)
- class_names.append(cl.get("name"))
- # Functions
- func_names = []
- for fs in root.iter("functions"):
- for f in fs.iter("function"):
- function(f)
- func_names.append(f.get("name"))
- # Wrap function
- wglue("/// Wrap the module.")
- wglue("void wrapModule%s(lua_State* l)" % get_base_fname(filename))
- wglue("{")
- ident(1)
- for class_name in class_names:
- wglue("wrap%s(l);" % class_name)
- for func_name in func_names:
- wglue("LuaBinder::pushLuaCFunc(l, \"%s\", wrap%s);" % (func_name, func_name))
- for enum_name in g_enum_names:
- wglue("wrap%s(l);" % enum_name)
- ident(-1)
- wglue("}")
- wglue("")
- # Tail
- tail = root.find("tail")
- if tail is not None:
- wglue("%s" % tail.text)
- wglue("")
- g_out_file.close()
- if __name__ == "__main__":
- main()
|