mirror of
https://github.com/pound-emu/ballistic.git
synced 2026-06-17 04:16:48 -07:00
This adds luajit-imgui without submodules. Signed-off-by: Ronald Caesar <github43132@proton.me>
746 lines
23 KiB
Lua
746 lines
23 KiB
Lua
-----------------------------------------------
|
|
-- script to build lua classes
|
|
-- expects lua 5.1 or luajit
|
|
-- expects "../cimgui/generator/definitions.lua" to be generated in cimgui (master_auto2 branch)
|
|
-----------------------------------------------
|
|
|
|
local cpp2ffi = require"cpp2ffi"
|
|
local ffi = require"ffi"
|
|
--utility functions
|
|
local ffi_cdef = function(code)
|
|
local ret,err = pcall(ffi.cdef,code)
|
|
if not ret then
|
|
local lineN = 1
|
|
for line in code:gmatch("([^\n\r]*)\r?\n") do
|
|
print(lineN, line)
|
|
lineN = lineN + 1
|
|
end
|
|
print(err)
|
|
error"bad cdef"
|
|
end
|
|
end
|
|
|
|
local strsplit = cpp2ffi.strsplit
|
|
|
|
-------------------------------------------------
|
|
-------------------------------------------------
|
|
local enumnames = {}
|
|
local enumsvalues = {}
|
|
local constants = {}
|
|
local opaque_structs = {}
|
|
|
|
|
|
--[[ tests
|
|
require"anima.utils" --gives us prtable
|
|
-- prtable(structs.ImFontConfig)
|
|
-- prtable(fundefs.igCombo)
|
|
local defaults = {}
|
|
for fun,defs in pairs(fundefs) do
|
|
for i,def in ipairs(defs) do
|
|
for k,v in pairs(def.defaults) do
|
|
defaults[v]=true
|
|
end
|
|
end
|
|
end
|
|
prtable(defaults)
|
|
do return end
|
|
--]]
|
|
|
|
--test correctness of generated lua code
|
|
local function testcode(codestr)
|
|
local fl,err = loadstring(codestr)
|
|
if not fl then
|
|
local linenum = err:match(":(%d+):")
|
|
linenum = tonumber(linenum)
|
|
--print("error on:",linenum,code[linenum])
|
|
local lineN,codelines = 1,{}
|
|
for line in codestr:gmatch("([^\n\r]*)\r?\n") do
|
|
print(lineN, line)
|
|
table.insert(codelines, line)
|
|
lineN = lineN + 1
|
|
end
|
|
print("error is ",err)
|
|
print("in line: ", codelines[linenum])
|
|
error("error in testcode",2)
|
|
end
|
|
end
|
|
|
|
--this replaces reserved lua words and not valid tokens
|
|
local function sanitize_reserved(def)
|
|
local words = {["in"]="_in",["repeat"]="_repeat"}
|
|
for k,w in pairs(words) do
|
|
local pat = "([%(,])("..k..")([,%)])"
|
|
if def.call_args_old:match(pat) then
|
|
--print("found",def.cimguiname,def.call_args_old,def.call_args_old:match(pat))
|
|
def.call_args_old = def.call_args_old:gsub(pat,"%1"..w.."%3")
|
|
--print(def.call_args_old)
|
|
--sanitize defaults
|
|
if def.defaults[k]~=nil then
|
|
def.defaults[w] = def.defaults[k]
|
|
def.defaults[k] = nil
|
|
end
|
|
for i,na in ipairs(def.argsT) do
|
|
if na.name == k then
|
|
na.name = w
|
|
end
|
|
end
|
|
end
|
|
end
|
|
--correct default vals
|
|
for k,v in pairs(def.defaults) do
|
|
--if type(v)=="number" then print("aver",def.cimguiname,type(v),k,v) end
|
|
--do only if not a c string
|
|
local is_cstring = v:sub(1,1)=='"' and v:sub(-1,-1) =='"'
|
|
if not is_cstring then
|
|
if v:match"::" then --could be nested enum
|
|
local enumname = v:gsub("[%w:]-::([%w]+)","%1")
|
|
local ok,val = pcall(cpp2ffi.parse_enum_value,enumname,enumsvalues)
|
|
if ok then
|
|
--print("parse_enum_value1",v,enumname,val,enumsvalues[enumname])
|
|
def.defaults[k] = val
|
|
else
|
|
print("deleting default ",v)
|
|
def.defaults[k] = nil
|
|
end
|
|
elseif enumsvalues[v] then
|
|
def.defaults[k] = enumsvalues[v]
|
|
elseif constants[v] then
|
|
def.defaults[k] = constants[v]
|
|
else
|
|
local ok,val = pcall(cpp2ffi.parse_enum_value,v,enumsvalues,true)
|
|
if ok then
|
|
--print("parse_enum_value2",v,val)
|
|
--if v~=val then print("sanitize",k,v,ok,val) end
|
|
def.defaults[k] = val
|
|
elseif def.defaults[k]:match"FLT_MAX" then
|
|
def.defaults[k] = def.defaults[k]:gsub("FLT_MAX","M.FLT_MAX")
|
|
elseif def.defaults[k]:match"FLT_MIN" then
|
|
def.defaults[k] = def.defaults[k]:gsub("FLT_MIN","M.FLT_MIN")
|
|
else
|
|
--numbers without f in the end
|
|
def.defaults[k] = v:gsub("([%d%.%-]+)[Ff]","%1")
|
|
--+ in front of numbers
|
|
def.defaults[k] = def.defaults[k]:gsub("^%+([%d%.%-]+)","%1")
|
|
|
|
def.defaults[k] = def.defaults[k]:gsub("ImDrawCornerFlags_All","lib.ImDrawCornerFlags_All")
|
|
def.defaults[k] = def.defaults[k]:gsub("sizeof%((%w+)%)",[[ffi.sizeof("%1")]])
|
|
def.defaults[k] = def.defaults[k]:gsub("%(%(void%s*%*%)0%)","nil")
|
|
def.defaults[k] = def.defaults[k]:gsub("NULL","nil")
|
|
def.defaults[k] = def.defaults[k]:gsub("nullptr","nil")
|
|
if def.defaults[k]:match"ImPlotSpec" then
|
|
def.defaults[k] = "M."..def.defaults[k].."[0]"
|
|
end
|
|
if def.defaults[k]:match"ImPlot3DSpec" then
|
|
def.defaults[k] = "M."..def.defaults[k].."[0]"
|
|
end
|
|
end
|
|
--if def.defaults[k]:match"~" then
|
|
-- def.defaults[k] = bit.bnot
|
|
--end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function ArgumentType(def,name)
|
|
for i,arg in ipairs(def.argsT) do
|
|
if arg.name == name then
|
|
return arg.type
|
|
end
|
|
end
|
|
end
|
|
|
|
local function make_function(method,def)
|
|
--if def.old_stname=="Language" then print("make_function",def.stname,def.cimguiname) end
|
|
if def.skipped then return "" end
|
|
if def.is_static_function then method = nil end
|
|
sanitize_reserved(def)
|
|
local fname = def.ov_cimguiname or def.cimguiname --overloaded or original
|
|
local fname_m = method and fname:match(def.stname.."_(.*)") or fname:match("^ig(.*)") or fname --drop struct name part
|
|
fname_m = fname_m:match("(.*)_nonUDT$") or fname_m --drop "_nonUDT" suffix
|
|
if fname_m == "end" then fname_m = "_end" end
|
|
--dump function code
|
|
if def.nonUDTno == 1 or next(def.defaults) then
|
|
local call_args_old = def.call_args_old:gsub("%*","")
|
|
local code = {}
|
|
local args, fname_lua
|
|
local empty = call_args_old:match("^%(%)") --no args
|
|
if method and not def.is_static_function then
|
|
args = call_args_old:gsub("^%(","(self"..(empty and "" or ","))
|
|
fname_lua = def.stname..":"..fname_m
|
|
empty = false
|
|
else
|
|
args = call_args_old
|
|
fname_lua = "M."..fname_m
|
|
end
|
|
table.insert(code,"function "..fname_lua..call_args_old)
|
|
--set defaults
|
|
cpp2ffi.table_do_sorted(def.defaults, function(k,v)
|
|
--for k,v in pairs(def.defaults) do
|
|
--special default treatment for ImStrv
|
|
if ArgumentType(def,k) == "ImStrv" then
|
|
--print("default for ImStrv",v)
|
|
if v:match"ImStrv()" then
|
|
table.insert(code," "..k.." = "..k.." or M.ImStrv()")
|
|
else
|
|
table.insert(code," "..k.." = "..k.." or M.ImStrv("..v..")")
|
|
end
|
|
else
|
|
if v == 'true' then
|
|
table.insert(code," if "..k.." == nil then "..k.." = "..v.." end")
|
|
--function for init struc ImPlotSpec
|
|
--elseif type(v)=="string" and v:match("%b()") and not v:match("^\"") and not v:match"sizeof" then
|
|
--elseif type(v)=="string" and v:match("%b()") and not v:match("^\"") and not v:match"sizeof" then
|
|
--print("default",v)
|
|
--table.insert(code," "..k.." = "..k.." or M."..v)
|
|
else
|
|
table.insert(code," "..k.." = "..k.." or "..v)
|
|
end
|
|
end
|
|
--end
|
|
end)
|
|
if def.nonUDTno == 1 then
|
|
--allocate variable for return value
|
|
local out_type = def.argsT[1].type:gsub("*", "")
|
|
table.insert(code,' local nonUDT_out = ffi.new("'..out_type..'")')
|
|
--prepend nonUDT_out to args
|
|
args = args:gsub("%(", "(nonUDT_out" .. (empty and "" or ","), 1)
|
|
--call cimgui and return value of out variable
|
|
table.insert(code," lib."..fname..args)
|
|
table.insert(code," return nonUDT_out")
|
|
else
|
|
--call cimgui
|
|
table.insert(code," return lib."..fname..args)
|
|
end
|
|
table.insert(code,"end")
|
|
return table.concat(code,"\n")
|
|
end
|
|
--for no nonUDTno and no defaults
|
|
return (method and def.stname or "M").."."..fname_m.." = lib."..fname
|
|
end
|
|
|
|
--struct constructor generator
|
|
local function constructor_gen(code,def)
|
|
sanitize_reserved(def)
|
|
--dump function code
|
|
if def.cimguiname == def.ov_cimguiname then --default constructor
|
|
local args = (def.call_args_old == "()") and "(ctype)" or "(ctype,"..def.call_args_old:sub(2)
|
|
table.insert(code,"function "..def.stname..".__new"..args)
|
|
else
|
|
local name = def.ov_cimguiname:match(def.stname.."_(.*)") --drop struct name part
|
|
table.insert(code,"function "..def.stname.."."..name..def.call_args_old)
|
|
end
|
|
--set defaults
|
|
cpp2ffi.table_do_sorted(def.defaults, function(k,v)
|
|
--for k,v in pairs(def.defaults) do
|
|
table.insert(code," if "..k.." == nil then "..k.." = "..v.." end")
|
|
--end
|
|
end)
|
|
local fname = def.ov_cimguiname or def.cimguiname
|
|
table.insert(code," local ptr = lib."..fname..def.call_args_old)
|
|
table.insert(code," return ffi.gc(ptr,lib."..def.stname.."_destroy)")
|
|
table.insert(code,"end")
|
|
end
|
|
|
|
--struct function generator
|
|
local function struct_function_gen(code,def)
|
|
table.insert(code,make_function(true,def))
|
|
end
|
|
|
|
--top level function generator (ImGui namespace)
|
|
local function function_gen(code,def)
|
|
table.insert(code,make_function(false,def))
|
|
end
|
|
|
|
local cdefs = dofile("./imgui/cdefs.lua")
|
|
ffi_cdef(cdefs)
|
|
|
|
--
|
|
|
|
-- test for pointers with unsigned-signed confusion and * vs []
|
|
local function GENp(typ,va)
|
|
local typ2 = typ:gsub("%*","[?]")
|
|
return "ffi.typeof('"..typ.."') == ffi.typeof("..va..") or ffi.typeof('const "..typ.."') == ffi.typeof("..va..") or ffi.typeof('"..typ2.."') == ffi.typeof("..va..") or ffi.typeof('const "..typ2.."') == ffi.typeof("..va..")"
|
|
end
|
|
--test against type or const type
|
|
local function CHK(typ,ti)
|
|
--print("CHK",typ,ti)
|
|
return ffi.typeof(typ) == ffi.typeof(ti) or ffi.typeof(typ) == ffi.typeof("const "..ti)
|
|
end
|
|
|
|
--not confused by ffi.istype
|
|
local types = {"void *","int8_t","uint8_t","int16_t","uint16_t","int32_t","uint32_t","int64_t","uint64_t","float","double","bool"}
|
|
local function CHK_types(typ,va)
|
|
for i=1,#types do
|
|
if CHK(typ,types[i]) then
|
|
local typ1 = types[i]
|
|
if typ1=="void *" then
|
|
return "ffi.istype('"..typ1.."',"..va..")"
|
|
elseif typ1== "bool" then
|
|
return "(ffi.istype('"..typ1.."',"..va..") or type("..va..")=='boolean')"
|
|
else -- let it be a number
|
|
return "(ffi.istype('"..typ1.."',"..va..") or type("..va..")=='number')"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--signed unsigned confusion of ffi.istype with pointers
|
|
local UStypes = {"int8_t*","uint8_t*","int16_t*","uint16_t*","int32_t*","uint32_t*","int64_t*","uint64_t*"}
|
|
local function CHK_types_p(typ,va)
|
|
for i=1,#UStypes do
|
|
if CHK(typ,UStypes[i]) then
|
|
return GENp(UStypes[i],va)
|
|
end
|
|
end
|
|
end
|
|
|
|
--not signed unsigned confusion of ffi.istype with pointers
|
|
local Ptypes = {"float*","double*","bool*"}
|
|
local function CHK_types_p2(typ,va)
|
|
for i=1,#Ptypes do
|
|
if CHK(typ,Ptypes[i]) then
|
|
local typ1 = Ptypes[i]
|
|
local typ2 = typ1:gsub("%*","[]")
|
|
return "(ffi.istype('"..typ1.."',"..va..") or ffi.istype('"..typ2.."',"..va.."))"
|
|
end
|
|
end
|
|
end
|
|
|
|
local badtypes = {}
|
|
local function checktype(typ,va,fname)
|
|
--if enumnames[typ] then print("==============",typ) end
|
|
local cond = CHK_types(typ,va)
|
|
if cond then return cond end
|
|
|
|
if ffi.typeof(typ)==ffi.typeof"const char*" then
|
|
return "(ffi.istype('"..typ.."',"..va..") or ffi.istype('char[]',"..va..") or type("..va..")=='string')"
|
|
end
|
|
|
|
cond = CHK_types_p(typ,va)
|
|
if cond then return cond end
|
|
|
|
cond = CHK_types_p2(typ,va)
|
|
if cond then return cond end
|
|
|
|
if not tostring(ffi.typeof(typ)):find"struct" then
|
|
badtypes[typ] = fname or true
|
|
end
|
|
if typ:match"%*" and not typ:match"%(%*%)" then --pointer not function pointer
|
|
local typsinptr = typ:gsub("(%*)","")
|
|
local extra = " or ffi.istype('"..typsinptr.."',"..va..")"
|
|
local extra2 = " or ffi.istype('"..typsinptr.."[]',"..va..")"
|
|
return "(ffi.istype('"..typ.."',"..va..")"..extra..extra2..")"
|
|
end
|
|
return "ffi.istype('"..typ.."',"..va..")"
|
|
|
|
end
|
|
|
|
local function gen_args(method,def,minvararg)
|
|
local n = #def.argsT
|
|
local args = ""
|
|
local isvararg
|
|
if minvararg < math.huge and n >= minvararg then
|
|
n = minvararg - 1
|
|
isvararg = true
|
|
end
|
|
local ini = 1
|
|
if method then ini = ini + 1 end
|
|
if def.nonUDTno then ini = ini + 1 end
|
|
for i=ini,n do
|
|
args = args.."a"..i..","
|
|
end
|
|
if isvararg then
|
|
args = args .. "...,"
|
|
end
|
|
args = args:sub(1,-2) --drop last
|
|
return args
|
|
end
|
|
|
|
--require"anima.utils" --gives us prtable
|
|
local function create_generic(code,defs,method)
|
|
if defs[1].skipped then return end
|
|
if defs[1].is_static_function then
|
|
method = nil
|
|
end
|
|
|
|
if defs[1].nonUDTno then print("create_generic nonUTD",defs[1].cimguiname) end
|
|
|
|
local methodnotconst = method and not defs[1].constructor
|
|
--find max number of arguments
|
|
local maxnargs = -1
|
|
local minvararg = math.huge
|
|
local is_vararg
|
|
for i,def in ipairs(defs) do
|
|
if #def.argsT> 0 and def.argsT[#def.argsT].type == "..." then
|
|
minvararg = minvararg > #def.argsT and #def.argsT or minvararg
|
|
--print("...",def.cimguiname,#def.argsT)
|
|
end
|
|
maxnargs = maxnargs < #def.argsT and #def.argsT or maxnargs
|
|
end
|
|
is_vararg = minvararg < math.huge
|
|
--if is_vararg then print("maxnargs",defs[1].cimguiname,maxnargs,minvararg) end
|
|
--[[
|
|
for i,def in ipairs(defs) do
|
|
io.write(def.ov_cimguiname," , ")
|
|
end
|
|
print()
|
|
for i=1,maxnargs do
|
|
io.write(i," ")
|
|
for j,def in ipairs(defs) do
|
|
io.write(def.argsT[i] and def.argsT[i].type or "nil")
|
|
io.write", "
|
|
end
|
|
print()
|
|
end
|
|
--]]
|
|
--if methodnotconst and defs[1].nonUDTno then print("zzzzz",defs[1].cimguiname) end
|
|
--find first different arg
|
|
local keys = {}
|
|
local done = {}
|
|
local check = {}
|
|
local maxnargs2 = is_vararg and minvararg-1 or maxnargs
|
|
local ini_i= methodnotconst and 2 or 1
|
|
ini_i= defs[1].nonUDTno and ini_i + 1 or ini_i
|
|
for i=ini_i,maxnargs2 do
|
|
keys[i] = {}
|
|
for j=1,#defs do
|
|
if not done[j] then
|
|
local tt = defs[j].argsT[i] and defs[j].argsT[i].type or "nil"
|
|
--keys[i][tt] = (keys[i][tt] or 0) + 1
|
|
keys[i][tt] = keys[i][tt] or {}
|
|
table.insert(keys[i][tt],j)
|
|
end
|
|
end
|
|
local keycount = 0
|
|
for k,v in pairs(keys[i]) do keycount = keycount + 1 end
|
|
--print("keycount",i,keycount,#defs)
|
|
for j=1,#defs do
|
|
if not done[j] then
|
|
local tt = defs[j].argsT[i] and defs[j].argsT[i].type or "nil"
|
|
if keycount > 1 then -- if more than one posible type then keep check
|
|
check[j] = check[j] or {}
|
|
check[j][i]=tt
|
|
end
|
|
if #keys[i][tt] == 1 then -- if one type is exclusive of one overload we are done
|
|
done[j]= true;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--for j=1,#defs do if not done[j] then print("not done",defs[1].cimguiname) end end
|
|
--[[
|
|
--for decision tree
|
|
local ordered_check = {}
|
|
for i=1,#check do
|
|
ordered_check[i] = {}
|
|
for k,v in pairs(check[i]) do
|
|
table.insert(ordered_check[i],{k,v})
|
|
end
|
|
table.sort(ordered_check[i],function(a,b) return a[1] < b[1] end)
|
|
end
|
|
local Tree = {}
|
|
|
|
|
|
--if is_vararg then cpp2ffi.prtable(keys,done,check) end
|
|
if defs[1].cimguiname == "igImLerp" then cpp2ffi.prtable(defs,keys,done,check, ordered_check) end
|
|
--]]
|
|
--if defs[1].cimguiname == "ImPlot_PlotLine" then cpp2ffi.prtable(defs,keys,done,check) end
|
|
--for decision tree by variable
|
|
|
|
--do generic--------------
|
|
local code2 = {}
|
|
--create args
|
|
if is_vararg then maxnargs = minvararg-1 end
|
|
local args = "" --method and "self," or ""
|
|
if methodnotconst then
|
|
if defs[1].nonUDTno then
|
|
for i=3,maxnargs do
|
|
args = args.."a"..i..","
|
|
end
|
|
else
|
|
for i=2,maxnargs do
|
|
args = args.."a"..i..","
|
|
end
|
|
end
|
|
elseif method then --constructor
|
|
args = maxnargs==0 and "ctype" or "ctype,"
|
|
for i=1,maxnargs do args = args.."a"..i.."," end
|
|
else
|
|
if defs[1].nonUDTno then
|
|
--print("mmmm",defs[1].cimguiname)
|
|
for i=2,maxnargs do
|
|
args = args.."a"..i..","
|
|
end
|
|
else
|
|
for i=1,maxnargs do
|
|
args = args.."a"..i..","
|
|
end
|
|
end
|
|
end
|
|
if is_vararg then args = args.."...," end
|
|
args = args:sub(1,-2) --drop last ,
|
|
|
|
local fname = defs[1].cimguiname
|
|
local fname_e = method and fname:match(defs[1].stname.."_(.*)") or fname:match("^ig(.*)") or fname--drop struct name part
|
|
fname = method and (methodnotconst and defs[1].stname..":"..fname_e or defs[1].stname..".__new") or "M."..fname_e
|
|
|
|
table.insert(code2, "function "..fname.."("..args..") -- generic version")
|
|
---------float and int check
|
|
--require"anima.utils"
|
|
--prtable(check)
|
|
for j=1,maxnargs do
|
|
local isint,isfloat
|
|
for i=1,#check do
|
|
local chk = check[i]
|
|
if chk and chk[j] then
|
|
if chk[j] == "int" then isint = defs[i].ov_cimguiname end
|
|
if chk[j]:match"Im[SU]+%d+$" then isint = defs[i].ov_cimguiname end
|
|
if chk[j] == "float" then isfloat = defs[i].ov_cimguiname end
|
|
if chk[j] == "double" then isfloat = defs[i].ov_cimguiname end
|
|
local ok,res = pcall(ffi.typeof,chk[j])
|
|
if ok then
|
|
if tostring(res):match("<enum") then isint = defs[i].ov_cimguiname; end
|
|
end
|
|
end
|
|
end
|
|
if isint and isfloat then
|
|
print("----------",fname,"int-float in arg",j)
|
|
print(isint,isfloat)
|
|
end
|
|
end
|
|
-------------------------------------------
|
|
for i=1,#check do
|
|
local chk = check[i]
|
|
table.insert(code2,"\n if ")
|
|
local addand = false
|
|
for k,v in pairs(chk) do
|
|
assert(k < minvararg, fname)
|
|
if addand then table.insert(code2," and ") end
|
|
if v=="nil" then
|
|
table.insert(code2,"a"..k.."==nil")
|
|
else
|
|
---------------------which function is using this overloading type
|
|
-- if v:find"short" and not v:find"%*" then
|
|
-- print("short",defs[1].cimguiname)
|
|
-- end
|
|
-----------------
|
|
local strcode = checktype(v,"a"..k,fname)
|
|
--if has a default take nil as valid check
|
|
--print("defs[i].defaults[k]",defs[i].ov_cimguiname,defs[i].defaults[defs[i].argsT[k].name])
|
|
|
|
if defs[i].defaults[defs[i].argsT[k].name]~=nil then
|
|
--if defs[i].argsT[k].type~="ImStrv" then
|
|
--print("---overload with default",defs[i].ov_cimguiname)
|
|
strcode = "("..strcode.." or type(a"..k..")=='nil')"
|
|
--end
|
|
end
|
|
--if type enum accept number
|
|
if enumnames[v] then
|
|
strcode = "("..strcode.." or type(a"..k..")=='number')"
|
|
end
|
|
table.insert(code2 , strcode)
|
|
---table.insert(code2,"ffi.istype('"..v.."',a"..k..")")
|
|
end
|
|
addand = true
|
|
end
|
|
local fname2 = defs[i].ov_cimguiname
|
|
local fname2_e = method and fname2:match(defs[1].stname.."_(.*)") or fname2:match("^ig(.*)") or fname2 --drop struct name part
|
|
fname2 = method and (methodnotconst and "self:"..fname2_e or defs[1].stname.."."..fname2_e) or "M."..fname2_e
|
|
table.insert(code2," then return "..fname2.."("..gen_args(methodnotconst,defs[i],minvararg)..") end")
|
|
if fname_e == fname2_e then
|
|
print("--------error cimguiname equals ov_cimguiname in overloaded function",fname)
|
|
--error"cimguiname equals ov_cimguiname"
|
|
end
|
|
end
|
|
table.insert(code2,"\n print("..args..")")
|
|
table.insert(code2,"\n error'"..fname.." could not find overloaded'\nend")
|
|
table.insert(code, table.concat(code2))
|
|
end
|
|
|
|
--struct code generator
|
|
local function code_for_struct(st,fundefs,structs)
|
|
local funs = structs[st]
|
|
table.sort(funs)
|
|
local code = {}
|
|
table.insert(code,"--------------------------"..st.."----------------------------")
|
|
--declare struct
|
|
table.insert(code,"local "..st.."= {}")
|
|
table.insert(code,st..".__index = "..st)
|
|
for _,f in ipairs(funs) do
|
|
local defs = fundefs[f]
|
|
for _,def in ipairs(defs) do
|
|
if not def.destructor then
|
|
if def.constructor then
|
|
constructor_gen(code,def)
|
|
else
|
|
struct_function_gen(code,def)
|
|
end
|
|
end
|
|
end
|
|
if #defs > 1 then
|
|
create_generic(code,defs,true)
|
|
end
|
|
end
|
|
local st2 = opaque_structs[st] and st.."_opq" or st
|
|
table.insert(code,[[M.]]..st..[[ = ffi.metatype("]]..st2..[[",]]..st..")")
|
|
local codestr = table.concat(code,"\n")
|
|
--test correctness of code
|
|
testcode(codestr)
|
|
return codestr
|
|
end
|
|
local FREETYPE = false
|
|
--ImGui namespace generator
|
|
local function code_for_imguifuns(st,fundefs,structs)
|
|
local funs = structs[st]
|
|
table.sort(funs)
|
|
local code = {}
|
|
table.insert(code,"--------------------------"..st.."----------------------------")
|
|
for _,f in ipairs(funs) do
|
|
local defs = fundefs[f]
|
|
for _,def in ipairs(defs) do
|
|
-- error"debug"
|
|
-- if def.cimguiname:match"Language_C" then error"debug" end
|
|
-- if def.ov_cimguiname:match"Language_C" then error"debug" end
|
|
--print("fun",def.cimguiname, def.ov_cimguiname)
|
|
--if st=="Language" then print(st,def.cimguiname) end
|
|
--can be an opaque_struct static function
|
|
if (not opaque_structs[st]) or def.is_static_function then
|
|
--if st=="Language" then print(st,def.cimguiname,def.location) end
|
|
if FREETYPE or (not def.location:match"imgui_freetype") then
|
|
def.old_stname = def.stname
|
|
def.stname = "M"
|
|
function_gen(code,def)
|
|
end
|
|
end
|
|
end
|
|
--if has overloading create the generic
|
|
if #defs > 1 then
|
|
create_generic(code, defs)
|
|
end
|
|
end
|
|
local codestr = table.concat(code,"\n")
|
|
--test correctness of code
|
|
testcode(codestr)
|
|
return codestr
|
|
end
|
|
|
|
local function make_enums(sources)
|
|
for i,v in ipairs(sources) do
|
|
local standenu = dofile([[../]]..v..[[/generator/output/structs_and_enums.lua]])
|
|
--first enums
|
|
for k,enu in pairs(standenu.enums) do
|
|
enumnames[k]=true
|
|
for i,v in ipairs(enu) do
|
|
assert(v.calc_value)
|
|
enumsvalues[v.name] = v.calc_value
|
|
end
|
|
end
|
|
--now opaque_structs
|
|
assert(standenu.opaque_structs,v)
|
|
for k,opq in pairs(standenu.opaque_structs) do
|
|
opaque_structs[k] = opq
|
|
end
|
|
--now constants
|
|
local ok,const = pcall(dofile,[[../]]..v..[[/generator/output/constants.lua]])
|
|
--print("const",v,ok,const)
|
|
if ok then
|
|
for key,val in pairs(const) do
|
|
if val:match"%b()" then val = "M."..val end
|
|
constants[key] = val
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function make_funcdefs(sources)
|
|
local count = 0
|
|
local gen_count = 0
|
|
local fundefs = {}
|
|
for i,v in ipairs(sources) do
|
|
local fundefs1 = dofile([[../]]..v..[[/generator/output/definitions.lua]])
|
|
for fun,defs in pairs(fundefs1) do
|
|
--print("make_funcdefs",fun,#defs)
|
|
gen_count = gen_count + 1
|
|
count = count + #defs
|
|
fundefs[fun] = defs
|
|
end
|
|
end
|
|
print("---number of funcs",count,"generic count",gen_count)
|
|
return fundefs
|
|
end
|
|
--------------------------------------------------------------
|
|
|
|
local function class_gen(sources, ft_gen)
|
|
FREETYPE = ft_gen
|
|
--firs get enumsvalues table
|
|
make_enums(sources)
|
|
local fundefs = make_funcdefs(sources)
|
|
--group them by structs
|
|
local structs = {}
|
|
local skipped = {}
|
|
for fun,defs in pairs(fundefs) do
|
|
local stname = defs[1].stname
|
|
if not defs[1].templated then
|
|
structs[stname] = structs[stname] or {}
|
|
table.insert(structs[stname],fun)
|
|
else
|
|
skipped[stname] = true
|
|
end
|
|
end
|
|
print"---skipped templated structs"
|
|
for k,_ in pairs(skipped) do
|
|
print(k)
|
|
end
|
|
--delete templated
|
|
structs.ImVec4 = nil
|
|
structs.ImVector = nil
|
|
structs.ImChunkStream = nil
|
|
structs.ImPool = nil
|
|
---------------------------------------------------------------
|
|
local strout = {}
|
|
--Do generation
|
|
table.insert(strout,"----------BEGIN_AUTOGENERATED_LUA---------------------------")
|
|
cpp2ffi.table_do_sorted(structs, function(struct,funs)
|
|
if struct ~= "ImGui" and struct ~= "ImVec2" and struct ~= "ImStrv" and struct ~= "" then
|
|
if not opaque_structs[struct] then
|
|
table.insert(strout,code_for_struct(struct,fundefs, structs))
|
|
else
|
|
table.insert(strout,code_for_imguifuns(struct,fundefs, structs))
|
|
end
|
|
end
|
|
end)
|
|
|
|
table.insert(strout,code_for_imguifuns("",fundefs, structs))--("ImGui"))
|
|
|
|
------------------------------------
|
|
print"----------------------------"
|
|
for k,v in pairs(badtypes) do
|
|
print("badtype",k,ffi.typeof(k),v)
|
|
end
|
|
print"----------------------------"
|
|
------------------------------------
|
|
table.insert(strout,"-- _LJ versions")
|
|
local funs = structs[""]
|
|
table.sort(funs)
|
|
for _,k in ipairs(funs) do
|
|
local defs = fundefs[k]
|
|
if #defs == 1 and k:match("_LJ$") then
|
|
table.insert(strout,"M."..k:gsub("_LJ$","").." = M."..k)
|
|
end
|
|
end
|
|
-- for k,defs in pairs(fundefs) do
|
|
-- if #defs == 1 and k:match("_LJ$") then
|
|
-- table.insert(strout,"M."..k:gsub("_LJ$","").." = M."..k)
|
|
-- end
|
|
-- end
|
|
------------------------------
|
|
table.insert(strout,"return M")
|
|
table.insert(strout,"----------END_AUTOGENERATED_LUA-----------------------------")
|
|
return table.concat(strout,"\n")
|
|
end
|
|
|
|
return class_gen
|
|
|