From 6160564247d4774ffdb1ceb59fae332207e56e76 Mon Sep 17 00:00:00 2001 From: XeonSquared Date: Sun, 30 Jul 2017 19:12:10 +1000 Subject: [PATCH] added all the already working stuff --- .gitignore | 2 + docs/api.md | 46 +++++++++++++++ genkernel.sh | 2 + modules/applications/luash.lua | 9 +++ modules/base/footer.lua | 1 + modules/base/header.lua | 102 +++++++++++++++++++++++++++++++++ modules/base/header.lua.old | 97 +++++++++++++++++++++++++++++++ modules/debug/log.lua | 13 +++++ modules/drivers/kbd.lua | 20 +++++++ modules/drivers/net.lua | 23 ++++++++ modules/drivers/tty.lua | 47 +++++++++++++++ modules/lib/buffer.lua | 33 +++++++++++ modules/lib/print.lua | 10 ++++ modules/lib/readline.lua | 17 ++++++ modules/setup.lua | 6 ++ modules/tests/dec.lua | 8 +++ modules/tests/inc.lua | 8 +++ strip.lua | 43 ++++++++++++++ wtape.lua | 12 ++++ 19 files changed, 499 insertions(+) create mode 100644 .gitignore create mode 100644 docs/api.md create mode 100755 genkernel.sh create mode 100644 modules/applications/luash.lua create mode 100644 modules/base/footer.lua create mode 100644 modules/base/header.lua create mode 100644 modules/base/header.lua.old create mode 100644 modules/debug/log.lua create mode 100644 modules/drivers/kbd.lua create mode 100644 modules/drivers/net.lua create mode 100644 modules/drivers/tty.lua create mode 100644 modules/lib/buffer.lua create mode 100644 modules/lib/print.lua create mode 100644 modules/lib/readline.lua create mode 100644 modules/setup.lua create mode 100644 modules/tests/dec.lua create mode 100644 modules/tests/inc.lua create mode 100644 strip.lua create mode 100644 wtape.lua diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cf0c423 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +kernel.lua +skernel.lua diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..1fa3ea2 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,46 @@ +# API +## Functions +### system +#### spawn(*name*, *function*, *environment*) +Spawns a process from *function* called *name* with *environment*. +### os +#### os.getenv(*k*) +Gets the *k* environment variable for the current process. +#### os.setenv(*k*, *v*) +Sets the *k* environment variable to *v* for the current process. +#### os.tasks() +Returns a list of current processes running, the key being the pid and the value being the name. +#### os.taskinfo(*pid*) +Returns the name, parent process, and user ID for process *pid*. +### event +#### event.get() +Gets the next event in the event queue for the process. +#### event.pull(*type*) +Gets, and possibly waits, for an event, optionally with *type +### buffer +#### buffer.create(*w*, *c*) +Creates a buffer with worker function *w* and close function *c*. *w* is called on creation with the buffer as the argument. +### I/O stuff +#### write(...) +Writes its arguments to the I/O device. +#### print(...) +Writes its arguments to the I/O device, with a newline after each. +#### readln(*rch*) +Reads a line from the I/O device, optionally replacing the echoed characters with *rch*. +### drivers +#### tty(*gA*, *sA*, *sI*, *fg*, *bg*) +Creates a GPU driver instance for GPU *gA* and screen *sA* attached to session *sI*, optionally with foreground and background colours *fg* and *bg*. +#### kbd(*kA*, *sI*) +Creates a keyboard driver instance for keyboard *kA* attached to session *sI*. +## Events +### Network +#### net\_msg, *from*, *port*, *message* +Queued when the system receives message *message* from *from* on port *port*. +### Terminal I/O +#### key, *session*, *char*, *code* +A key with value *char* and code *code* was pressed and parsed by a keyboard handler attached to session *session* +#### display, *session*, *text* +This is triggered to make a tty driver attached to *session* write *text* to the screen. Ideally, use write(), not the raw event. +## Applications +### luash(*sI*) +Spawns a luash instance for session *sI* diff --git a/genkernel.sh b/genkernel.sh new file mode 100755 index 0000000..8fee321 --- /dev/null +++ b/genkernel.sh @@ -0,0 +1,2 @@ +#!/bin/bash +cat modules/debug/log.lua modules/base/header.lua modules/drivers/tty.lua modules/lib/print.lua modules/drivers/kbd.lua modules/drivers/net.lua modules/lib/readline.lua modules/applications/luash.lua modules/setup.lua modules/base/footer.lua diff --git a/modules/applications/luash.lua b/modules/applications/luash.lua new file mode 100644 index 0000000..a7447f9 --- /dev/null +++ b/modules/applications/luash.lua @@ -0,0 +1,9 @@ +function luash(si) +spawn("lua shell",function() + print(_VERSION) + while true do + write("> ") + print(pcall(load(readln()))) + end +end,si) +end diff --git a/modules/base/footer.lua b/modules/base/footer.lua new file mode 100644 index 0000000..1fffee4 --- /dev/null +++ b/modules/base/footer.lua @@ -0,0 +1 @@ +sched() diff --git a/modules/base/header.lua b/modules/base/header.lua new file mode 100644 index 0000000..a4d7247 --- /dev/null +++ b/modules/base/header.lua @@ -0,0 +1,102 @@ +do -- so local works + -- task format: + -- { + -- ["n"] = "name", + -- ["c"] = coroutine of task, + -- ["e"] = { table, of, environment, variables }, + -- ["p"] = parent pid, + -- ["u"] = user ID, + -- ["ep"]= event queue pointer + -- } + local tT,nP,rg,eq,p = {},1,_G,{},1 -- taskTable,nextPid,real _G,event queue + _G.cT,sbt,C,T = 0,{},coroutine,table -- currentTask,sandboxTable + function _G.spawn(n,f,e) + tT[nP] = {} + sbt[nP] = {} + setmetatable(sbt[nP],{__index=_G}) + _ENV = sbt[nP] + tT[nP].c = coroutine.create(f) + _ENV = rg + tT[nP].n = n + tT[nP].p = cT or -1 + if tT[cT] then + tT[nP].u,tT[nP].ep,tT[nP].e = tT[cT].u,tT[cT].ep,e or tT[cT].e or {} + else + tT[nP].u,tT[nP].ep,tT[nP].e = 0,1,{} + end + nP = nP + 1 + end + function _G.sched() + _G.sched = nil + while #tT > 0 do + eq[#eq+1]={computer.pullSignal(p)} -- add the latest event to the eq + if #eq > 16 then + table.remove(eq,1) -- remove the earliest if the eq is full + for pid,proc in ipairs(tT) do + if proc.ep > 1 then + proc.ep = proc.ep - 1 -- decrement pointers for tasks to keep them on the same ones + end + end + end + for pid,proc in ipairs(tT) do + if coroutine.status(proc.c) == "dead" then + tT[pid] = nil + else + cT=pid + for i = 1,tT[pid].ep, #eq do + sbt[pid].ev = eq[#eq] -- make an ev for MultICE compat + coroutine.resume(proc.c) + end + end + end + end + end + _G.event = {} + function event.get() -- get the next event in the queue, or nil + if eq[tT[cT].ep] then + tT[cT].ep = tT[cT].ep + 1 + if tT[cT].ep > 17 then + tT[cT].ep = 17 + end + return eq[tT[cT].ep - 1] + end + end + function event.pull(t) -- return or wait for the next event, optionally with the first param matching t + while true do + local e = event.get() + if e then + if t then + if e[1] == t then + return table.unpack(e) + end + else + return table.unpack(e) + end + end + coroutine.yield() + end + end + event.push = computer.pushSignal + function os.getenv(k) -- gets an envionment variable from tT[cT].e + if tT[cT] then + return tT[cT].e[k] + end + end + function os.setenv(k,v) -- sets " + if tT[cT] then + tT[cT].e[k] = v + end + end + function os.tasks() -- returns a table of tasks running on the system + local t = {} + for k,v in ipairs(tT) do + t[k] = v.n + end + return t + end + function os.taskinfo(pid) -- returns info on a task + if tT[pid] then + return tT[pid].n,tT[pid].p,tT[pid].u + end + end +end diff --git a/modules/base/header.lua.old b/modules/base/header.lua.old new file mode 100644 index 0000000..fd7cc1d --- /dev/null +++ b/modules/base/header.lua.old @@ -0,0 +1,97 @@ +if component then + function log(...) + for k,v in ipairs({...}) do + component.invoke(component.list("ocemu")(),"log",v) + end + end + print=log +else log = print +end +do -- so local works + -- task format: + -- { + -- ["n"] = "name", + -- ["c"] = coroutine of task, + -- ["e"] = { table, of, environment, variables }, + -- ["p"] = parent pid, + -- ["u"] = user ID, + -- ["ep"]= event queue pointer + -- } + local tT,nP,rg,eq,p = {},1,_G,{},1 -- taskTable,nextPid,real _G,event queue + _G.cT,sbt,C,T = 0,{},coroutine,table -- currentTask,sandboxTable + function _G.spawn(n,f,e) + tT[nP] = {} + sbt[nP] = {} + setmetatable(sbt[nP],{__index=_G}) + _ENV = sbt[nP] + tT[nP].c = coroutine.create(f) + _ENV = rg + tT[nP].n = n + tT[nP].p = cT or -1 + if tT[cT] then + tT[nP].u,tT[nP].ep,tT[nP].e = tT[cT].u,tT[cT].ep,e or tT[cT].e or {} + else + tT[nP].u,tT[nP].ep,tT[nP].e = 0,1,{} + end + nP = nP + 1 + end + function _G.sched() + _G.sched = nil + while #tT > 0 do + eq[#eq+1]={computer.pullSignal(p)} -- add the latest event to the eq + if #eq > 16 then + table.remove(eq,1) -- remove the earliest if the eq is full + for pid,proc in ipairs(tT) do + if proc.ep > 1 then + proc.ep = proc.ep - 1 -- decrement pointers for tasks to keep them on the same ones + end + end + end + for pid,proc in ipairs(tT) do + if coroutine.status(proc.c) == "dead" then + tT[pid] = nil + else + cT=pid + sbt[pid].ev = eq[#eq] -- make an ev for MultICE compat + coroutine.resume(proc.c) + end + end + end + end + _G.event = {} + function event.get() -- get the next event in the queue, or nil + if eq[tT[cT].ep] then + tT[cT].ep = tT[cT].ep + 1 + if tT[cT].ep > 17 then + tT[cT].ep = 17 + end + return eq[tT[cT].ep - 1] + end + end + function event.pull(t) -- return or wait for the next event, optionally with the first param matching t + while true do + local e = event.get() + if e then + if t then + if e[1] == t then + return table.unpack(e) + end + else + return table.unpack(e) + end + end + coroutine.yield() + end + end + event.push = computer.pushSignal + function os.getenv(k) + if tT[cT] then + return tT[cT].e[k] + end + end + function os.setenv(k,v) + if tT[cT] then + tT[cT].e[k] = v + end + end +end diff --git a/modules/debug/log.lua b/modules/debug/log.lua new file mode 100644 index 0000000..b33113e --- /dev/null +++ b/modules/debug/log.lua @@ -0,0 +1,13 @@ +if component then + _G.Log = "" + function log(...) + if component.list("ocemu")() then + for k,v in ipairs({...}) do + component.invoke(component.list("ocemu")(),"log",v) + end + end + Log=Log..tostring(v).."\n" + end + print=log +else log = print +end diff --git a/modules/drivers/kbd.lua b/modules/drivers/kbd.lua new file mode 100644 index 0000000..0b69336 --- /dev/null +++ b/modules/drivers/kbd.lua @@ -0,0 +1,20 @@ +function kbd(kA,sI) + spawn("kbd: "..kA:sub(1,8),function() + while true do + local _,ka,c,C = event.pull("key_down") + if ka == kA then + event.push("key",sI,c,C) + end + end + end) + spawn("kbd-clipboard: "..kA:sub(1,8),function() + while true do + local _,ka,s = event.pull("clipboard") + if ka == kA then + for c in s:gmatch(".") do + event.push("key",sI,string.byte(c),0) + end + end + end + end) +end diff --git a/modules/drivers/net.lua b/modules/drivers/net.lua new file mode 100644 index 0000000..0b8057b --- /dev/null +++ b/modules/drivers/net.lua @@ -0,0 +1,23 @@ +function _G.net_send(id,po,msg) -- id, port, message + event.push("sendmsg",id,po,msg) +end +spawn("network daemon",function () + tM,nP,_G.nID,nVL = {}, 4096, computer.address():sub(1,8), 1 + for a,t in component.list("modem") do -- open the port of the vlan on all network interfaces + table.insert(tM,component.proxy(a)) + component.proxy(a).open(nVL) + end + while true do + local ev = {event.pull()} -- this totally isn't just MultICE code with a fancy wrapper + if ev[1] == "sendmsg" then + local eT = ev + for k,v in ipairs(tM) do + v.broadcast(nVL,nP,eT[2],nID,eT[3],eT[4]) + end + elseif ev[1] == "modem_message" then + if ev[7] == nID then + event.push("net_msg",ev[8],ev[9],ev[10]) + end + end + end +end) diff --git a/modules/drivers/tty.lua b/modules/drivers/tty.lua new file mode 100644 index 0000000..7ec8645 --- /dev/null +++ b/modules/drivers/tty.lua @@ -0,0 +1,47 @@ +function tty(gA,sA,sI,fg,bg) -- gpuAddress,screenAddress,sessionID,foreground,background + local gP,cx,cy,bg,fg = component.proxy(gA),1,1,bg or 0x000000, fg or 0xffffff -- basic setup from here + gP.bind(sA) + local sx, sy = gP.getResolution() + gP.setResolution(sx,sy) + gP.setForeground(fg) + gP.setBackground(bg) + gP.fill(1,1,sx,sy," ") + local function cv() -- check cursor position + if cx > sx then cx,cy=1,cy+1 end + if cx < 1 then cx,cy=sx,cy-1 end + if cy < 1 then cx,cy=1,1 end + if cy > sy then gP.copy(1,2,sx,sy-1,0,-1) gP.fill(1,sy,sx,1," ") cx,cy=1,sy end + end + local function ic(s) + local cc,fg,bg=gP.get(cx,cy) + if s then fG,bG = bg,fg else fG,bG = fg,bg end + gP.setForeground(bG) + gP.setBackground(fG) + gP.set(cx,cy,cc) + gP.setForeground(fG) + gP.setBackground(bG) + end + local function wl(str) -- write line + for c in str:gmatch(".") do + if c == "\n" then cx,cy=1,cy+1 + elseif c == "\r" then cx=1 + elseif c == "\f" then cx=1 cy=1 gP.fill(1, 1, sx, sy, " ") + elseif c == "\t" then cx=(cx+4-((cx+4)%4))+1 + elseif c == "\127" or c == "\008" then cx=cx-1 gP.set(cx,cy," ") + else gP.set(cx,cy,c) cx=cx+1 + end cv() + end + end + spawn("tty",function() log(pcall(function() -- spawns the listener + local csi = os.getenv("sI") + log(csi) + while true do + _,si,str=event.pull("display") + if si == csi then + wl(str) + ic() + end + end + end)) end) +end + diff --git a/modules/lib/buffer.lua b/modules/lib/buffer.lua new file mode 100644 index 0000000..d523660 --- /dev/null +++ b/modules/lib/buffer.lua @@ -0,0 +1,33 @@ +_G.buffer = {} +function buffer.create(w,c) -- worker, close + local t={} + t.b="" + function t.w(s,d) + s.b=s.b..TS(d) + end + t.write = t.w + function t.r(s,l) + if type(l) == "number" then + local ns,bs=s.b:sub(1,l+1),s.b:sub(l+2) + s.b=bs + return ns + elseif type(l) == "string" then + local oS=s.b + if l == "*a" then + s.b="" + return oS + elseif l == "*l" then + S=s.b:find("\n") or #s.b + s.b=s.b:sub(S+1) + rS = oS:sub(1,S-1) + if rS:len() < 1 then return nil end + return rS + end + end + end + t.read = t.r + t.close = c + w(t) + return t +end + diff --git a/modules/lib/print.lua b/modules/lib/print.lua new file mode 100644 index 0000000..886adaa --- /dev/null +++ b/modules/lib/print.lua @@ -0,0 +1,10 @@ +function write(...) + for k,v in ipairs({...}) do + event.push("display",os.getenv(sI),tostring(v)) + end +end +function print(...) + for k,v in ipairs({...}) do + write(tostring(v).."\n") + end +end diff --git a/modules/lib/readline.lua b/modules/lib/readline.lua new file mode 100644 index 0000000..9eec54a --- /dev/null +++ b/modules/lib/readline.lua @@ -0,0 +1,17 @@ +function readln(rC) + local s,si="",os.getenv("sI") + while true do + _,sI,c,C = event.pull("key") + if sI == si then + if c == 13 then + write(" \n") + coroutine.yield() + return s + elseif c == 8 then + if s:len()>0 then s=s:sub(1,-2) write("\127") end + elseif c > 31 and c < 127 then + s=s..string.char(c) write((rC or string.char(c))) + end + end + end +end diff --git a/modules/setup.lua b/modules/setup.lua new file mode 100644 index 0000000..34d98d7 --- /dev/null +++ b/modules/setup.lua @@ -0,0 +1,6 @@ +tty(component.list("gpu")(),component.list("screen")()) +log(pcall(function() +local ka = component.list("keyboard")() +kbd(ka) +end)) +luash() diff --git a/modules/tests/dec.lua b/modules/tests/dec.lua new file mode 100644 index 0000000..b654b8f --- /dev/null +++ b/modules/tests/dec.lua @@ -0,0 +1,8 @@ +spawn("test", + function() + for i = 10, 1, -1 do + print(i) + coroutine.yield() + end + end +) diff --git a/modules/tests/inc.lua b/modules/tests/inc.lua new file mode 100644 index 0000000..f14b619 --- /dev/null +++ b/modules/tests/inc.lua @@ -0,0 +1,8 @@ +spawn("test", + function() + for i = 1, 10 do + print(i) + coroutine.yield() + end + end +) diff --git a/strip.lua b/strip.lua new file mode 100644 index 0000000..4428a89 --- /dev/null +++ b/strip.lua @@ -0,0 +1,43 @@ +tA={...} +f=io.open(tA[1]) +ss=f:read("*a") +f:close() +print("Optimising source") +sl=tostring(ss:len()) +no=0 +replacements={ +{" "," "}, +{"\n ","\n"}, +{"\n\n","\n"}, +{" == ","=="}, +{" ~= ","~="}, +{" >= ",">="}, +{" <= ","<="}, +{" > ",">"}, +{" < ","<"}, +{" = ","="}, +{", ",","}, +{" %+ ","+"}, +{" %- ","-"}, +{" %/ ","/"}, +{" %* ","*"}, +{" \n","\n"}, +{"%-%-.-\n",""}, +{"coroutine%.","C."}, +{"table%.","T."}, +{"tostring","TS"}, +{"tonumber","TN"}, +} +for k,v in ipairs(replacements) do + while ss:find(v[1]) ~= nil do + ss=ss:gsub(v[1],v[2]) + io.write(".") + no=no+1 + end +end +print("\nBefore: "..sl.."\nAfter: "..tostring(ss:len()).."\n"..tostring(no).." optimisations made.\n") + +f=io.open(tA[2],"wb") +f:write(ss) +f:close() + diff --git a/wtape.lua b/wtape.lua new file mode 100644 index 0000000..3aebd77 --- /dev/null +++ b/wtape.lua @@ -0,0 +1,12 @@ +tArgs = {...} +component = require "component" +t=component.tape_drive +f=io.open(tArgs[1]) +c=f:read("*a") +f:close() +t.seek(-math.huge) +fh="!"..string.format("%8d",c:len()) +print("Header: "..fh) +t.write(fh) +t.write(c) +t.seek(-math.huge)