mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-19 04:06:43 -04:00
Attempt to fix
This commit is contained in:
parent
7d9eac5584
commit
211b81fdd0
@ -47,11 +47,14 @@ local stats = {
|
||||
}
|
||||
|
||||
local function doSleep()
|
||||
|
||||
local epsilon = 1e-6
|
||||
local deadline = computer.uptime() + (tonumber(options.i) or tonumber(options.interval) or 1)
|
||||
repeat
|
||||
event.pull(deadline - computer.uptime())
|
||||
until computer.uptime() >= deadline
|
||||
local remaining = deadline - computer.uptime()
|
||||
if remaining <= epsilon then break end
|
||||
|
||||
event.pull(math.max(remaining, 0.001))
|
||||
until computer.uptime() >= deadline - epsilon
|
||||
end
|
||||
|
||||
local function doPing()
|
||||
|
@ -25,9 +25,13 @@ end
|
||||
function os.sleep(timeout)
|
||||
checkArg(1, timeout, "number", "nil")
|
||||
local deadline = computer.uptime() + (timeout or 0)
|
||||
local epsilon = 1e-6
|
||||
repeat
|
||||
event.pull(deadline - computer.uptime())
|
||||
until computer.uptime() >= deadline
|
||||
local remaining = deadline - computer.uptime()
|
||||
if remaining <= epsilon then break end
|
||||
|
||||
event.pull(math.max(remaining, 0.001))
|
||||
until computer.uptime() >= deadline - epsilon
|
||||
end
|
||||
|
||||
os.setenv("PATH", "/bin:/usr/bin:/home/bin:.")
|
||||
|
@ -37,11 +37,15 @@ local ipsCount = calcHookInterval()
|
||||
-- Since our IPS might still be too generous (hookInterval needs to run at most
|
||||
-- every 0.05 seconds), we divide it further by 10 relative to that.
|
||||
hookInterval = (ipsCount * 0.005)
|
||||
if hookInterval < 1000 then hookInterval = 1000 end
|
||||
if hookInterval < 1000 then
|
||||
hookInterval = 1000
|
||||
end
|
||||
|
||||
local deadline = math.huge
|
||||
local hitDeadline = false
|
||||
local tooLongWithoutYielding = setmetatable({}, { __tostring = function() return "too long without yielding" end})
|
||||
local tooLongWithoutYielding = setmetatable({}, { __tostring = function()
|
||||
return "too long without yielding"
|
||||
end })
|
||||
local function checkDeadline()
|
||||
if computer.realTime() > deadline then
|
||||
debug.sethook(coroutine.running(), checkDeadline, "", 1)
|
||||
@ -96,8 +100,7 @@ do
|
||||
local SPECIALS = "^$*+?.([%-"
|
||||
local SHORT_STRING = 500 -- use native implementations for short strings
|
||||
|
||||
local string_find, string_lower, string_match, string_gmatch, string_gsub =
|
||||
string.find, string.lower, string.match, string.gmatch, string.gsub
|
||||
local string_find, string_lower, string_match, string_gmatch, string_gsub = string.find, string.lower, string.match, string.gmatch, string.gsub
|
||||
|
||||
local match -- forward declaration
|
||||
|
||||
@ -157,22 +160,45 @@ do
|
||||
}, strptr_mt)
|
||||
end
|
||||
|
||||
local function islower(b) return b >= 'a' and b <= 'z' end
|
||||
local function isupper(b) return b >= 'A' and b <= 'Z' end
|
||||
local function isalpha(b) return islower(b) or isupper(b) end
|
||||
local function iscntrl(b) return b <= '\007' or (b >= '\010' and b <= '\017') or (b >= '\020' and b <= '\027') or (b >= '\030' and b <= '\037' and b ~= ' ') or b == '\177' end
|
||||
local function isdigit(b) return b >= '0' and b <= '9' end
|
||||
local function ispunct(b) return (b >= '{' and b <= '~') or (b == '`') or (b >= '[' and b <= '_') or (b == '@') or (b >= ':' and b <= '?') or (b >= '(' and b <= '/') or (b >= '!' and b <= '\'') end
|
||||
local function isspace(b) return b == '\t' or b == '\n' or b == '\v' or b == '\f' or b == '\r' or b == ' ' end
|
||||
local function isalnum(b) return isalpha(b) or isdigit(b) end
|
||||
local function isxdigit(b) return isdigit(b) or (b >= 'a' and b <= 'f') or (b >= 'A' and b <= 'F') end
|
||||
local function isgraph(b) return not iscntrl(b) and not isspace(b) end
|
||||
local function islower(b)
|
||||
return b >= 'a' and b <= 'z'
|
||||
end
|
||||
local function isupper(b)
|
||||
return b >= 'A' and b <= 'Z'
|
||||
end
|
||||
local function isalpha(b)
|
||||
return islower(b) or isupper(b)
|
||||
end
|
||||
local function iscntrl(b)
|
||||
return b <= '\007' or (b >= '\010' and b <= '\017') or (b >= '\020' and b <= '\027') or (b >= '\030' and b <= '\037' and b ~= ' ') or b == '\177'
|
||||
end
|
||||
local function isdigit(b)
|
||||
return b >= '0' and b <= '9'
|
||||
end
|
||||
local function ispunct(b)
|
||||
return (b >= '{' and b <= '~') or (b == '`') or (b >= '[' and b <= '_') or (b == '@') or (b >= ':' and b <= '?') or (b >= '(' and b <= '/') or (b >= '!' and b <= '\'')
|
||||
end
|
||||
local function isspace(b)
|
||||
return b == '\t' or b == '\n' or b == '\v' or b == '\f' or b == '\r' or b == ' '
|
||||
end
|
||||
local function isalnum(b)
|
||||
return isalpha(b) or isdigit(b)
|
||||
end
|
||||
local function isxdigit(b)
|
||||
return isdigit(b) or (b >= 'a' and b <= 'f') or (b >= 'A' and b <= 'F')
|
||||
end
|
||||
local function isgraph(b)
|
||||
return not iscntrl(b) and not isspace(b)
|
||||
end
|
||||
|
||||
-- translate a relative string position: negative means back from end
|
||||
local function posrelat(pos, len)
|
||||
if pos >= 0 then return pos
|
||||
elseif -pos > len then return 0
|
||||
else return len + pos + 1
|
||||
if pos >= 0 then
|
||||
return pos
|
||||
elseif -pos > len then
|
||||
return 0
|
||||
else
|
||||
return len + pos + 1
|
||||
end
|
||||
end
|
||||
|
||||
@ -196,7 +222,8 @@ do
|
||||
end
|
||||
|
||||
local function classend(ms, p)
|
||||
local p0 = p:char() p = p:copy(1)
|
||||
local p0 = p:char()
|
||||
p = p:copy(1)
|
||||
if p0 == L_ESC then
|
||||
if p == ms.p_end then
|
||||
error("malformed pattern (ends with %)")
|
||||
@ -226,21 +253,35 @@ do
|
||||
local function match_class(c, cl)
|
||||
local res
|
||||
local cll = string_lower(cl)
|
||||
if cll == 'a' then res = isalpha(c)
|
||||
elseif cll == 'c' then res = iscntrl(c)
|
||||
elseif cll == 'd' then res = isdigit(c)
|
||||
elseif cll == 'g' then res = isgraph(c)
|
||||
elseif cll == 'l' then res = islower(c)
|
||||
elseif cll == 'p' then res = ispunct(c)
|
||||
elseif cll == 's' then res = isspace(c)
|
||||
elseif cll == 'u' then res = isupper(c)
|
||||
elseif cll == 'w' then res = isalnum(c)
|
||||
elseif cll == 'x' then res = isxdigit(c)
|
||||
elseif cll == 'z' then res = c == '\0' -- deprecated option
|
||||
else return cl == c
|
||||
if cll == 'a' then
|
||||
res = isalpha(c)
|
||||
elseif cll == 'c' then
|
||||
res = iscntrl(c)
|
||||
elseif cll == 'd' then
|
||||
res = isdigit(c)
|
||||
elseif cll == 'g' then
|
||||
res = isgraph(c)
|
||||
elseif cll == 'l' then
|
||||
res = islower(c)
|
||||
elseif cll == 'p' then
|
||||
res = ispunct(c)
|
||||
elseif cll == 's' then
|
||||
res = isspace(c)
|
||||
elseif cll == 'u' then
|
||||
res = isupper(c)
|
||||
elseif cll == 'w' then
|
||||
res = isalnum(c)
|
||||
elseif cll == 'x' then
|
||||
res = isxdigit(c)
|
||||
elseif cll == 'z' then
|
||||
res = c == '\0' -- deprecated option
|
||||
else
|
||||
return cl == c
|
||||
end
|
||||
if islower(cl) then return res
|
||||
else return not res
|
||||
if islower(cl) then
|
||||
return res
|
||||
else
|
||||
return not res
|
||||
end
|
||||
end
|
||||
|
||||
@ -275,10 +316,14 @@ do
|
||||
return false
|
||||
end
|
||||
local p0 = p:char()
|
||||
if p0 == '.' then return true -- matches any char
|
||||
elseif p0 == L_ESC then return match_class(s:char(), p:char(1))
|
||||
elseif p0 == '[' then return matchbracketclass(s:char(), p, ep:copy(-1))
|
||||
else return p:char() == s:char()
|
||||
if p0 == '.' then
|
||||
return true -- matches any char
|
||||
elseif p0 == L_ESC then
|
||||
return match_class(s:char(), p:char(1))
|
||||
elseif p0 == '[' then
|
||||
return matchbracketclass(s:char(), p, ep:copy(-1))
|
||||
else
|
||||
return p:char() == s:char()
|
||||
end
|
||||
end
|
||||
|
||||
@ -286,7 +331,9 @@ do
|
||||
if p >= ms.p_end - 1 then
|
||||
error("malformed pattern (missing arguments to %b)")
|
||||
end
|
||||
if s:char() ~= p:char() then return nil end
|
||||
if s:char() ~= p:char() then
|
||||
return nil
|
||||
end
|
||||
local b = p:char()
|
||||
local e = p:char(1)
|
||||
local cont = 1
|
||||
@ -294,7 +341,9 @@ do
|
||||
while s:step() < ms.src_end do
|
||||
if s:char() == e then
|
||||
cont = cont - 1
|
||||
if cont == 0 then return s:step() end
|
||||
if cont == 0 then
|
||||
return s:step()
|
||||
end
|
||||
elseif s:char() == b then
|
||||
cont = cont + 1
|
||||
end
|
||||
@ -310,7 +359,9 @@ do
|
||||
-- keeps trying to match with the maximum repetitions
|
||||
while i >= 0 do
|
||||
local res = match(ms, s:copy(i), ep:copy(1))
|
||||
if res then return res end
|
||||
if res then
|
||||
return res
|
||||
end
|
||||
i = i - 1 -- else didn't match; reduce 1 repetition to try again
|
||||
end
|
||||
return nil
|
||||
@ -324,7 +375,8 @@ do
|
||||
return res
|
||||
elseif singlematch(ms, s, p, ep) then
|
||||
s:step() -- try with one more repetition
|
||||
else return nil
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -336,7 +388,8 @@ do
|
||||
ms.capture[level].len = what
|
||||
ms.level = level + 1
|
||||
local res = match(ms, s, p)
|
||||
if res == nil then -- match failed?
|
||||
if res == nil then
|
||||
-- match failed?
|
||||
ms.level = ms.level - 1 -- undo capture
|
||||
end
|
||||
return res
|
||||
@ -346,7 +399,8 @@ do
|
||||
local l = capture_to_close(ms)
|
||||
ms.capture[l].len = s - ms.capture[l].init -- close capture
|
||||
local res = match(ms, s, p)
|
||||
if res == nil then -- match failed?
|
||||
if res == nil then
|
||||
-- match failed?
|
||||
ms.capture[l].len = CAP_UNFINISHED -- undo capture
|
||||
end
|
||||
return res
|
||||
@ -359,7 +413,8 @@ do
|
||||
ms.capture[l].init:head(len) == s:head(len)
|
||||
then
|
||||
return s:copy(len)
|
||||
else return nil
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
@ -369,32 +424,39 @@ do
|
||||
:: init :: -- using goto's to optimize tail recursion
|
||||
if p ~= ms.p_end then
|
||||
local p0 = p:char()
|
||||
if p0 == '(' then -- start capture
|
||||
if p:char(1) == ')' then -- position capture?
|
||||
if p0 == '(' then
|
||||
-- start capture
|
||||
if p:char(1) == ')' then
|
||||
-- position capture?
|
||||
s = start_capture(ms, s, p:copy(2), CAP_POSITION)
|
||||
else
|
||||
s = start_capture(ms, s, p:copy(1), CAP_UNFINISHED)
|
||||
end
|
||||
goto brk
|
||||
elseif p0 == ')' then -- end capture
|
||||
elseif p0 == ')' then
|
||||
-- end capture
|
||||
s = end_capture(ms, s, p:copy(1))
|
||||
goto brk
|
||||
elseif p0 == '$' then
|
||||
if p + 1 ~= ms.p_end then -- is the `$' the last char in pattern?
|
||||
if p + 1 ~= ms.p_end then
|
||||
-- is the `$' the last char in pattern?
|
||||
goto dflt -- no; go to default
|
||||
end
|
||||
s = (s == ms.src_end) and s or nil -- check end of string
|
||||
goto brk
|
||||
elseif p0 == L_ESC then -- escaped sequences not in the format class[*+?-]?
|
||||
elseif p0 == L_ESC then
|
||||
-- escaped sequences not in the format class[*+?-]?
|
||||
local p1 = p:char(1)
|
||||
if p1 == 'b' then -- balanced string?
|
||||
if p1 == 'b' then
|
||||
-- balanced string?
|
||||
s = matchbalance(ms, s, p:copy(2))
|
||||
if s ~= nil then
|
||||
p:step(4)
|
||||
goto init -- return match(ms, s, p + 4)
|
||||
end
|
||||
-- else fail (s == nil)
|
||||
elseif p1 == 'f' then -- frontier?
|
||||
elseif p1 == 'f' then
|
||||
-- frontier?
|
||||
p:step(2)
|
||||
if p:char() ~= '[' then
|
||||
error("missing [ after %f in pattern")
|
||||
@ -408,7 +470,8 @@ do
|
||||
goto init -- return match(ms, s, ep)
|
||||
end
|
||||
s = nil -- match failed
|
||||
elseif isdigit(p:char(1)) then -- capture results (%0-%9)?
|
||||
elseif isdigit(p:char(1)) then
|
||||
-- capture results (%0-%9)?
|
||||
s = match_capture(ms, s, p:char(1))
|
||||
if s ~= nil then
|
||||
p:step(2)
|
||||
@ -419,18 +482,23 @@ do
|
||||
end
|
||||
goto brk
|
||||
end
|
||||
::dflt:: do
|
||||
:: dflt ::
|
||||
do
|
||||
local ep = classend(ms, p) -- points to what is next
|
||||
local ep0 = ep:char()
|
||||
if not singlematch(ms, s, p, ep) then
|
||||
if ep0 == '*' or ep0 == '?' or ep0 == '-' then -- accept empty?
|
||||
if ep0 == '*' or ep0 == '?' or ep0 == '-' then
|
||||
-- accept empty?
|
||||
p = ep:copy(1)
|
||||
goto init -- return match(ms, s, ep + 1)
|
||||
else -- '+' or no suffix
|
||||
else
|
||||
-- '+' or no suffix
|
||||
s = nil -- fail
|
||||
end
|
||||
else -- matched once
|
||||
if ep0 == '?' then -- optional
|
||||
else
|
||||
-- matched once
|
||||
if ep0 == '?' then
|
||||
-- optional
|
||||
local res = match(ms, s:copy(1), ep:copy(1))
|
||||
if res ~= nil then
|
||||
s = res
|
||||
@ -438,11 +506,14 @@ do
|
||||
p = ep:copy(1)
|
||||
goto init -- else return match(ms, s, ep + 1)
|
||||
end
|
||||
elseif ep0 == '+' then -- 1 or more repetitions
|
||||
elseif ep0 == '+' then
|
||||
-- 1 or more repetitions
|
||||
s = max_expand(ms, s:copy(1), p, ep) -- 1 match already done
|
||||
elseif ep0 == '*' then -- 0 or more repetitions
|
||||
elseif ep0 == '*' then
|
||||
-- 0 or more repetitions
|
||||
s = max_expand(ms, s, p, ep)
|
||||
elseif ep0 == '-' then -- 0 or more repetitions (minimum)
|
||||
elseif ep0 == '-' then
|
||||
-- 0 or more repetitions (minimum)
|
||||
s = min_expand(ms, s, p, ep)
|
||||
else
|
||||
s:step()
|
||||
@ -458,14 +529,17 @@ do
|
||||
|
||||
local function push_onecapture(ms, i, s, e)
|
||||
if i >= ms.level then
|
||||
if i == 0 then -- ms->level == 0, too
|
||||
if i == 0 then
|
||||
-- ms->level == 0, too
|
||||
return s:head(e - s) -- add whole match
|
||||
else
|
||||
error("invalid capture index")
|
||||
end
|
||||
else
|
||||
local l = ms.capture[i].len;
|
||||
if l == CAP_UNFINISHED then error("unfinished capture") end
|
||||
if l == CAP_UNFINISHED then
|
||||
error("unfinished capture")
|
||||
end
|
||||
if l == CAP_POSITION then
|
||||
return ms.capture[i].init - ms.src_init + 1
|
||||
else
|
||||
@ -507,8 +581,10 @@ do
|
||||
local s = strptr(str)
|
||||
local p = strptr(pattern)
|
||||
local init = posrelat(init or 1, #str)
|
||||
if init < 1 then init = 1
|
||||
elseif init > #str + 1 then -- start after string's end?
|
||||
if init < 1 then
|
||||
init = 1
|
||||
elseif init > #str + 1 then
|
||||
-- start after string's end?
|
||||
return nil -- cannot find anything
|
||||
end
|
||||
-- explicit request or no special characters?
|
||||
@ -521,7 +597,9 @@ do
|
||||
else
|
||||
local s1 = s:copy(init - 1)
|
||||
local anchor = p:char() == '^'
|
||||
if anchor then p:step() end
|
||||
if anchor then
|
||||
p:step()
|
||||
end
|
||||
local ms = {
|
||||
src_init = s,
|
||||
src_end = s:copy(s:len()),
|
||||
@ -564,9 +642,13 @@ do
|
||||
checkArg(3, init, "number", "nil")
|
||||
if init ~= nil then
|
||||
start = posrelat(init, #s)
|
||||
if start < 1 then start = 0
|
||||
elseif start > #s + 1 then start = #s + 1
|
||||
else start = start - 1 end
|
||||
if start < 1 then
|
||||
start = 0
|
||||
elseif start > #s + 1 then
|
||||
start = #s + 1
|
||||
else
|
||||
start = start - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -585,7 +667,9 @@ do
|
||||
local e = match(ms, src, p)
|
||||
if e ~= nil then
|
||||
local newstart = e - s
|
||||
if e == src then newstart = newstart + 1 end -- empty match? go at least one position
|
||||
if e == src then
|
||||
newstart = newstart + 1
|
||||
end -- empty match? go at least one position
|
||||
start = newstart
|
||||
return push_captures(ms, src, e)
|
||||
end
|
||||
@ -621,10 +705,12 @@ do
|
||||
res = r(push_captures(ms, s, e))
|
||||
elseif tr == "table" then
|
||||
res = r[push_onecapture(ms, 0, s, e)]
|
||||
else -- LUA_TNUMBER or LUA_TSTRING
|
||||
else
|
||||
-- LUA_TNUMBER or LUA_TSTRING
|
||||
return add_s(ms, b, s, e, r)
|
||||
end
|
||||
if not res then -- nil or false?
|
||||
if not res then
|
||||
-- nil or false?
|
||||
res = s:head(e - s) -- keep original text
|
||||
elseif type(res) ~= "string" and type(res) ~= "number" then
|
||||
error("invalid replacement value (a " .. type(res) .. ")")
|
||||
@ -666,14 +752,18 @@ do
|
||||
n = n + 1
|
||||
b = add_value(ms, b, src, e, repl, tr)
|
||||
end
|
||||
if e and e > src then -- non empty match?
|
||||
if e and e > src then
|
||||
-- non empty match?
|
||||
src = e -- skip it
|
||||
elseif src < ms.src_end then
|
||||
b = b .. src:char()
|
||||
src:step()
|
||||
else break
|
||||
else
|
||||
break
|
||||
end
|
||||
if anchor then
|
||||
break
|
||||
end
|
||||
if anchor then break end
|
||||
end
|
||||
b = b .. src:head()
|
||||
return b, n -- number of substitutions
|
||||
@ -740,7 +830,8 @@ sandbox = {
|
||||
error = error,
|
||||
_G = nil, -- see below
|
||||
getmetatable = function(t)
|
||||
if type(t) == "string" then -- don't allow messing with the string mt
|
||||
if type(t) == "string" then
|
||||
-- don't allow messing with the string mt
|
||||
return nil
|
||||
end
|
||||
local result = getmetatable(t)
|
||||
@ -763,7 +854,9 @@ sandbox = {
|
||||
pcall = function(...)
|
||||
-- prevent infinite pcall() loops by checking deadline before pcall()
|
||||
local status, err = pcall(checkDeadline)
|
||||
if not status then return false, err end
|
||||
if not status then
|
||||
return false, err
|
||||
end
|
||||
|
||||
return pcallTimeoutCheck(pcall(...))
|
||||
end,
|
||||
@ -777,7 +870,8 @@ sandbox = {
|
||||
if type(mt) ~= "table" then
|
||||
return setmetatable(t, mt)
|
||||
end
|
||||
if rawget(mt, "__gc") ~= nil then -- If __gc is set to ANYTHING not `nil`, we're gonna have issues
|
||||
if rawget(mt, "__gc") ~= nil then
|
||||
-- If __gc is set to ANYTHING not `nil`, we're gonna have issues
|
||||
-- Garbage collector callbacks apparently can't be sandboxed after
|
||||
-- all, because hooks are disabled while they're running. So we just
|
||||
-- disable them altogether by default.
|
||||
@ -800,7 +894,9 @@ sandbox = {
|
||||
rawset(mt, "__gc", nil) -- remove __gc
|
||||
local ret = table.pack(pcall(setmetatable, t, mt))
|
||||
rawset(mt, "__gc", gc) -- restore __gc
|
||||
if not ret[1] then error(ret[2], 0) end
|
||||
if not ret[1] then
|
||||
error(ret[2], 0)
|
||||
end
|
||||
return table.unpack(ret, 2, ret.n)
|
||||
end
|
||||
end
|
||||
@ -818,7 +914,9 @@ sandbox = {
|
||||
errorCapture = function(ff, ...)
|
||||
-- prevent infinite xpcall() loops by checking deadline before xpcall()
|
||||
local status, err = pcall(checkDeadline)
|
||||
if not status then return false, err end
|
||||
if not status then
|
||||
return false, err
|
||||
end
|
||||
|
||||
return xpcall(ff, function(...)
|
||||
if rawequal((...), tooLongWithoutYielding) then
|
||||
@ -840,31 +938,39 @@ sandbox = {
|
||||
|
||||
coroutine = {
|
||||
create = coroutine.create,
|
||||
resume = function(co, ...) -- custom resume part for bubbling sysyields
|
||||
resume = function(co, ...)
|
||||
-- custom resume part for bubbling sysyields
|
||||
checkArg(1, co, "thread")
|
||||
local args = table.pack(...)
|
||||
while true do -- for consecutive sysyields
|
||||
while true do
|
||||
-- for consecutive sysyields
|
||||
debug.sethook(co, checkDeadline, "", hookInterval)
|
||||
local result = table.pack(
|
||||
coroutine.resume(co, table.unpack(args, 1, args.n)))
|
||||
debug.sethook(co) -- avoid gc issues
|
||||
checkDeadline()
|
||||
if result[1] then -- success: (true, sysval?, ...?)
|
||||
if coroutine.status(co) == "dead" then -- return: (true, ...)
|
||||
if result[1] then
|
||||
-- success: (true, sysval?, ...?)
|
||||
if coroutine.status(co) == "dead" then
|
||||
-- return: (true, ...)
|
||||
return true, table.unpack(result, 2, result.n)
|
||||
elseif result[2] ~= nil then -- yield: (true, sysval)
|
||||
elseif result[2] ~= nil then
|
||||
-- yield: (true, sysval)
|
||||
args = table.pack(coroutine.yield(result[2]))
|
||||
else -- yield: (true, nil, ...)
|
||||
else
|
||||
-- yield: (true, nil, ...)
|
||||
return true, table.unpack(result, 3, result.n)
|
||||
end
|
||||
else -- error: result = (false, string)
|
||||
else
|
||||
-- error: result = (false, string)
|
||||
return false, result[2]
|
||||
end
|
||||
end
|
||||
end,
|
||||
running = coroutine.running,
|
||||
status = coroutine.status,
|
||||
wrap = function(f) -- for bubbling coroutine.resume
|
||||
wrap = function(f)
|
||||
-- for bubbling coroutine.resume
|
||||
local co = coroutine.create(f)
|
||||
return function(...)
|
||||
local result = table.pack(sandbox.coroutine.resume(co, ...))
|
||||
@ -875,7 +981,8 @@ sandbox = {
|
||||
end
|
||||
end
|
||||
end,
|
||||
yield = function(...) -- custom yield part for bubbling sysyields
|
||||
yield = function(...)
|
||||
-- custom yield part for bubbling sysyields
|
||||
return coroutine.yield(nil, ...)
|
||||
end,
|
||||
-- Lua 5.3.
|
||||
@ -929,7 +1036,8 @@ sandbox = {
|
||||
fmod = math.fmod,
|
||||
frexp = math.frexp, -- Deprecated in Lua 5.3
|
||||
huge = math.huge,
|
||||
ldexp = math.ldexp or function(a, e) -- Deprecated in Lua 5.3
|
||||
ldexp = math.ldexp or function(a, e)
|
||||
-- Deprecated in Lua 5.3
|
||||
return a * (2.0 ^ e)
|
||||
end,
|
||||
log = math.log,
|
||||
@ -937,7 +1045,8 @@ sandbox = {
|
||||
min = math.min,
|
||||
modf = math.modf,
|
||||
pi = math.pi,
|
||||
pow = math.pow or function(a, b) -- Deprecated in Lua 5.3
|
||||
pow = math.pow or function(a, b)
|
||||
-- Deprecated in Lua 5.3
|
||||
return a ^ b
|
||||
end,
|
||||
rad = math.rad,
|
||||
@ -1025,8 +1134,12 @@ sandbox = {
|
||||
-- e.g. (1, 2) is only (1), the 2 is not returned
|
||||
-- this is critically important here because the 2nd return value from these
|
||||
-- debug methods is the value itself, which opens a door to exploit the sandbox
|
||||
getlocal = function(...) return (debug.getlocal(...)) end,
|
||||
getupvalue = function(...) return (debug.getupvalue(...)) end,
|
||||
getlocal = function(...)
|
||||
return (debug.getlocal(...))
|
||||
end,
|
||||
getupvalue = function(...)
|
||||
return (debug.getupvalue(...))
|
||||
end,
|
||||
},
|
||||
|
||||
-- Lua 5.3.
|
||||
@ -1070,9 +1183,11 @@ local wrappedUserdata = setmetatable({}, wrappedUserdataMeta)
|
||||
|
||||
local function processResult(result)
|
||||
result = wrapUserdata(result) -- needed for metamethods.
|
||||
if not result[1] then -- error that should be re-thrown.
|
||||
if not result[1] then
|
||||
-- error that should be re-thrown.
|
||||
error(result[2], 0)
|
||||
else -- success or already processed error.
|
||||
else
|
||||
-- success or already processed error.
|
||||
return table.unpack(result, 2, result.n)
|
||||
end
|
||||
end
|
||||
@ -1084,7 +1199,8 @@ local function invoke(target, direct, ...)
|
||||
args = unwrapUserdata(args)
|
||||
result = table.pack(target.invoke(table.unpack(args, 1, args.n)))
|
||||
args = nil -- clear upvalue, avoids trying to persist it
|
||||
if result.n == 0 then -- limit for direct calls reached
|
||||
if result.n == 0 then
|
||||
-- limit for direct calls reached
|
||||
result = nil
|
||||
end
|
||||
-- no need to wrap here, will be wrapped in processResult
|
||||
@ -1411,14 +1527,17 @@ local libcomputer = {
|
||||
return spcall(computer.pushSignal, ...)
|
||||
end,
|
||||
pullSignal = function(timeout)
|
||||
local deadline = computer.uptime() +
|
||||
(type(timeout) == "number" and timeout or math.huge)
|
||||
local epsilon = 1e-6
|
||||
local deadline = computer.uptime() + (type(timeout) == "number" and timeout or math.huge)
|
||||
repeat
|
||||
local signal = table.pack(coroutine.yield(deadline - computer.uptime()))
|
||||
local remaining = deadline - computer.uptime()
|
||||
if remaining <= epsilon then break end
|
||||
|
||||
local signal = table.pack(coroutine.yield(math.max(remaining, 0.001)))
|
||||
if signal.n > 0 then
|
||||
return table.unpack(signal, 1, signal.n)
|
||||
end
|
||||
until computer.uptime() >= deadline
|
||||
until computer.uptime() >= deadline - epsilon
|
||||
end,
|
||||
|
||||
beep = function(...)
|
||||
@ -1520,7 +1639,8 @@ local function main()
|
||||
|
||||
-- NOTE: since this is run in an executor thread and we enforce timeouts
|
||||
-- in user-defined garbage collector callbacks this should be safe.
|
||||
if persistKey then -- otherwise we're in LuaJ
|
||||
if persistKey then
|
||||
-- otherwise we're in LuaJ
|
||||
forceGC = forceGC - 1
|
||||
if forceGC < 1 then
|
||||
collectgarbage("collect")
|
||||
|
Loading…
x
Reference in New Issue
Block a user