Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@Oberon00
Last active June 14, 2020 08:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Oberon00/8c74d22c25a0fb3581e7 to your computer and use it in GitHub Desktop.
Save Oberon00/8c74d22c25a0fb3581e7 to your computer and use it in GitHub Desktop.
Lua C API function HTML reference table data & generator (http://oberon00.github.io/lua-cfuncidx/index.html)
-- Helpers {{{1
local function fail_on_missing_tbl(t, missing_name)
missing_name = missing_name or 'table entry'
return setmetatable(t, {__index = function(t, k)
error(('No %s with key "%s" (in %s).'):format(missing_name, k, t))
end
})
end
fail_on_missing_tbl(_G, 'global');
local function nolprefixname(fn)
return fn:sub(1, 2) == 'L_' and fn:sub(3) or fn
end
local function keys(tbl)
local result = {}
for k, v in pairs(tbl) do
result[#result + 1] = k
end
return result
end
local function swapkv(tbl)
local result = {}
for k, v in pairs(tbl) do
result[v] = k
end
return result
end
local function findfirst(needles, haystackset)
for _, needle in ipairs(needles) do
local v = haystackset[needle]
if v then
return v
end
end
return nil
end
-- Category data {{{1
local cat = fail_on_missing_tbl({
stack = 'Stack manipulation',
exec = 'Executing Lua code',
err = 'Error handling',
coro = 'Coroutines',
state = 'lua_State managemenent',
str = 'string functions',
psh = 'Creating and pushing new values',
tbl = 'table functions',
fn = 'function functions',
mem = 'Memory and allocation related functions',
glob = 'Global table',
dbg = 'Debugging functions',
mt = 'Metatable functions',
udata = 'userdata functions',
ty = 'Type information',
chunk = 'Chunk loading and dumping',
num = 'number functions',
nostate = 'Functions not needing a lua_State*',
op = 'Operators',
verr = 'Raising errors on purpose',
rerr = 'Possibly raising errors',
merr = 'Raising errors only when out of memory',
zerr = 'Never raising errors',
aux = 'Auxiliary library (luaL_*)',
buf = 'String buffer (luaL_Buffer) functions',
get = 'Functions for getting Lua values to C objects'
}, 'category')
local cat_mt = {__index = function(c, k)
error (('Property "%s" does not exist in category %s.'):format(k, c.id))
end}
for k, v in pairs(cat) do
cat[k] = setmetatable({id = k, title = v}, cat_mt)
end
local ecats = {cat.verr, cat.rerr, cat.merr, cat.zerr}
-- Function data {{{1
local cfuncs = fail_on_missing_tbl({
absindex = {cat.stack},
arith = {cat.num, cat.op, cat.rerr},
atpanic = {cat.err},
call = {cat.exec, cat.rerr},
callk = {cat.exec, cat.coro, cat.rerr},
checkstack = {cat.stack},
close = {cat.state},
compare = {cat.op, cat.num, cat.rerr},
concat = {cat.op, cat.str, cat.rerr},
copy = {cat.stack},
createtable = {cat.psh, cat.tbl, cat.merr},
dump = {cat.fn, cat.chunk},
error = {cat.err, cat.verr},
gc = {cat.mem, cat.rerr}, -- misc?
getallocf = {cat.mem},
getextraspace = {cat.state},
getfield = {cat.tbl, cat.rerr},
getglobal = {cat.glob, cat.rerr},
gethook = {cat.dbg},
gethookcount = {cat.dbg},
gethookmask = {cat.dbg},
geti = {cat.tbl, cat.rerr},
getinfo = {cat.dbg, cat.rerr}, -- ?
getlocal = {cat.dbg, cat.fn},
getmetatable = {cat.tbl, cat.mt},
getstack = {cat.dbg},
gettable = {cat.tbl, cat.op, cat.rerr},
gettop = {cat.stack},
getupvalue = {cat.dbg, cat.fn},
getuservalue = {cat.udata},
insert = {cat.stack},
isboolean = {cat.ty},
iscfunction = {cat.ty, cat.fn},
isinteger = {cat.ty, cat.num},
islightuserdata = {cat.ty, cat.udata},
isnil = {cat.ty},
isnone = {cat.ty},
isnoneornil = {cat.ty},
isnumber = {cat.ty, cat.num},
isstring = {cat.ty, cat.str},
istable = {cat.ty, cat.tbl},
isthread = {cat.ty, cat.coro},
isuserdata = {cat.ty, cat.udata},
isyieldable = {cat.coro},
len = {cat.tbl, cat.op, cat.rerr},
load = {cat.fn, cat.chunk},
newstate = {cat.state, cat.nostate},
newtable = {cat.tbl, cat.psh, cat.merr},
newthread = {cat.coro, cat.psh, cat.merr},
newuserdata = {cat.udata, cat.psh, cat.merr},
next = {cat.tbl, cat.rerr},
numbertointeger = {cat.num, cat.nostate},
pcall = {cat.exec, cat.err},
pcallk = {cat.exec, cat.err, cat.coro},
pop = {cat.stack},
pushboolean = {cat.psh},
pushcclosure = {cat.psh, cat.fn, cat.merr}, -- conditionally safe, cf. pushcfunction
pushcfunction = {cat.psh, cat.fn},
pushfstring = {cat.psh, cat.str, cat.merr},
pushglobaltable = {cat.psh, cat.glob},
pushinteger = {cat.psh, cat.num},
pushlightuserdata = {cat.psh, cat.udata},
pushliteral = {cat.psh, cat.str, cat.merr},
pushlstring = {cat.psh, cat.str, cat.merr},
pushnil = {cat.psh},
pushnumber = {cat.psh, cat.num},
pushstring = {cat.psh, cat.str, cat.merr},
pushthread = {cat.psh, cat.coro},
pushvalue = {cat.psh, cat.stack},
pushvfstring = {cat.psh, cat.str, cat.merr},
rawequal = {cat.op},
rawget = {cat.tbl, cat.op},
rawgeti = {cat.tbl},
rawgetp = {cat.tbl},
rawlen = {cat.tbl},
rawset = {cat.tbl, cat.merr},
rawseti = {cat.tbl, cat.merr},
rawsetp = {cat.tbl, cat.merr},
register = {cat.glob, cat.fn, cat.rerr},
remove = {cat.stack},
replace = {cat.stack},
resume = {cat.coro},
rotate = {cat.stack},
setallocf = {cat.mem},
setfield = {cat.tbl, cat.rerr},
setglobal = {cat.glob, cat.rerr},
sethook = {cat.dbg},
seti = {cat.tbl, cat.rerr},
setlocal = {cat.dbg, cat.fn},
setmetatable = {cat.tbl, cat.mt, cat.rerr},
settable = {cat.tbl, cat.op, cat.rerr},
settop = {cat.stack},
setupvalue = {cat.dbg, cat.fn},
setuservalue = {cat.udata},
status = {cat.coro},
stringtonumber = {cat.str, cat.num},
toboolean = {cat.get},
tocfunction = {cat.get, cat.fn},
tointeger = {cat.get, cat.num},
tointegerx = {cat.get, cat.num},
tolstring = {cat.get, cat.str, cat.merr},
tonumber = {cat.get, cat.num},
tonumberx = {cat.get, cat.num},
topointer = {cat.dbg},
tostring = {cat.get, cat.str, cat.merr},
tothread = {cat.get, cat.coro},
touserdata = {cat.get, cat.udata},
type = {cat.ty},
typename = {cat.ty},
upvalueid = {cat.dbg, cat.fn},
upvalueindex = {cat.fn, cat.stack},
upvaluejoin = {cat.dbg, cat.fn},
version = {cat.state, cat.nostate},
xmove = {cat.coro, cat.stack},
yield = {cat.coro, cat.rerr},
yieldk = {cat.coro, cat.rerr},
-- auxlib
addchar = {cat.aux, cat.buf, cat.merr},
addlstring = {cat.aux, cat.buf, cat.merr},
addsize = {cat.aux, cat.buf},
addstring = {cat.aux, cat.buf, cat.merr},
addvalue = {cat.aux, cat.merr},
argcheck = {cat.aux, cat.verr},
argerror = {cat.aux, cat.verr},
buffinit = {cat.aux, cat.buf},
buffinitsize = {cat.aux, cat.buf, cat.merr},
callmeta = {cat.aux, cat.rerr, cat.mt, cat.exec},
checkany = {cat.aux, cat.verr},
checkinteger = {cat.aux, cat.verr, cat.num, cat.get},
checklstring = {cat.aux, cat.verr, cat.str, cat.get},
checknumber = {cat.aux, cat.verr, cat.num, cat.get},
checkoption = {cat.aux, cat.verr, cat.str, cat.get},
L_checkstack = {cat.aux, cat.verr, cat.stack},
checkstring = {cat.aux, cat.verr, cat.str, cat.get},
checktype = {cat.aux, cat.verr, cat.ty},
checkudata = {cat.aux, cat.verr, cat.udata, cat.get},
checkversion = {cat.aux, cat.verr, cat.state},
dofile = {cat.aux, cat.exec, cat.chunk, cat.rerr},
dostring = {cat.aux, cat.exec, cat.chunk},
L_error = {cat.aux, cat.err, cat.verr, cat.str},
execresult = {cat.aux, cat.merr}, -- cat.internal
fileresult = {cat.aux, cat.merr}, -- cat.internal
getmetafield = {cat.aux, cat.merr, cat.mt},
L_getmetatable = {cat.aux, cat.merr, cat.mt},
getsubtable = {cat.aux, cat.tbl, cat.rerr},
gsub = {cat.aux, cat.str, cat.merr},
L_len = {cat.aux, cat.tbl, cat.rerr},
loadbuffer = {cat.aux, cat.chunk},
loadbufferx = {cat.aux, cat.chunk},
loadfile = {cat.aux, cat.chunk, cat.merr},
loadfilex = {cat.aux, cat.chunk, cat.merr},
loadstring = {cat.aux, cat.chunk},
newlib = {cat.aux, cat.tbl, cat.fn, cat.merr},
newlibtable = {cat.aux, cat.tbl, cat.merr},
newmetatable = {cat.aux, cat.mt, cat.merr},
L_newstate = {cat.aux, cat.state, cat.nostate},
openlibs = {cat.aux, cat.state, cat.rerr},
optinteger = {cat.aux, cat.get, cat.num, cat.verr},
optlstring = {cat.aux, cat.get, cat.str, cat.verr},
optnumber = {cat.aux, cat.get, cat.num, cat.verr},
optstring = {cat.aux, cat.get, cat.str, cat.verr},
prepbuffer = {cat.aux, cat.buf, cat.merr},
prepbuffsize = {cat.aux, cat.buf, cat.merr},
pushresult = {cat.aux, cat.buf, cat.merr},
pushresultsize = {cat.aux, cat.buf, cat.merr},
ref = {cat.aux, cat.merr, cat.tbl},
requiref = {cat.aux, cat.rerr, cat.exec, cat.fn},
setfuncs = {cat.aux, cat.fn, cat.tbl, cat.merr},
L_setmetatable = {cat.aux, cat.mt},
testudata = {cat.aux, cat.mt, cat.merr, cat.get, cat.udata},
L_tolstring = {cat.aux, cat.get, cat.str, cat.op, cat.rerr},
traceback = {cat.aux, cat.dbg, cat.merr},
typename = {cat.aux, cat.ty, cat.merr},
unref = {cat.aux, cat.tbl},
where = {cat.aux, cat.dbg, cat.merr}
}, 'C function')
-- Adds zerr category {{{2
-- to any function which does not already have a error category.
if false then -- disable
for fname, fcats in pairs(cfuncs) do
if not findfirst(ecats, swapkv(fcats)) then
table.insert(fcats, cat.zerr)
end
end
end
-- Output generation {{{1
local out = io.stdout
local fns_by_cat = {}
for fname, fcats in pairs(cfuncs) do
for _, fcat in ipairs(fcats) do
local catfns = fns_by_cat[fcat.id]
if not catfns then
fns_by_cat[fcat.id] = {fname}
else
catfns[#catfns + 1] = fname
end
end
end
local catids = keys(fns_by_cat) -- use fns_by_cat instead of cat: ignores emtpy
table.sort(catids, function(a, b)
return cat[a].title:lower() < cat[b].title:lower()
end)
-- Write static start of page and category index {{{2
out:write(
[[
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Lua C-API functions by category</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Lua C-API functions by category</h1>
<p>Functions may appear in multiple categories.</p>
<p>
The prefixes <code>lua_</code> and <code>luaL_</code> are omitted. Some
function pairs (e.g. <code>lua_len</code> and <code>luaL_len</code>) only
differ in the prefix. In this cases look if the function is marked as being
in the <a href="#aux">“Auxiliary library” (aux)</a> category.
</p>
<p>
Categories: <ul class="cats">
]])
local catentry_fmt = '<a class="cat" href="#%s">%s (%s)</a>'
for _, catid in ipairs(catids) do
local ct = cat[catid]
out:write(' <li>' .. catentry_fmt:format(ct.id, ct.title, ct.id) .. '\n')
end
out:write('</ul></p>\n')
-- Write functions by category and end of page {{{2
local cathdr_fmt = '<h2 class="cathdr" id="%s">%s</h2>\n'
local func_fmt = '<a class="func" title="%s" href="http://www.lua.org/manual/5.3/manual.html#%s">%s</a>'
local catlnk_fmt = '<a class="catlnk" title="%s" href="#%s">%s</a>'
local function write_extracats(fcats, catid)
if #fcats <= 1 then
return -- There is just the single category already in the header.
end
out:write(' <ul class="funccats">\n')
for _, curct in ipairs(fcats) do
if curct.id ~= catid then
local catlnk = catlnk_fmt:format(curct.title, curct.id, curct.id)
out:write(' <li>' .. catlnk .. '\n')
end
end
out:write(' </ul>\n')
end
for _, catid in ipairs(catids) do
catfns = fns_by_cat[catid]
table.sort(catfns, function(a, b)
-- Sort by name first, if same, sort L_ prefix after others
local aname, bname = nolprefixname(a), nolprefixname(b)
return aname == bname and #a < #b or aname < bname
end)
out:write(cathdr_fmt:format(catid, cat[catid].title))
out:write('<ul class="catfns">\n')
for _, catfn in ipairs(catfns) do
local fcats = cfuncs[catfn]
catfn = nolprefixname(catfn)
local ltag = fcats[1] == cat.aux and 'L' or ''
table.sort(fcats, function(a, b) return a.id < b.id end)
local ffullname = 'lua' .. ltag .. '_' .. catfn
out:write('<li>' .. func_fmt:format(ffullname, ffullname, catfn) .. '\n')
write_extracats(fcats, catid)
end
out:write('</ul>\n')
end
out:write('\n<aside>Generated by <a href="https://gist.github.com/Oberon00/8c74d22c25a0fb3581e7">https://gist.github.com/Oberon00/8c74d22c25a0fb3581e7</a>.</aside>')
out:write('\n</body>\n</html>\n')
-- vim: fdm=marker
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment