local insert = table.insert local function ToStr(t,dometatables) local function basicToStr (o) if type(o) == "number" or type(o)=="boolean" then return tostring(o) elseif type(o) == "string" then return string.format("%q", o) else return tostring(o) --"nil" end end local strTG = {} --local basicToStr= basicSerialize --tostring if type(t) ~="table" then return basicToStr(t) end local recG = 0 local nameG="SELF"..recG local ancest ={} local function _ToStr(t,strT,rec,name) if ancest[t] then strT[#strT + 1]=ancest[t] return end rec = rec + 1 ancest[t]=name strT[#strT + 1]='{' local count=0 ------------- --if t.name then strT[#strT + 1]=string.rep("\t",rec).."name:"..tostring(t.name) end ---------------- for k,v in pairs(t) do count=count+1 strT[#strT + 1]="\n" local kstr if type(k) == "table" then local name2=string.format("%s.KEY%d",name,count) strT[#strT + 1]=string.rep("\t",rec).."[" local strTK = {} _ToStr(k,strTK,rec,name2) kstr=table.concat(strTK) strT[#strT + 1]=kstr.."]=" else kstr = basicToStr(k) strT[#strT + 1]=string.rep("\t",rec).."["..kstr.."]=" end if type(v) == "table" then local name2=string.format("%s[%s]",name,kstr) _ToStr(v,strT,rec,name2) else strT[#strT + 1]=basicToStr(v) end end if dometatables then local mt = getmetatable(t) if mt then local namemt = string.format("%s.METATABLE",name) local strMT = {} _ToStr(mt,strMT,rec,namemt) local metastr=table.concat(strMT) strT[#strT + 1] = "\n"..string.rep("\t",rec).."[METATABLE]="..metastr end end strT[#strT + 1]='}' rec = rec - 1 return end _ToStr(t,strTG,recG,nameG) return table.concat(strTG) end local function prtable(...) for i=1, select('#', ...) do local t = select(i, ...) print(ToStr(t)) print("\n") end end -- more compact serialization local function basicSerialize (o) if type(o) == "number" then return string.format("%.17g", o) elseif type(o)=="boolean" then return tostring(o) elseif type(o) == "string" then return string.format("%q", o) elseif pcall(function() return o.__serialize end) then return o.__serialize(o) elseif type(o)=="cdata" then return cdataSerialize(o) else return tostring(o) --"nil" end end -- very readable and now suited for cyclic tables local kw = {['and'] = true, ['break'] = true, ['do'] = true, ['else'] = true, ['elseif'] = true, ['end'] = true, ['false'] = true, ['for'] = true, ['function'] = true, ['goto'] = true, ['if'] = true, ['in'] = true, ['local'] = true, ['nil'] = true, ['not'] = true, ['or'] = true, ['repeat'] = true, ['return'] = true, ['then'] = true, ['true'] = true, ['until'] = true, ['while'] = true} function tb2st_serialize(t,options) options = options or {} local function sorter(a,b) if type(a)==type(b) then return a 1 do i = i - 1 local c = string.sub(params,i,i) if c == "," then return string.sub(params, 1, i-1) .. params:sub(j+1) elseif c == "(" then return string.sub(params, 1, i) .. params:sub(j+1) end end error("paramListWithoutDots failed") return "()" end -------------------------------json saving --avoid mixed tables (with string and integer keys) local function json_prepare(defs) --delete signatures in function for k,def in pairs(defs) do for k2,v in pairs(def) do if type(k2)=="string" then def[k2] = nil end end end return defs end local function save_output(self) --add VARGS0 local defsVARG = {} for k,defs in pairs(self.defsT) do for i, def in ipairs(defs) do if def.isvararg then --print("vararg",k,#def) local def1 = deepcopy(def) def1.isvararg = nil def1.isVARG0 = true def1.argsT[#def1.argsT] = nil def1.args = paramListWithoutDots(def1.args) def1.call_args = paramListWithoutDots(def1.call_args) def1.call_args_conv = paramListWithoutDots(def1.call_args_conv) def1.signature = paramListWithoutDots(def1.signature) def1.cimguiname = def1.cimguiname.."0" def1.ov_cimguiname = def1.ov_cimguiname.."0" defsVARG[k.."0"] = defsVARG[k.."0"] or {} table.insert(defsVARG[k.."0"], def1) end end end for k,def in pairs(defsVARG) do self.defsT[k] = def end --add manual not present in module for k,v in pairs(self.manuals) do if not self.defsT[k] then --print("add manual",k) self.defsT[k] = {v} else --print("skipped manual",k) end end ---------- delete call_args_conv -- for k,defs in pairs(self.defsT) do -- for i, def in ipairs(defs) do -- def.call_args_conv = nil -- end -- end ---------------------- save_data("./output/overloads.txt",self.overloadstxt) save_data("./output/definitions.lua",serializeTableF(self.defsT)) save_data("./output/structs_and_enums.lua",serializeTableF(self.structs_and_enums_table)) save_data("./output/typedefs_dict.lua",serializeTableF(self.typedefs_dict)) save_data("./output/constants.lua",serializeTableF(self.constants)) local json = require"json" local json_opts = {dict_on_empty={defaults=true}} save_data("./output/definitions.json",json.encode(json_prepare(self.defsT),json_opts)) save_data("./output/structs_and_enums.json",json.encode(self.structs_and_enums_table)) save_data("./output/typedefs_dict.json",json.encode(self.typedefs_dict)) save_data("./output/constants.json",json.encode(self.constants)) local modulename = self.modulename copyfile("./output/"..modulename..".h", "../"..modulename..".h") copyfile("./output/"..modulename..".cpp", "../"..modulename..".cpp") os.remove("./output/"..modulename..".h") os.remove("./output/"..modulename..".cpp") end ---------------------- C writing functions local function func_header_generate_structs(FP) local outtab = {}--"\n/////func_header_generate_structs\n"} prtable("embeded_structs",FP.embeded_structs) table_do_sorted(FP.embeded_structs,function(k,v) if not FP.typenames[k] then print("embeded",k,v) table.insert(outtab,"typedef "..v.." "..k..";\n") end end) table_do_sorted(FP.embeded_enums,function(k,v) table.insert(outtab,"typedef "..v.." "..k..";\n") end) --table.insert(outtab, "\n//////////templates\n") table_do_sorted(FP.templates,function(ttype,v) --print("func_header_generate_structs",ttype) if not (ttype == "std::function") then table_do_sorted(v,function(ttypein,te) local ttype2 = ttype:gsub("::","_") --std::string table.insert(outtab,"typedef "..ttype.."<"..ttypein.."> "..ttype2.."_"..te..";\n") end) end end) --M.prtable("typenames",FP.typenames) table_do_sorted(FP.opaque_structs,function(k,v) if not FP.typenames[k] then table.insert(outtab,"typedef "..v.." "..k..";\n") --table.insert(outtab,"typedef const "..v.."* "..k.."_opq;\n") --table.insert(outtab,"typedef "..v.."* "..k.."_opq;\n") end end) --table.insert(outtab, "\n//////////end func header\n") return outtab end local function func_header_generate_funcs(FP) local outtab = {} for _,t in ipairs(FP.funcdefs) do if t.cimguiname then local cimf = FP.defsT[t.cimguiname] local def = cimf[t.signature] assert(def,t.signature..t.cimguiname) local custom if FP.custom_header then custom = FP.custom_header(outtab, def) end local manual = FP.get_manuals(def) if not custom and not manual and not def.templated and not FP.get_skipped(def) --and not (FP.opaque_structs[def.stname] and not def.is_static_function) then local addcoment = "" --def.comment or "" local empty = def.args:match("^%(%)") --no args if def.constructor then assert(def.stname ~= "","constructor without struct") table.insert(outtab,"CIMGUI_API "..def.stname.."* "..def.ov_cimguiname ..(empty and "(void)" or def.args)..";"..addcoment.."\n") if FP.CONSTRUCTORS_GENERATION then outtab[#outtab] = outtab[#outtab].."\nCIMGUI_API void "..def.ov_cimguiname.."_Construct("..def.stname.."* self"..(empty and "" or ","..def.args:sub(2,-2))..");\n" end elseif def.destructor then table.insert(outtab,"CIMGUI_API void "..def.ov_cimguiname..def.args..";"..addcoment.."\n") else --not constructor --local ret = FP.nP_ret[def.ret] or def.ret local ret = def.ret if def.stname == "" or def.is_static_function then --ImGui namespace or top level table.insert(outtab,"CIMGUI_API "..ret.." ".. def.ov_cimguiname ..(empty and "(void)" or def.args)..";"..addcoment.."\n") if def.isvararg then -- For variadic functions we add a function implementation with zero argumets, for compatibility with languages such as C#. table.insert(outtab, "#ifdef CIMGUI_VARGS0\n") table.insert(outtab, "CIMGUI_API".." "..ret.." "..def.ov_cimguiname.."0"..paramListWithoutDots(def.args)..";\n") table.insert(outtab, "#endif\n") end else table.insert(outtab,"CIMGUI_API "..ret.." "..def.ov_cimguiname..def.args..";"..addcoment.."\n") if def.isvararg then -- For variadic functions we add a function implementation with zero argumets, for compatibility with languages such as C#. table.insert(outtab, "#ifdef CIMGUI_VARGS0\n") table.insert(outtab, "CIMGUI_API".." "..ret.." "..def.ov_cimguiname.."0"..paramListWithoutDots(def.args)..";\n") table.insert(outtab, "#endif\n") end end end end if FP.custom_function_post then FP:custom_function_post(outtab, def) end else --not cimguiname table.insert(outtab,t.comment:gsub("%%","%%%%").."\n")-- %% substitution for gsub end end return outtab end local function func_header_generate(FP) local outtab = func_header_generate_structs(FP) table.insert(outtab, 1, "\n#ifndef CIMGUI_DEFINE_ENUMS_AND_STRUCTS\n") table.insert(outtab,"#endif //CIMGUI_DEFINE_ENUMS_AND_STRUCTS\n") local outtabf = func_header_generate_funcs(FP) outtabf = table.concat(outtabf) assert(type(outtabf)=="string") --outtabf = M.header_subs_nonPOD(FP,outtabf) local cfuncsstr = table.concat(outtab)..outtabf cfuncsstr = cfuncsstr:gsub("\n+","\n") --several empty lines to one empty line return cfuncsstr end local function ImGui_f_implementation(def) local outtab = {} local ptret = def.retref and "&" or "" table.insert(outtab,"CIMGUI_API".." "..def.ret.." "..def.ov_cimguiname..def.args.."\n") table.insert(outtab,"{\n") local namespace = def.namespace and def.namespace.."::" or "" --namespace = def.is_static_function and namespace..def.stname.."::" or namespace local call_args_conv = def.call_args_conv or def.call_args if def.isvararg then local call_args_conv = call_args_conv:gsub("%.%.%.","args") table.insert(outtab," va_list args;\n") table.insert(outtab," va_start(args, fmt);\n") if def.ret~="void" then table.insert(outtab," "..def.ret.." ret = "..namespace..def.funcname.."V"..call_args_conv..";\n") else table.insert(outtab," "..namespace..def.funcname.."V"..call_args_conv..";\n") end table.insert(outtab," va_end(args);\n") if def.ret~="void" then table.insert(outtab," return ret;\n") end table.insert(outtab,"}\n") -- For variadic functions we add a function implementation with zero argumets, for compatibility with languages such as C#. table.insert(outtab, "#ifdef CIMGUI_VARGS0\n") table.insert(outtab, "CIMGUI_API".." "..def.ret.." "..def.ov_cimguiname.."0"..paramListWithoutDots(def.args).."\n") table.insert(outtab, "{\n") local returnword = "return " if def.ret=="void" then returnword = "" end table.insert(outtab, " "..returnword..def.ov_cimguiname..paramListWithoutDots(def.call_args)..";\n") table.insert(outtab, "}\n") table.insert(outtab, "#endif\n") elseif def.nonUDT then if def.nonUDT == 1 then insert(outtab," return ConvertFromCPP_"..def.conv.."("..namespace..def.funcname..call_args_conv..");\n") elseif def.nonUDT == 2 then insert(outtab," return reinterpret_cast<"..def.ret..">("..ptret..namespace..def.funcname..call_args_conv..");\n") elseif def.nonUDT == "string" then insert(outtab," static std::string str;\n") insert(outtab," str.assign("..ptret.."self->"..def.funcname..call_args_conv..");\n") insert(outtab," return str.c_str();\n") elseif def.nonUDT == "opaque" then insert(outtab," static auto opq = "..ptret..namespace..def.funcname..call_args_conv..";\n") insert(outtab," opq = "..ptret..namespace..def.funcname..call_args_conv..";\n") insert(outtab," return &opq;\n") end table.insert(outtab,"}\n") else --standard ImGui table.insert(outtab," return "..ptret..namespace..def.funcname..call_args_conv..";\n") table.insert(outtab,"}\n") end --table.insert(outtab,"}\n") return table.concat(outtab, "") end local function struct_f_implementation(def) local outtab = {} local empty = def.args:match("^%(%)") --no args local ptret = def.retref and "&" or "" local imgui_stname = def.stname table.insert(outtab,"CIMGUI_API".." "..def.ret.." "..def.ov_cimguiname..def.args.."\n") table.insert(outtab,"{\n") local call_args_conv = def.call_args_conv or def.call_args if def.isvararg then local call_args_conv = call_args_conv:gsub("%.%.%.","args") table.insert(outtab," va_list args;\n") table.insert(outtab," va_start(args, fmt);\n") if def.ret~="void" then table.insert(outtab," "..def.ret.." ret = self->"..def.funcname.."V"..call_args_conv..";\n") else table.insert(outtab," self->"..def.funcname.."V"..call_args_conv..";\n") end table.insert(outtab," va_end(args);\n") if def.ret~="void" then table.insert(outtab," return ret;\n") end table.insert(outtab,"}\n") -- For variadic functions we add a function implementation with zero argumets, for compatibility with languages such as C#. table.insert(outtab, "#ifdef CIMGUI_VARGS0\n") table.insert(outtab, "CIMGUI_API".." "..def.ret.." "..def.ov_cimguiname.."0"..paramListWithoutDots(def.args).."\n") table.insert(outtab, "{\n") local returnword = "return " if def.ret=="void" then returnword = "" end table.insert(outtab, " "..returnword..def.ov_cimguiname.."(self,"..paramListWithoutDots(def.call_args):sub(2,-1)..";\n") table.insert(outtab, "}\n") table.insert(outtab, "#endif\n") elseif def.nonUDT then if def.nonUDT == 1 then insert(outtab," return ConvertFromCPP_"..def.conv.."(self->"..def.funcname..call_args_conv..");\n") elseif def.nonUDT == 2 then insert(outtab," return reinterpret_cast<"..def.ret..">("..ptret.."self->"..def.funcname..call_args_conv..");\n") elseif def.nonUDT == "string" then insert(outtab," static std::string str;\n") insert(outtab," str.assign("..ptret.."self->"..def.funcname..call_args_conv..");\n") insert(outtab," return str.c_str();\n") elseif def.nonUDT == "opaque" then insert(outtab," static auto opq = "..ptret.."self->"..def.funcname..call_args_conv..";\n") insert(outtab," opq = "..ptret.."self->"..def.funcname..call_args_conv..";\n") insert(outtab," return &opq;\n") end table.insert(outtab,"}\n") else --standard struct table.insert(outtab," return "..ptret.."self->"..def.funcname..call_args_conv..";\n") table.insert(outtab,"}\n") end return table.concat(outtab, "") end local function func_implementation(FP) local outtab = {} for _,t in ipairs(FP.funcdefs) do repeat -- continue simulation if not t.cimguiname then break end local cimf = FP.defsT[t.cimguiname] local def = cimf[t.signature] assert(def) local custom if FP.custom_implementation then custom = FP.custom_implementation(outtab, def, FP) end local manual = FP.get_manuals(def) if not custom and not manual and not def.templated and not FP.get_skipped(def) --and not (FP.opaque_structs[def.stname] and not def.is_static_function) then local call_args_conv = def.call_args_conv or def.call_args if def.constructor then local tab = {} assert(def.stname ~= "","constructor without struct") local empty = def.args:match("^%(%)") --no args table.insert(tab,"CIMGUI_API "..def.stname.."* "..def.ov_cimguiname..(empty and "(void)" or def.args).."\n") table.insert(tab,"{\n") table.insert(tab," return IM_NEW("..def.stname..")"..call_args_conv..";\n") table.insert(tab,"}\n") if FP.CONSTRUCTORS_GENERATION then table.insert(tab,"CIMGUI_API void "..def.ov_cimguiname.."_Construct("..def.stname.."* self"..(empty and "" or ","..def.args:sub(2,-2))..")\n") table.insert(tab,"{\n") table.insert(tab," IM_PLACEMENT_NEW(self)"..def.stname..call_args_conv..";\n") table.insert(tab,"}\n") end table.insert(outtab, table.concat(tab, "")) elseif def.destructor then local tab = {} local args = "("..def.stname.."* self)" local fname = def.stname.."_destroy" table.insert(tab,"CIMGUI_API void "..fname..args.."\n") table.insert(tab,"{\n") table.insert(tab," IM_DELETE(self);\n") table.insert(tab,"}\n") table.insert(outtab, table.concat(tab, "")) elseif def.stname == "" or def.is_static_function then table.insert(outtab, ImGui_f_implementation(def)) else -- stname table.insert(outtab, struct_f_implementation(def)) end end if FP.custom_function_post then FP:custom_function_post(outtab, def) end until true end local conversors = FP:genConversors() local cimplem = conversors .. table.concat(outtab) return cimplem end return {func_implementation = func_implementation, save_output = save_output, save_data = save_data, read_data = read_data, copyfile = copyfile, func_header_generate = func_header_generate, prtable = prtable, table_do_sorted = table_do_sorted, save_output = save_output, deepcopy = deepcopy, serializeTableF = serializeTableF, func_header_generate_structs = func_header_generate_structs}