diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b973370 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.velx +/.doc +.ktmp +debug.lua diff --git a/build.lua b/build.lua index fc25987..9fabb5c 100644 --- a/build.lua +++ b/build.lua @@ -159,9 +159,23 @@ local velx_spec = struct { -- This builds Tsuki into a VELX executable. print("Compiling kernel...") -local h = io.popen("luacomp ksrc/init.lua") +local h = io.popen("luacomp ksrc/init.lua", "r") +os.execute("luacomp ksrc/init.lua -O debug.lua") +local krnl = h:read("*a") +h:close() +print("Generating docs and stripping comments...") +os.execute("mkdir .docs") +h = io.popen("lua utils/gendocs.lua .docs 2>.ktmp", "w") +h:write(krnl) +h:close() +h = io.popen("find .docs -depth | tsar -o", "r") +local arc = h:read("*a") +h:close() +h = io.open(".ktmp", "rb") +local data = h:read("*a") +h:close() print("Compressing kernel...") -local data = M.compress(h:read("*a")) +data = M.compress(data) print("Writing out tkrnl.velx...") local h = io.open("tkrnl.velx", "wb") local header = velx_spec({ @@ -169,13 +183,17 @@ local header = velx_spec({ compression = 1, lver = 0x53, fver = 1, - os = 0xFF, + os = 0x7F, psize = #data, lsize=0, ssize=0, - rsize=0 + rsize=#arc }) - h:write(header) h:write(data) -h:close() \ No newline at end of file +h:write(arc) +h:close() +print("Cleaning up...") +os.execute("rm -rf .docs") +os.execute("rm -rf .ktmp") +print("Build complete.") \ No newline at end of file diff --git a/ksrc/bios/zoryalegacy/docs.lua b/ksrc/bios/zoryalegacy/docs.lua index 6d84874..b4a4fc9 100644 --- a/ksrc/bios/zoryalegacy/docs.lua +++ b/ksrc/bios/zoryalegacy/docs.lua @@ -1,6 +1,6 @@ ----@method "Zorya 1.x (Zorya Legacy)" ---[[-- - Zorya 1.x puts a few things in the global space that need to be removed. These include: - - The OEFI library - - The Zorya library -]] \ No newline at end of file +---@page zorya_legacy "Zorya 1.x (Zorya Legacy)" +---@doc "Zorya 1.x puts a few things in the global space that need to be removed. These include:" +---@doc "- The OEFI library" +---@doc "- The Zorya library" +---@doc "" +---@doc "Note: This *should* also apply to any forks of Zorya Legacy." \ No newline at end of file diff --git a/ksrc/bios/zoryaneo/docs.lua b/ksrc/bios/zoryaneo/docs.lua index f79adc7..2a310d5 100644 --- a/ksrc/bios/zoryaneo/docs.lua +++ b/ksrc/bios/zoryaneo/docs.lua @@ -1,4 +1,2 @@ ----@method "Zorya NEO (Zorya 2.0)" ---[[-- - There's not much to be done for Zorya NEO as the included Zorya module starts Tsuki with a nice enviroment. -]] \ No newline at end of file +---@page zorya_neo "Zorya NEO (Zorya 2.0)" +---@doc "There's not much to be done for Zorya NEO as the included Zorya module starts Tsuki with a nice enviroment." \ No newline at end of file diff --git a/ksrc/biosfixes.lua b/ksrc/biosfixes.lua index fe6ebe8..ec6db52 100644 --- a/ksrc/biosfixes.lua +++ b/ksrc/biosfixes.lua @@ -1,4 +1,4 @@ ----@module "BIOS fixes" +---@section biosfixes "BIOS fixes" local _biossupport = {} @[[function biosfix(bios)]] diff --git a/ksrc/lupi2.lua b/ksrc/lupi2.lua new file mode 100644 index 0000000..e69de29 diff --git a/ksrc/security.lua b/ksrc/security.lua index 6604fb2..838d91c 100644 --- a/ksrc/security.lua +++ b/ksrc/security.lua @@ -1,9 +1,15 @@ +---@module security Security local security = {} +---@func checkacl +---@arg permission string "The permission to check." +---@return boolean "True if the current process has this permission." function security.checkacl(permission) local perms = acl.get("group", thread.info().egid, {}) end +---@func getmode +---@return string "The current security mode." function security.getmode() end @@ -11,4 +17,4 @@ end function security.init() klog("security", 1, "Security init started.") -end \ No newline at end of file +end diff --git a/ksrc/stdlib/init.lua b/ksrc/stdlib/init.lua index 26a77bc..c5cb84b 100644 --- a/ksrc/stdlib/init.lua +++ b/ksrc/stdlib/init.lua @@ -2,4 +2,7 @@ function _P.load(...) if (security.checkacl("unsigned_code")) then end -end \ No newline at end of file +end + +--#include "ksrc/stdlib/string.lua" +--#include "ksrc/stdlib/thread.lua" \ No newline at end of file diff --git a/ksrc/stdlib/string.lua b/ksrc/stdlib/string.lua new file mode 100644 index 0000000..850e02c --- /dev/null +++ b/ksrc/stdlib/string.lua @@ -0,0 +1,11 @@ +_P.string = {} +@[[function copylib(method)]] +_P.string.@[{method}] = string.@[{method}] +@[[end]] + +@[[for k, v in pairs(string) do + copylib(k) +end]] +@[[copylib("trim")]] +@[[copylib("explode")]] +@[[copylib = nil]] \ No newline at end of file diff --git a/ksrc/stdlib/table.lua b/ksrc/stdlib/table.lua new file mode 100644 index 0000000..081bbdd --- /dev/null +++ b/ksrc/stdlib/table.lua @@ -0,0 +1,9 @@ +_P.table = {} +@[[function copylib(method)]] +_P.table.@[{method}] = table.@[{method}] +@[[end]] + +@[[for k, v in pairs(table) do + copylib(k) +end]] +@[[copylib = nil]] \ No newline at end of file diff --git a/tkrnl.velx b/tkrnl.velx index 57c815a..42f087e 100644 Binary files a/tkrnl.velx and b/tkrnl.velx differ diff --git a/utils/gendocs.lua b/utils/gendocs.lua new file mode 100644 index 0000000..96fac1a --- /dev/null +++ b/utils/gendocs.lua @@ -0,0 +1,248 @@ +local outdir = arg[1] + +function string.trim(self) + return self:gsub("^%s+", ""):gsub("%s+$", "") +end + +local escapes = { + ["\\"] = "\\", + ["n"] = "\n", + ["t"] = "\t", + ["r"] = "\r" +} +local docs = {} +local cdoc +local cfunc +local function parse_string(str, close, noesc) + local s = "" + local esc = false + repeat + local c = str.read() + if not esc then + if (c ~= "\\" or noesc) then + s = s .. c + else + esc = true + end + else + if (escapes[c]) then + s = s .. escapes[c] + else + return nil, "invalid escape" + end + end + until str.peek(#close) == close or str.peek(#close) == "" + str.seek(#close) + return s +end + +local function parse_dec(str) + local num = "" + repeat + num = num .. str.read() + until not str.peek():match("%d") or str.peek() == "" + return tonumber(num, 10) +end + +local function parse_hex(str) + if not str.peek():match("%x") then + return nil, "malformed hex" + end + local num = "" + repeat + num = num .. str.read() + until not str.peek():match("%x") or str.peek() == "" + return tonumber(num, 16) +end +local ln = 0 +local function parse_line(line) + local args = {} + local idx = 1 + local str = { + peek = function(amt) + amt = amt or 1 + return line:sub(idx, idx+amt-1) + end, + read = function(amt) + amt = amt or 1 + local data = line:sub(idx, idx+amt-1) + idx = idx + amt + return data + end, + seek = function(amt) + amt = amt or 0 + idx = idx + amt + return idx + end + } + local function lassert(a, b) + return assert(a, "line #"..ln..": "..(b or "unknown error")) + end + while str.peek() ~= "" do + if (str.peek() == "\"") then + str.seek(1) + args[#args+1] = lassert(parse_string(str, "\"", false)) + elseif (str.peek(2) == "0x") then + str.seek(2) + args[#args+1] = lassert(parse_hex(str)) + elseif (str.peek(1):match("%d")) then + args[#args+1] = lassert(parse_dec(str)) + elseif (str.peek() == "'") then + str.seek(1) + args[#args+1] = lassert(parse_string(str, "'", false)) + elseif (str.peek() == " ") then + --do nothing + else + args[#args+1] = lassert(parse_string(str, " ", true)) + end + end + return args +end +local function is_comment(line) + if (line:trim():sub(1, 2) == "--") then + return true, line:sub(3) + end +end +for line in io.stdin:lines() do + ln = ln+1 + local com, rline = is_comment(line) + if (com) then + if (rline:match("^%-@module")) then + local args = parse_line(rline:sub(10)) + if (cdoc) then + if (cfunc) then + cdoc.methods[#cdoc.methods+1] = cfunc + end + docs[#docs+1] = cdoc + end + cdoc = { + type = "module", + methods = {}, + name = args[2], + mod = args[1] + } + elseif (rline:match("^%-@section")) then + local args = parse_line(rline:sub(11)) + if (cdoc) then + if (cfunc) then + cdoc.methods[#cdoc.methods+1] = cfunc + end + docs[#docs+1] = cdoc + end + cdoc = { + type = "generic", + methods = {}, + name = args[2], + mod = args[1] + } + elseif (rline:match("^%-@page")) then + if (cfunc) then + cdoc.methods[#cdoc.methods+1] = cfunc + end + local args = parse_line(rline:sub(8)) + cfunc = { + type = "page", + doc = {}, + name = args[1], + print_name = args[2] + } + elseif (rline:match("^%-@arg") and cfunc.type == "func") then + local args = parse_line(rline:sub(7)) + cfunc.args[#cfunc.args+1] = { + name = args[1], + type = args[2], + doc = args[3] + } + elseif (rline:match("^%-@return") and cfunc.type == "func") then + local args = parse_line(rline:sub(10)) + cfunc.ret[#cfunc.args+1] = { + type = args[1], + doc = args[2], + } + elseif (rline:match("^%-@doc")) then + local args = parse_line(rline:sub(7)) + cfunc.doc[#cfunc.doc+1] = { + doc = args[1], + } + elseif (rline:match("^%-@see")) then + local args = parse_line(rline:sub(7)) + cfunc.doc[#cfunc.doc+1] = { + doc = "See \27_S"..arg[2].."\27_E" + } + elseif (rline:match("^%-@vararg")) then + cfunc.vararg = true + elseif (rline:match("^%-@varret")) then + cfunc.varret = true + elseif (rline:match("^%-@func")) then + if (cfunc) then + cdoc.methods[#cdoc.methods+1] = cfunc + end + local args = parse_line(rline:sub(8)) + cfunc = { + type = "func", + doc = {}, + name = args[1], + ret = {}, + args = {} + } + end + else + io.stderr:write(line.."\n") + end +end + +if (cfunc) then + cdoc.methods[#cdoc.methods+1] = cfunc +end +if (cdoc) then + docs[#docs+1] = cdoc +end +for i=1, #docs do + os.execute("mkdir -p \""..outdir.."/"..docs[i].mod:trim().."\"") + for j=1, #docs[i].methods do + local docc = "" + local f = io.open(outdir.."/"..docs[i].mod:trim().."/"..docs[i].methods[j].name:trim()..".tdf", "wb") + if (docs[i].methods[j].type == "func") then + local argtext = "" + local fun = docs[i].mod.."."..docs[i].methods[j].name.."(" + if (#docs[i].methods[j].args > 0) then + for k=1, #docs[i].methods[j].args do + fun = fun .. docs[i].methods[j].args[k].name..":"..docs[i].methods[j].args[k].type .. ", " + argtext = argtext .. docs[i].methods[j].args[k].name .. " - " .. docs[i].methods[j].args[k].doc .. "\n" + end + if (docs[i].methods[j].vararg) then + fun = fun .. "..." + else + fun = fun:sub(1, #fun-2) + end + else + argtext = "No arguments" + end + fun = fun .. ")" + + local rettext = "" + if (#docs[i].methods[j].ret > 0) then + fun = fun .. ":" + for k=1, #docs[i].methods[j].ret do + fun = fun .. docs[i].methods[j].ret[k].type .. ", " + rettext = rettext .. docs[i].methods[j].ret[k].type .. " - " .. docs[i].methods[j].ret[k].doc .. "\n" + end + if (docs[i].methods[j].varret) then + fun = fun .. "..." + else + fun = fun:sub(1, #fun-2) + end + else + rettext = "No return." + end + docc = docc .. fun .. "\n\nArguments:\n"..argtext.."\n\nReturns:\n"..rettext + else + docc = docc .. docs[i].methods[j].print_name .. "\n\n" + end + for k=1, #docs[i].methods[j].doc do + docc = docc..docs[i].methods[j].doc[k].doc .. "\n" + end + f:write(docc) + f:close() + end +end \ No newline at end of file