mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-06-08 03:13:52 +00:00
231 lines
5.2 KiB
Lua
231 lines
5.2 KiB
Lua
local codegen = require "codegen"
|
|
|
|
local gen = {}
|
|
|
|
local function to_underscorecase(name)
|
|
local tmp = {}
|
|
for v in name:gmatch "[_%u][%l%d]*" do
|
|
if v:byte() == 95 then -- '_'
|
|
v = v:sub(2)
|
|
end
|
|
tmp[#tmp+1] = v
|
|
end
|
|
return table.concat(tmp, "_")
|
|
end
|
|
|
|
function gen.gen()
|
|
local idl = codegen.idl()
|
|
|
|
-- Count C++ name occurrences for overload detection
|
|
-- Only count non-conly, non-class functions (free functions)
|
|
local cpp_name_count = {}
|
|
for _, f in ipairs(idl.funcs) do
|
|
if not f.conly and not f.class then
|
|
cpp_name_count[f.name] = (cpp_name_count[f.name] or 0) + 1
|
|
end
|
|
end
|
|
|
|
-- Collect section items by section id from declarations
|
|
local section_items = {}
|
|
|
|
for _, t in ipairs(idl.types) do
|
|
if t.section then
|
|
if not section_items[t.section] then
|
|
section_items[t.section] = {}
|
|
end
|
|
local kind
|
|
if t.flag then
|
|
kind = "flag"
|
|
elseif t.struct or t.enum then
|
|
kind = "struct"
|
|
end
|
|
if kind then
|
|
table.insert(section_items[t.section], {
|
|
kind = kind,
|
|
item = t,
|
|
order = t._order or 0,
|
|
})
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, f in ipairs(idl.funcs) do
|
|
if f.section and not f.conly and not f.class then
|
|
if not section_items[f.section] then
|
|
section_items[f.section] = {}
|
|
end
|
|
table.insert(section_items[f.section], {
|
|
kind = "func",
|
|
item = f,
|
|
order = f._order or 0,
|
|
})
|
|
end
|
|
end
|
|
|
|
for _, items in pairs(section_items) do
|
|
table.sort(items, function(a, b) return a.order < b.order end)
|
|
end
|
|
|
|
-- Build C++ function signature
|
|
local function build_signature(f)
|
|
local parts = {}
|
|
for _, arg in ipairs(f.args) do
|
|
local s = arg.fulltype .. " " .. arg.name
|
|
if arg.array then
|
|
s = s .. arg.array
|
|
end
|
|
if arg.default then
|
|
s = s .. " = " .. arg.default
|
|
end
|
|
parts[#parts+1] = s
|
|
end
|
|
return table.concat(parts, ", ")
|
|
end
|
|
|
|
-- Get BGFX_ define name for a flag item
|
|
local function get_define_name(flag_type, flag_item)
|
|
local prefix = "BGFX_" .. (flag_type.cname or to_underscorecase(flag_type.name):upper())
|
|
local suffix
|
|
if flag_item.cname then
|
|
suffix = flag_item.cname
|
|
else
|
|
suffix = to_underscorecase(flag_item.name):upper()
|
|
end
|
|
return prefix .. "_" .. suffix
|
|
end
|
|
|
|
local underlines = {
|
|
[0] = "=",
|
|
[1] = "-",
|
|
[2] = "~",
|
|
[3] = "*",
|
|
[4] = '"',
|
|
}
|
|
|
|
local r = {}
|
|
local function emit(s)
|
|
r[#r+1] = s or ""
|
|
end
|
|
|
|
emit(".. AUTO GENERATED! DO NOT EDIT!")
|
|
emit()
|
|
|
|
-- Determine leaf sections and build parent paths for item lookup.
|
|
-- A leaf section is one not immediately followed by a deeper-level section.
|
|
-- The path is "parent_title/title" (used to disambiguate duplicate titles).
|
|
local parent_at_level = {}
|
|
for i, sec in ipairs(idl.sections) do
|
|
parent_at_level[sec.level] = sec.title
|
|
local parent = parent_at_level[sec.level - 1]
|
|
sec._path = parent and (parent .. "/" .. sec.title) or sec.title
|
|
sec._is_leaf = true
|
|
if i > 1 then
|
|
local prev = idl.sections[i - 1]
|
|
if prev.level < sec.level then
|
|
prev._is_leaf = false
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, sec in ipairs(idl.sections) do
|
|
if sec.level > 0 then
|
|
emit()
|
|
end
|
|
|
|
-- Section header
|
|
emit(sec.title)
|
|
emit(string.rep(underlines[sec.level], #sec.title))
|
|
|
|
-- Description (skip first line if it matches the section title)
|
|
if sec.desc then
|
|
local start_idx = 1
|
|
if sec.desc[1] == sec.title then
|
|
start_idx = 2
|
|
end
|
|
-- Skip leading empty lines
|
|
while start_idx <= #sec.desc and sec.desc[start_idx] == "" do
|
|
start_idx = start_idx + 1
|
|
end
|
|
if start_idx <= #sec.desc then
|
|
emit()
|
|
local in_note = false
|
|
for i = start_idx, #sec.desc do
|
|
local line = sec.desc[i]
|
|
local remarks_text = line:match "^@remarks%s+(.*)"
|
|
if remarks_text then
|
|
emit(".. note::")
|
|
emit()
|
|
emit(" " .. remarks_text)
|
|
in_note = true
|
|
elseif in_note then
|
|
if line == "" then
|
|
emit()
|
|
else
|
|
emit(" " .. line)
|
|
end
|
|
else
|
|
emit(line)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Items (only for leaf sections)
|
|
if sec._is_leaf then
|
|
local items = section_items[sec._path] or section_items[sec.title] or {}
|
|
local prev_kind = nil
|
|
|
|
for _, entry in ipairs(items) do
|
|
if entry.kind == "func" then
|
|
local f = entry.item
|
|
local count = cpp_name_count[f.name] or 0
|
|
if prev_kind ~= "func" then
|
|
emit()
|
|
end
|
|
if count > 1 then
|
|
emit(".. doxygenfunction:: bgfx::" .. f.name .. "(" .. build_signature(f) .. ")")
|
|
else
|
|
emit(".. doxygenfunction:: bgfx::" .. f.name)
|
|
end
|
|
prev_kind = "func"
|
|
elseif entry.kind == "struct" then
|
|
local t = entry.item
|
|
emit()
|
|
emit(".. doxygenstruct:: bgfx::" .. (t.typename or t.name))
|
|
emit(" :members:")
|
|
prev_kind = "struct"
|
|
elseif entry.kind == "flag" then
|
|
local t = entry.item
|
|
emit()
|
|
if t.label then
|
|
emit("**" .. t.label .. "**")
|
|
emit()
|
|
end
|
|
for _, fitem in ipairs(t.flag) do
|
|
emit(".. doxygendefine:: " .. get_define_name(t, fitem))
|
|
end
|
|
prev_kind = "flag"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
emit()
|
|
|
|
return table.concat(r, "\n") .. "\n"
|
|
end
|
|
|
|
function gen.write(codes, outputfile)
|
|
local out = assert(io.open(outputfile, "wb"))
|
|
out:write(codes)
|
|
out:close()
|
|
print("Generating: " .. outputfile)
|
|
end
|
|
|
|
if (...) == nil then
|
|
-- run `lua docs-rst.lua` in command line
|
|
print(gen.gen())
|
|
end
|
|
|
|
return gen
|