diff options
Diffstat (limited to '3rdparty/bgfx/scripts/bgfx-codegen.lua')
-rw-r--r-- | 3rdparty/bgfx/scripts/bgfx-codegen.lua | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/3rdparty/bgfx/scripts/bgfx-codegen.lua b/3rdparty/bgfx/scripts/bgfx-codegen.lua new file mode 100644 index 00000000000..4069b933f8a --- /dev/null +++ b/3rdparty/bgfx/scripts/bgfx-codegen.lua @@ -0,0 +1,330 @@ +-- Copyright 2019 云风 https://github.com/cloudwu . All rights reserved. +-- License (the same with bgfx) : https://github.com/bkaradzic/bgfx/blob/master/LICENSE + +local codegen = require "codegen" +local idl = codegen.idl "bgfx.idl" + +local func_actions = { + + c99 = "\n", + c99decl = "\n", + cppdecl = "\n", + interface_struct = "\n\t", + interface_import = ",\n\t\t\t", + c99_interface = "\n", + cpp_interface = "\n", + c99_functionid = "\n\t", + cpp_functionid = "\n\t\t", +} + +local type_actions = { + + cflags = "\n", + enums = "\n", + cenums = "\n", + structs = "\n", + cstructs = "\n", + handles = "\n", + chandles = "\n", + funcptrs = "\n", + cfuncptrs = "\n", +} + +local function cfunc(f) + return function(func) + if not func.cpponly then + return f(func) + end + end +end + +local funcgen = {} + +local functemp = {} + +functemp.interface_struct = "$CRET (*$CFUNCNAME)($CARGS);" +functemp.interface_import = "bgfx_$CFUNCNAME" +functemp.c99_interface = [[ +BGFX_C_API $CRET bgfx_$CFUNCNAME($CARGS) +{ + $CONVERSIONCTOC + $PRERETCTOCg_interface->$CFUNCNAME($CALLARGS); + $POSTRETCTOC +} +]] +functemp.c99_functionid = "BGFX_FUNCTION_ID_$CFUNCNAMEUPPER," +functemp.cpp_functionid = "$CFUNCNAMECAML," + +for action,temp in pairs(functemp) do + funcgen[action] = cfunc(function(func) + return codegen.apply_functemp(func, temp) + end) +end + +funcgen.cpp_interface= cfunc(function(func) + if not func.cfunc and not func.conly then + return codegen.apply_functemp(func, [[ +$RET $CLASSNAME$FUNCNAME($CPPARGS)$CONST +{ + $CONVERSIONCTOCPP + $PRERETCPPTOCg_interface->$CFUNCNAME($CALLARGSCPPTOC); + $POSTRETCPPTOC +} +]]) + end +end) + +funcgen.c99 = cfunc(function(func) + local temp + if func.cfunc then + temp = "/* BGFX_C_API $CRET bgfx_$CFUNCNAME($CARGS) */\n" + else + temp = [[ +BGFX_C_API $CRET bgfx_$CFUNCNAME($CARGS) +{ + $CONVERSION + $PRERET$CPPFUNC($CALLARGSCTOCPP); + $POSTRET +} +]] + end + return codegen.apply_functemp(func, temp) +end) + +local function cppdecl(func) + local doc = func.comments + if not doc and func.comment then + doc = { func.comment } + end + if doc then + local cname + if not func.cpponly then + if func.multicfunc then + cname = {} + for _, name in ipairs(func.multicfunc) do + cname[#cname+1] = "bgfx_" .. name + end + else + cname = "bgfx_" .. func.cname + end + end + doc = codegen.doxygen_type(doc, func, cname) + end + local funcdecl = codegen.apply_functemp(func, "$RET $FUNCNAME($ARGS)$CONST;\n") + if doc then + return doc .. "\n" .. funcdecl + else + return funcdecl + end +end + +function funcgen.cppdecl(func) + -- Don't generate member functions here + if not func.class and not func.conly then + return cppdecl(func) + end +end + +funcgen.c99decl = cfunc(function(func) + local doc = func.comments + if not doc and func.comment then + doc = { func.comment } + end + if doc then + doc = codegen.doxygen_ctype(doc, func) + end + local funcdecl = codegen.apply_functemp(func, "BGFX_C_API $CRET bgfx_$CFUNCNAME($CARGS);") + if doc then + return "\n" .. doc .. "\n" .. funcdecl + else + return funcdecl + end +end) + +local typegen = {} + +local function add_doxygen(typedef, define, cstyle, cname) + local func = cstyle and codegen.doxygen_ctype or codegen.doxygen_type + local doc = func(typedef.comments, typedef, cname or typedef.cname) + if doc then + return doc .. "\n" .. define + else + return define + end +end + +function typegen.enums(typedef) + if typedef.enum then + return add_doxygen(typedef, codegen.gen_enum_define(typedef), false, "bgfx_" .. typedef.cname) + end +end + +function typegen.cenums(typedef) + if typedef.enum then + return add_doxygen(typedef, codegen.gen_enum_cdefine(typedef), true) + end +end + +function typegen.cflags(typedef) + if typedef.flag then + return add_doxygen(typedef, codegen.gen_flag_cdefine(typedef), true) + end +end + +function typegen.structs(typedef) + if typedef.struct and not typedef.namespace then + local methods = typedef.methods + if methods then + local m = {} + for _, func in ipairs(methods) do + m[#m+1] = cppdecl(func) + end + methods = m + end + return add_doxygen(typedef, codegen.gen_struct_define(typedef, methods)) + end +end + +function typegen.cstructs(typedef) + if typedef.struct then + return add_doxygen(typedef, codegen.gen_struct_cdefine(typedef), true) + end +end + +function typegen.handles(typedef) + if typedef.handle then + return codegen.gen_handle(typedef) + end +end + +function typegen.chandles(typedef) + if typedef.handle then + return codegen.gen_chandle(typedef) + end +end + +function typegen.funcptrs(typedef) + if typedef.args then + return add_doxygen(typedef, codegen.gen_funcptr(typedef)) + end +end + +function typegen.cfuncptrs(typedef) + if typedef.args then + return add_doxygen(typedef, codegen.gen_cfuncptr(typedef), true) + end +end + +local function codes() + local temp = {} + for k in pairs(func_actions) do + temp[k] = {} + end + + for k in pairs(type_actions) do + temp[k] = {} + end + + -- call actions with func + for _, f in ipairs(idl.funcs) do + for k in pairs(func_actions) do + local funcgen = funcgen[k] + if funcgen then + table.insert(temp[k], (funcgen(f))) + end + end + end + + -- call actions with type + + for _, typedef in ipairs(idl.types) do + for k in pairs(type_actions) do + local typegen = typegen[k] + if typegen then + table.insert(temp[k], (typegen(typedef))) + end + end + end + + for k, indent in pairs(func_actions) do + temp[k] = table.concat(temp[k], indent) + end + for k, indent in pairs(type_actions) do + temp[k] = table.concat(temp[k], indent) + end + + temp.version = string.format("#define BGFX_API_VERSION UINT32_C(%d)", idl._version or 0) + + return temp +end + +local codes_tbl = codes() + +local function add_path(filename) + local path + if type(paths) == "string" then + path = paths + else + path = assert(paths[filename]) + end + return path .. "/" .. filename +end + +local function change_indent(str, indent) + if indent == "\t" then + -- strip trailing space only + return (str:gsub("(.-)\n", function (line) + return line:gsub("([ \t]*)$","\n") end)) + else + return (str:gsub("(.-)\n", function (line) + return line:gsub("^(\t*)(.-)[ \t]*$", + function (tabs, content) + return indent:rep(#tabs) .. content .. "\n" + end) + end)) + end +end + +local gen = {} + +function gen.apply(tempfile) + local f = assert(io.open(tempfile, "rb")) + local temp = f:read "a" + f:close() + codes_tbl.source = tempfile + return (temp:gsub("$([%l%d_]+)", codes_tbl)) +end + +function gen.format(codes, f) + return change_indent(codes, f.indent) +end + +function gen.changed(codes, outputfile) + local out = io.open(outputfile, "rb") + if out then + local origin = out:read "a" + out:close() + return origin ~= codes + end + return true +end + +function gen.write(codes, outputfile) + local out = assert(io.open(outputfile, "wb")) + out:write(codes) + out:close() +end + +function gen.gen(tempfile, outputfile, indent) + print ("Generate", outputfile, "from", tempfile) + local codes = gen.apply(tempfile) + codes = change_indent(codes, indent) + + if not gen.changed(codes, outputfile) then + print("No change") + end + + gen.write(codes, outputfile) +end + +return gen |