| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- -- 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) or func.conly 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
- if not func.conly then
- m[#m+1] = cppdecl(func)
- end
- 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
|