| @@ -0,0 +1,126 @@ | ||
|
|
||
|
|
||
| function juno.onLoad(dt) | ||
| G.field = juno.Buffer.fromBlank(G.width, G.height) | ||
| G.field:drawBox(0, 0, G.width, G.height) | ||
| G.tickTimer = 0 | ||
| -- Initialise player | ||
| G.player = { | ||
| x = 20, | ||
| y = G.height / 2, | ||
| direction = "down", | ||
| color = { 1, 1, 1 }, | ||
| } | ||
| -- Initialise AIs | ||
| G.ai = {} | ||
| for i = 1, 3 do | ||
| table.insert(G.ai, { | ||
| x = ((G.width - 40) / 3) * i + 20, | ||
| y = G.height / 2, | ||
| dead = false, | ||
| direction = "down", | ||
| turnTimer = 0, | ||
| turnRate = 10 + math.random(20), | ||
| color = ({ { 1, 0, 0 }, { 0, 1, 1 }, { 1, 1, 0 } })[i], | ||
| }) | ||
| end | ||
| end | ||
|
|
||
|
|
||
| function juno.onKeyDown(k) | ||
| -- Handle player movement keys | ||
| if k == "left" or k == "up" or k == "down" or k == "right" then | ||
| G.player.direction = k | ||
| end | ||
| -- Handle game restart key | ||
| if k == "r" then | ||
| juno.onLoad() | ||
| end | ||
| end | ||
|
|
||
|
|
||
| local function isPixelBlack(x, y) | ||
| local r, g, b = G.field:getPixel(x, y) | ||
| return r == 0 and g == 0 and b == 0 | ||
| end | ||
|
|
||
|
|
||
| local function nextPosition(bike, steps) | ||
| steps = steps or 1 | ||
| return ({ | ||
| left = function() return bike.x - steps, bike.y end, | ||
| right = function() return bike.x + steps, bike.y end, | ||
| up = function() return bike.x, bike.y - steps end, | ||
| down = function() return bike.x, bike.y + steps end, | ||
| })[bike.direction]() | ||
| end | ||
|
|
||
|
|
||
| local function randomDirection() | ||
| return ({ "left", "right", "up", "down" })[math.random(4)] | ||
| end | ||
|
|
||
|
|
||
| local function updateAi(ai, dt) | ||
| -- Do random turn timer and random turn | ||
| ai.turnTimer = ai.turnTimer - 1 | ||
| if ai.turnTimer <= 0 then | ||
| ai.turnTimer = math.random(ai.turnRate) | ||
| ai.direction = randomDirection() | ||
| end | ||
| -- Do obstacle avoidance | ||
| for lookahead = 4, 1, -1 do | ||
| for i = 1, 8 do | ||
| if not isPixelBlack(nextPosition(ai, lookahead)) then | ||
| ai.direction = randomDirection() | ||
| end | ||
| end | ||
| end | ||
| end | ||
|
|
||
|
|
||
| local function updateBike(bike) | ||
| -- Don't update the bike if its dead | ||
| if bike.dead then | ||
| return | ||
| end | ||
| -- Move bike | ||
| bike.x, bike.y = nextPosition(bike) | ||
| -- Kill the bike if it collided with something | ||
| if not isPixelBlack(bike.x, bike.y) then | ||
| bike.dead = true | ||
| return | ||
| end | ||
| -- Draw bike | ||
| G.field:setPixel(bike.x, bike.y, unpack(bike.color)) | ||
| end | ||
|
|
||
|
|
||
| local function onTick() | ||
| -- Update AIs | ||
| for i, ai in ipairs(G.ai) do | ||
| updateAi(ai) | ||
| updateBike(ai) | ||
| end | ||
| -- Update player | ||
| updateBike(G.player) | ||
| end | ||
|
|
||
|
|
||
| function juno.onUpdate(dt) | ||
| -- Update tick timer | ||
| G.tickTimer = G.tickTimer - dt | ||
| while G.tickTimer <= 0 do | ||
| onTick() | ||
| G.tickTimer = G.tickTimer + .03 | ||
| end | ||
| -- Player is dead? Restart the game | ||
| if G.player.dead then | ||
| juno.onLoad() | ||
| end | ||
| end | ||
|
|
||
|
|
||
| function juno.onDraw() | ||
| juno.graphics.copyPixels(G.field, 0, 0, nil, G.scale) | ||
| end |
| @@ -0,0 +1,71 @@ | ||
| -- | ||
| -- Copyright (c) 2015 rxi | ||
| -- | ||
| -- This library is free software; you can redistribute it and/or modify it | ||
| -- under the terms of the MIT license. See LICENSE for details. | ||
| -- | ||
|
|
||
|
|
||
| local function checkArg(idx, cond, msg) | ||
| if not cond then | ||
| error("bad argument #" .. idx .. ", " .. msg, 3) | ||
| end | ||
| end | ||
|
|
||
|
|
||
| function juno.Buffer:getSize() | ||
| return self:getWidth(), self:getHeight() | ||
| end | ||
|
|
||
|
|
||
| local defaultFont = juno.Font.fromEmbedded() | ||
|
|
||
| local fontTexCache = {} | ||
| setmetatable(fontTexCache, { | ||
| __index = function(t, k) | ||
| fontTexCache[k] = {} | ||
| return fontTexCache[k] | ||
| end, | ||
| __mode = "v", | ||
| }) | ||
|
|
||
| function juno.Buffer:drawText(font, text, x, y, width) | ||
| if type(font) ~= "userdata" then | ||
| return self:drawText(defaultFont, font, text, x, y, width) | ||
| end | ||
| checkArg(3, x == nil or type(x) == "number", "expected number") | ||
| checkArg(4, y == nil or type(y) == "number", "expected number") | ||
| checkArg(5, width == nil or type(width) == "number", "expected number") | ||
| text = tostring(text) | ||
| if width then | ||
| -- Word wrapped multi line | ||
| local height = font:getHeight() | ||
| local line | ||
| for word in text:gmatch("%S+") do | ||
| local tmp = (line and (line .. " ") or "") .. word | ||
| if font:getWidth(tmp) > width then | ||
| juno.graphics.drawText(font, line, x, y) | ||
| y = y + height | ||
| line = word | ||
| else | ||
| line = tmp | ||
| end | ||
| end | ||
| self:drawText(font, line, x, y) | ||
| elseif text:find("\n") then | ||
| -- Multi line | ||
| local height = font:getHeight() | ||
| for line in (text.."\n"):gmatch("(.-)\n") do | ||
| self:drawText(font, line, x, y) | ||
| y = y + height | ||
| end | ||
| else | ||
| -- Single line | ||
| local tex = fontTexCache[font][text] | ||
| if not tex then | ||
| tex = font:render(text) | ||
| fontTexCache[font][text] = tex | ||
| end | ||
| self:drawBuffer(tex, x, y) | ||
| end | ||
| end |
| @@ -0,0 +1,246 @@ | ||
| -- | ||
| -- Copyright (c) 2015 rxi | ||
| -- | ||
| -- This library is free software; you can redistribute it and/or modify it | ||
| -- under the terms of the MIT license. See LICENSE for details. | ||
| -- | ||
|
|
||
|
|
||
| juno.debug = juno.debug or {} | ||
|
|
||
| local font | ||
| local inited = false | ||
| local enabled = false | ||
| local focused = false | ||
| local indicators = {} | ||
| local lines = {} | ||
| local inputbuf = "" | ||
|
|
||
| -- Override print | ||
| local _print = print | ||
| print = function(...) | ||
| _print(...) | ||
| -- Convert all arguments to string and store in table | ||
| local t = {} | ||
| for i = 1, select("#", ...) do | ||
| t[#t + 1] = tostring(select(i, ...)) | ||
| end | ||
| local str = table.concat(t, " ") | ||
| -- Multiple lines? Split and insert, else just insert the string | ||
| if str:match("\n") then | ||
| for line in (str .. "\n"):gmatch("(.-)\n") do | ||
| table.insert(lines, line) | ||
| end | ||
| else | ||
| table.insert(lines, str) | ||
| end | ||
| while #lines > 6 do | ||
| table.remove(lines, 1) | ||
| end | ||
| end | ||
|
|
||
|
|
||
| local indicatorIdx | ||
| local textRegionWidth = 20 | ||
|
|
||
| local function newIndicator(fn, min, max) | ||
| min = min or 0 | ||
| max = max or 0 | ||
| local trueMin, trueMax = min, max | ||
| -- Get idx | ||
| indicatorIdx = indicatorIdx and (indicatorIdx + 1) or 0 | ||
| -- Init | ||
| local pad = 8 | ||
| local height = 26 | ||
| local maxBars = 16 | ||
| local barUpdatePeriod = 1 | ||
| local yoffset = pad + height * indicatorIdx | ||
| local lastUpdate = juno.time.getNow() | ||
| local bars = {} | ||
| local lastMin = min | ||
| local lastMax = max | ||
| -- Fill bars with zeros | ||
| for i = 1, maxBars do | ||
| bars[i] = 0 | ||
| end | ||
| -- Return draw function | ||
| return function() | ||
| local txt, val = fn() | ||
| -- Resize text region? | ||
| textRegionWidth = math.max(font:getWidth(txt) + 8, textRegionWidth) | ||
| -- Update bars? | ||
| if juno.time.getNow() > lastUpdate + barUpdatePeriod then | ||
| table.remove(bars) | ||
| table.insert(bars, 1, val) | ||
| min = math.min(trueMin, unpack(bars)) | ||
| max = math.max(trueMax, unpack(bars)) | ||
| lastUpdate = juno.time.getNow() | ||
| end | ||
| -- Draw text | ||
| local w = textRegionWidth | ||
| juno.graphics.drawRect(pad / 2, yoffset - (pad / 2), | ||
| w, height - 1, 0, 0, 0, .8) | ||
| juno.graphics.drawText(font, txt, pad, yoffset) | ||
| -- Draw bars | ||
| juno.graphics.drawRect(pad / 2 + w + 1, yoffset - (pad / 2), | ||
| 73, height - 1, 0, 0, 0, .8) | ||
| for i, v in ipairs(bars) do | ||
| local x = math.floor((bars[i] - min) / (max - min) * 16) | ||
| juno.graphics.drawRect(pad / 2 + w + 1 + (i - 1) * 4 + 5, | ||
| yoffset + 16 - x, 3, x, | ||
| nil, nil, nil, (i == 1) and 1 or .4) | ||
| end | ||
| end | ||
| end | ||
|
|
||
|
|
||
| local function draw() | ||
| -- Not enabled? Don't draw | ||
| if not enabled then | ||
| return | ||
| end | ||
| -- Draw | ||
| juno.graphics.reset() | ||
| -- Draw indicators | ||
| for i, v in ipairs(indicators) do | ||
| v() | ||
| end | ||
| -- Draw console input text | ||
| local w = 300 | ||
| if focused then | ||
| local h = font:getHeight() | ||
| local y = juno.graphics.getHeight() - 8 - h | ||
| local caret = (juno.time.getTime() % .6 < .3) and "_" or "" | ||
| w = math.max(w, font:getWidth(inputbuf .. "_")) | ||
| juno.graphics.drawRect(4, juno.graphics.getHeight() - h - 12, | ||
| w + 8, h + 8, | ||
| 0, 0, 0, .8) | ||
| juno.graphics.drawText(font, inputbuf .. caret, 8, y) | ||
| end | ||
| -- Draw console output text | ||
| if #lines > 0 then | ||
| local h = font:getHeight() | ||
| local rh = #lines * h + 8 | ||
| local oy = focused and (h + 9) or 0 | ||
| for i, v in ipairs(lines) do | ||
| w = math.max(w, font:getWidth(v)) | ||
| end | ||
| juno.graphics.drawRect(4, juno.graphics.getHeight() - 4 - rh - oy, | ||
| w + 8, rh, | ||
| 0, 0, 0, .8) | ||
| for i, v in ipairs(lines) do | ||
| local y = juno.graphics.getHeight() - 8 - (#lines - i + 1) * h | ||
| juno.graphics.drawText(font, v, 8, y - oy) | ||
| end | ||
| end | ||
| end | ||
|
|
||
|
|
||
| local function init() | ||
| -- Init font | ||
| font = juno.Font.fromEmbedded(12) | ||
| -- Init indicators | ||
| juno.debug.addIndicator(function() | ||
| local r = juno.time.getFps() | ||
| return r .. "fps", r | ||
| end) | ||
| juno.debug.addIndicator(function() | ||
| local r = collectgarbage("count") | ||
| return string.format("%.2fmb", r / 1024), r | ||
| end) | ||
| -- Override present function to draw the debug information before calling the | ||
| -- proper present function | ||
| local present = juno.graphics.present | ||
| juno.graphics.present = function(...) | ||
| draw() | ||
| present(...) | ||
| end | ||
| -- Set init flag | ||
| inited = true | ||
| end | ||
|
|
||
|
|
||
| local onError = function(msg) | ||
| print("error: " .. msg:match("[^\n]+")) | ||
| end | ||
|
|
||
| function juno.debug._onEvent(e) | ||
| -- Handle console's keyboard input | ||
| if e.type == "keydown" and enabled and focused then | ||
| if e.key == "backspace" then | ||
| inputbuf = inputbuf:sub(1, #inputbuf - 1) | ||
| elseif e.key == "return" then | ||
| local fn, err = loadstring(inputbuf, "=input") | ||
| if fn then | ||
| xpcall(fn, onError) | ||
| else | ||
| onError(err) | ||
| end | ||
| inputbuf = "" | ||
| elseif e.char then | ||
| inputbuf = inputbuf .. e.char | ||
| end | ||
| end | ||
| end | ||
|
|
||
|
|
||
| function juno.debug._draw() | ||
| draw() | ||
| end | ||
|
|
||
|
|
||
| function juno.debug.setVisible(x) | ||
| enabled = x and true or false | ||
| if enabled and not inited then | ||
| init() | ||
| end | ||
| end | ||
|
|
||
| function juno.debug.getVisible(x) | ||
| return enabled | ||
| end | ||
|
|
||
|
|
||
| function juno.debug.setFocused(x) | ||
| focused = x and true or false | ||
| end | ||
|
|
||
| function juno.debug.getFocused(x) | ||
| return focused | ||
| end | ||
|
|
||
|
|
||
| function juno.debug.clear() | ||
| while #lines > 0 do | ||
| table.remove(lines) | ||
| end | ||
| end | ||
|
|
||
|
|
||
| function juno.debug.addIndicator(fn, min, max) | ||
| -- Error check | ||
| local str, num = fn() | ||
| if type(str) ~= "string" or type(num) ~= "number" then | ||
| error("expected indicator function to return string and number", 2) | ||
| end | ||
| if min and type(min) ~= "number" then | ||
| error("expected `min` to be a number", 2) | ||
| end | ||
| if max and type(max) ~= "number" then | ||
| error("expected `max` to be a number", 2) | ||
| end | ||
| -- Create, add and return | ||
| local indicator = newIndicator(fn, min, max) | ||
| table.insert(indicators, indicator) | ||
| return indicator | ||
| end | ||
|
|
||
|
|
||
| function juno.debug.removeIndicator(indicator) | ||
| for i, v in ipairs(indicators) do | ||
| if v == indicator then | ||
| table.remove(indicators, i) | ||
| return | ||
| end | ||
| end | ||
| end |
| @@ -0,0 +1,46 @@ | ||
| -- | ||
| -- Copyright (c) 2015 rxi | ||
| -- | ||
| -- This library is free software; you can redistribute it and/or modify it | ||
| -- under the terms of the MIT license. See LICENSE for details. | ||
| -- | ||
|
|
||
|
|
||
| -- Override juno.graphics.init function | ||
| local init = juno.graphics.init | ||
|
|
||
| juno.graphics.init = function(...) | ||
| -- Do init | ||
| local screen = init(...) | ||
| juno.graphics.screen = screen | ||
| -- Bind the screen buffer's methods to the graphics module | ||
| for k, v in pairs(juno.Buffer) do | ||
| if not juno.graphics[k] then | ||
| juno.graphics[k] = function(...) | ||
| return v(screen, ...) | ||
| end | ||
| end | ||
| end | ||
| -- Unbind Buffer constructors (which make no sense bound) | ||
| juno.graphics.fromBlank = nil | ||
| juno.graphics.fromFile = nil | ||
| juno.graphics.fromString = nil | ||
| -- Override juno.graphics.clear() to use _clearColor if available | ||
| local clear = juno.graphics.clear | ||
| function juno.graphics.clear(r, g, b, a) | ||
| local c = juno.graphics._clearColor | ||
| r = r or (c and c[1]) | ||
| g = g or (c and c[2]) | ||
| b = b or (c and c[3]) | ||
| clear(r, g, b, 1) | ||
| end | ||
| -- Return main screen buffer | ||
| return screen | ||
| end | ||
|
|
||
|
|
||
| function juno.graphics.setClearColor(...) | ||
| juno.graphics._clearColor = { ... } | ||
| end | ||
|
|
||
|
|
| @@ -0,0 +1,341 @@ | ||
| -- | ||
| -- Copyright (c) 2015 rxi | ||
| -- | ||
| -- This library is free software; you can redistribute it and/or modify it | ||
| -- under the terms of the MIT license. See LICENSE for details. | ||
| -- | ||
|
|
||
|
|
||
| local function call(fn, ...) | ||
| if fn then return fn(...) end | ||
| end | ||
|
|
||
| local function merge(...) | ||
| local res = {} | ||
| for i = 1, select("#", ...) do | ||
| local t = select(i, ...) | ||
| if t then | ||
| for k, v in pairs(t) do | ||
| res[k] = v | ||
| end | ||
| end | ||
| end | ||
| return res | ||
| end | ||
|
|
||
| local function push(arr, ...) | ||
| for i = 1, select("#", ...) do | ||
| table.insert(arr, (select(i, ...))) | ||
| end | ||
| end | ||
|
|
||
|
|
||
| local doneOnError = false | ||
| local exit = os.exit | ||
| local traceback = debug.traceback | ||
|
|
||
| local function onError(msg) | ||
| if not doneOnError then | ||
| doneOnError = true | ||
| juno.onError(msg, traceback()) | ||
| else | ||
| print("\n" .. msg .. "\n" .. traceback()) | ||
| exit(1) | ||
| end | ||
| end | ||
|
|
||
| ------------------------------------------------------------------------------- | ||
| -- Init callbacks | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| local eventHandlers = { | ||
| keydown = function(e) | ||
| call(juno.keyboard._onEvent, e) | ||
| call(juno.debug._onEvent, e) | ||
| call(juno.onKeyDown, e.key, e.char) | ||
| end, | ||
| keyup = function(e) | ||
| call(juno.keyboard._onEvent, e) | ||
| call(juno.onKeyUp, e.key) | ||
| end, | ||
| mousemove = function(e) | ||
| call(juno.mouse._onEvent, e) | ||
| call(juno.onMouseMove, e.x, e.y) | ||
| end, | ||
| mousebuttondown = function(e) | ||
| call(juno.mouse._onEvent, e) | ||
| call(juno.onMouseDown, e.x, e.y, e.button) | ||
| end, | ||
| mousebuttonup = function(e) | ||
| call(juno.mouse._onEvent, e) | ||
| call(juno.onMouseUp, e.x, e.y, e.button) | ||
| end, | ||
| quit = function(e) | ||
| call(juno.onQuit) | ||
| os.exit() | ||
| end, | ||
| } | ||
|
|
||
| local function onStepMain() | ||
| for i, e in ipairs(juno.system.poll()) do | ||
| call(eventHandlers[e.type], e) | ||
| end | ||
| call(juno.time.step) | ||
| call(juno.onUpdate, call(juno.time.getDelta)) | ||
| call(juno.graphics.clear) | ||
| call(juno.onDraw) | ||
| call(juno.debug._draw) | ||
| call(juno.keyboard.reset) | ||
| call(juno.mouse.reset) | ||
| end | ||
|
|
||
| function juno._onStep() | ||
| xpcall(onStepMain, onError) | ||
| end | ||
|
|
||
| function juno._onAudio(...) | ||
| local res | ||
| local args = { ... } | ||
| xpcall(function() | ||
| res = call(juno.onAudio, unpack(args)) | ||
| end, onError) | ||
| return res | ||
| end | ||
|
|
||
| local pcallFunc | ||
| local pcallArgs = {} | ||
| local pcallWrap = function() | ||
| return pcallFunc(unpack(pcallArgs)) | ||
| end | ||
|
|
||
| function juno._pcall(fn, ...) | ||
| pcallFunc = fn | ||
| -- Fill argument table with new arguments, discard old args | ||
| local n = select("#", ...) | ||
| for i = 1, n do | ||
| pcallArgs[i] = select(i, ...) | ||
| end | ||
| if #pcallArgs > n then | ||
| for i = n + 1, #pcallArgs do | ||
| pcallArgs[i] = nil | ||
| end | ||
| end | ||
| -- Do call | ||
| return xpcall(pcallWrap, onError) | ||
| end | ||
|
|
||
| function juno.onError(msg, stacktrace) | ||
| -- Create and print error string | ||
| local tab = " " | ||
| local str = | ||
| msg:gsub("\t", tab):gsub("\n+$", "") .. "\n\n" .. | ||
| stacktrace:gsub("\t", tab) | ||
| print("Error:\n" .. str) | ||
| -- Override event handlers | ||
| eventHandlers = { | ||
| quit = function() os.exit() end, | ||
| keydown = function(e) if e.key == "escape" then os.exit() end end, | ||
| } | ||
| -- Disable debug | ||
| call(juno.debug.setVisible, false) | ||
| call(juno.mouse.setVisible, true) | ||
|
|
||
| -- Init error state | ||
| local font, bigfont | ||
| local done = false | ||
| local alpha = 0 | ||
|
|
||
| function juno.onUpdate() | ||
| -- The initialisation of the error state's graphics is defered to the | ||
| -- first onUpdate() call in case the error occurs in the audio thread in | ||
| -- which case it won't be able to change the openGL state | ||
| juno.graphics.reset() | ||
| juno.graphics.setClearColor(.15, .16, .2) | ||
| font = juno.Font.fromEmbedded(14) | ||
| bigfont = juno.Font.fromEmbedded(40) | ||
| -- Init update function | ||
| function juno.onUpdate(dt) | ||
| if alpha == 1 then | ||
| done = true | ||
| else | ||
| alpha = math.min(alpha + dt / .5, 1) | ||
| end | ||
| end | ||
| end | ||
|
|
||
| function juno.onAudio() end | ||
|
|
||
| function juno.onDraw() | ||
| juno.graphics.setAlpha(alpha) | ||
| juno.graphics.drawText(bigfont, "Error", 40, 40) | ||
| juno.graphics.drawText(font, str, 40, 120) | ||
| -- As this screen won't change after its faded in we can sleep here to | ||
| -- avoid having to redraw too often -- this will reduce CPU usage | ||
| if done then | ||
| juno.time.sleep(.1) | ||
| end | ||
| end | ||
| end | ||
|
|
||
|
|
||
| ------------------------------------------------------------------------------- | ||
| -- Init filesystem | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| -- Mount project paths | ||
| if juno._argv[2] then | ||
| -- Try to mount all arguments as package | ||
| for i = 2, #juno._argv do | ||
| juno.fs.mount(juno._argv[i]) | ||
| end | ||
| else | ||
| -- Try to mount default packages (pak0, pak1, etc.) | ||
| local dirs = { juno.system.info("exedir") } | ||
| if juno.system.info("os") == "osx" then | ||
| table.insert(dirs, juno.system.info("exedir") .. "/../Resources") | ||
| end | ||
| for _, dir in ipairs(dirs) do | ||
| local idx = 0 | ||
| while juno.fs.mount(dir .. "/pak" .. idx) do | ||
| idx = idx + 1 | ||
| end | ||
| if idx ~= 0 then break end | ||
| end | ||
| end | ||
|
|
||
| -- Add filesystem-compatible package loader | ||
| table.insert(package.loaders, 1, function(modname) | ||
| modname = modname:gsub("%.", "/") | ||
| for x in package.path:gmatch("[^;]+") do | ||
| local filename = x:gsub("?", modname) | ||
| if juno.fs.exists(filename) then | ||
| return assert(loadstring(juno.fs.read(filename), "=" .. filename)) | ||
| end | ||
| end | ||
| end) | ||
|
|
||
| -- Add extra package paths | ||
| package.path = package.path .. ";?/init.lua" | ||
|
|
||
|
|
||
|
|
||
| ------------------------------------------------------------------------------- | ||
| -- Init config | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| local c = {} | ||
| if juno.fs.exists("config.lua") then | ||
| c = call(require, "config") | ||
| end | ||
|
|
||
| local config = merge({ | ||
| title = "Juno " .. juno.getVersion(), | ||
| width = 500, | ||
| height = 500, | ||
| maxfps = 60, | ||
| samplerate = 44100, | ||
| buffersize = 2048, | ||
| fullscreen = false, | ||
| resizable = false, | ||
| }, c) | ||
|
|
||
| if not config.identity then | ||
| config.identity = config.title:gsub("[^%w]", ""):lower() | ||
| end | ||
|
|
||
|
|
||
| ------------------------------------------------------------------------------- | ||
| -- Init filesystem write path | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| local appdata = juno.system.info("appdata") | ||
| local path = appdata .. "/juno/" .. config.identity | ||
|
|
||
| juno.fs.setWritePath(path) | ||
| juno.fs.mount(path) | ||
|
|
||
|
|
||
| ------------------------------------------------------------------------------- | ||
| -- Init modules | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| juno.graphics.init(config.width, config.height, config.title, | ||
| config.fullscreen, config.resizable) | ||
| juno.graphics.setMaxFps(config.maxfps) | ||
| juno.graphics.setClearColor(0, 0, 0) | ||
| juno.audio.init(config.samplerate, config.buffersize) | ||
|
|
||
|
|
||
| ------------------------------------------------------------------------------- | ||
| -- Init project | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| if juno.fs.exists("main.lua") then | ||
| -- Load project file | ||
| xpcall(function() require "main" end, onError) | ||
| else | ||
| -- No project file -- init "no project loaded" screen | ||
| local w, h = juno.graphics.getSize() | ||
| local txt = juno.Font.fromEmbedded(14):render("No project loaded") | ||
| local txtPost = txt:clone() | ||
| local txtMask = txt:clone() | ||
| local particles = {} | ||
|
|
||
| function juno.onLoad() | ||
| juno.graphics.setClearColor(0.15, 0.15, 0.15) | ||
| for i = 1, 30 do | ||
| local p = { | ||
| x = 0, | ||
| y = (i / 30) * 100, | ||
| z = 0, | ||
| r = (i / 30) * 2, | ||
| } | ||
| table.insert(particles, p) | ||
| end | ||
| end | ||
|
|
||
| function juno.onUpdate(dt) | ||
| local n = juno.time.getTime() | ||
| for _, p in ipairs(particles) do | ||
| p.x = math.cos(n * p.r) * 100 | ||
| p.z = math.sin(n * p.r) | ||
| end | ||
| end | ||
|
|
||
| function juno.onKeyDown(k) | ||
| if k == "escape" then | ||
| os.exit() | ||
| end | ||
| end | ||
|
|
||
| function juno.onDraw() | ||
| -- Draw particles | ||
| juno.graphics.setBlend("add") | ||
| local lastx, lasty | ||
| for _, p in ipairs(particles) do | ||
| local x, y = (p.x * p.z) + w / 2, (p.y * p.z) + w / 2 | ||
| juno.graphics.setAlpha(p.a) | ||
| juno.graphics.drawPixel(x, y) | ||
| if lastx then | ||
| juno.graphics.setAlpha(.3) | ||
| juno.graphics.drawLine(x, y, lastx, lasty) | ||
| end | ||
| lastx, lasty = x, y | ||
| end | ||
| -- Draw text | ||
| local n = juno.time.getTime() * 2 | ||
| local x = (1 + math.sin(n)) * txtMask:getWidth() / 2 | ||
| txtPost:copyPixels(txt) | ||
| txtMask:clear(1, 1, 1, .5) | ||
| txtMask:drawRect(x - 10, 0, 20, 100, 1, 1, 1, .6) | ||
| txtMask:drawRect(x - 5, 0, 10, 100, 1, 1, 1, 1) | ||
| juno.bufferfx.mask(txtPost, txtMask) | ||
| local tx, ty = (h - txt:getWidth()) / 2, (h - txt:getHeight()) / 2 | ||
| juno.graphics.reset() | ||
| juno.graphics.draw(txtPost, tx, ty + 130) | ||
| end | ||
|
|
||
| end | ||
|
|
||
| xpcall(function() call(juno.onLoad) end, onError) | ||
|
|
| @@ -0,0 +1,55 @@ | ||
| -- | ||
| -- Copyright (c) 2015 rxi | ||
| -- | ||
| -- This library is free software; you can redistribute it and/or modify it | ||
| -- under the terms of the MIT license. See LICENSE for details. | ||
| -- | ||
|
|
||
|
|
||
| -- The table is checked and created here if it does not exist, at the time of | ||
| -- writing this the juno.keyboard does not have a C module, and so the table | ||
| -- won't exist yet. | ||
| juno.keyboard = juno.keyboard or {} | ||
|
|
||
| local keysDown = {} | ||
| local keysPressed = {} | ||
|
|
||
|
|
||
| function juno.keyboard._onEvent(e) | ||
| if e.type == "keydown" then | ||
| keysDown[e.key] = true | ||
| keysPressed[e.key] = true | ||
| elseif e.type == "keyup" then | ||
| keysDown[e.key] = nil | ||
| end | ||
| end | ||
|
|
||
|
|
||
| function juno.keyboard.reset() | ||
| for k in pairs(keysPressed) do | ||
| keysPressed[k] = nil | ||
| end | ||
| end | ||
|
|
||
|
|
||
| function juno.keyboard.isDown(...) | ||
| for i = 1, select("#", ...) do | ||
| local k = select(i, ...) | ||
| if keysDown[k] then | ||
| return true | ||
| end | ||
| end | ||
| return false | ||
| end | ||
|
|
||
|
|
||
| function juno.keyboard.wasPressed(...) | ||
| for i = 1, select("#", ...) do | ||
| local k = select(i, ...) | ||
| if keysPressed[k] then | ||
| return true | ||
| end | ||
| end | ||
| return false | ||
| end | ||
|
|
| @@ -0,0 +1,67 @@ | ||
| -- | ||
| -- Copyright (c) 2015 rxi | ||
| -- | ||
| -- This library is free software; you can redistribute it and/or modify it | ||
| -- under the terms of the MIT license. See LICENSE for details. | ||
| -- | ||
|
|
||
|
|
||
| local position = { x = 0, y = 0 } | ||
| local buttonsDown = {} | ||
| local buttonsPressed = {} | ||
|
|
||
|
|
||
| function juno.mouse._onEvent(e) | ||
| if e.type == "mousemove" then | ||
| position.x, position.y = e.x, e.y | ||
| elseif e.type == "mousebuttondown" then | ||
| buttonsDown[e.button] = true | ||
| buttonsPressed[e.button] = true | ||
| elseif e.type == "mousebuttonup" then | ||
| buttonsDown[e.button] = nil | ||
| end | ||
| end | ||
|
|
||
|
|
||
| function juno.mouse.reset() | ||
| for k in pairs(buttonsPressed) do | ||
| buttonsPressed[k] = nil | ||
| end | ||
| end | ||
|
|
||
|
|
||
| function juno.mouse.isDown(...) | ||
| for i = 1, select("#", ...) do | ||
| local b = select(i, ...) | ||
| if buttonsDown[b] then | ||
| return true | ||
| end | ||
| end | ||
| return false | ||
| end | ||
|
|
||
|
|
||
| function juno.mouse.wasPressed(...) | ||
| for i = 1, select("#", ...) do | ||
| local b = select(i, ...) | ||
| if buttonsPressed[b] then | ||
| return true | ||
| end | ||
| end | ||
| return false | ||
| end | ||
|
|
||
|
|
||
| function juno.mouse.getPosition() | ||
| return position.x, position.y | ||
| end | ||
|
|
||
|
|
||
| function juno.mouse.getX() | ||
| return position.x | ||
| end | ||
|
|
||
|
|
||
| function juno.mouse.getY() | ||
| return position.y | ||
| end |
| @@ -0,0 +1,47 @@ | ||
| -- | ||
| -- Copyright (c) 2015 rxi | ||
| -- | ||
| -- This library is free software; you can redistribute it and/or modify it | ||
| -- under the terms of the MIT license. See LICENSE for details. | ||
| -- | ||
|
|
||
|
|
||
| local last = 0 | ||
| local delta = 0 | ||
| local average = 0 | ||
| local avgTimer = 0 | ||
| local avgAcc = 1 | ||
| local avgCount = 1 | ||
|
|
||
|
|
||
| function juno.time.step() | ||
| local now = juno.time.getTime() | ||
| if last == 0 then last = now end | ||
| delta = now - last | ||
| last = now | ||
| avgTimer = avgTimer - delta | ||
| avgAcc = avgAcc + delta | ||
| avgCount = avgCount + 1 | ||
| if avgTimer <= 0 then | ||
| average = avgAcc / avgCount | ||
| avgTimer = avgTimer + 1 | ||
| avgCount = 0 | ||
| avgAcc = 0 | ||
| end | ||
| end | ||
|
|
||
|
|
||
| function juno.time.getDelta() | ||
| return delta | ||
| end | ||
|
|
||
|
|
||
| function juno.time.getAverage() | ||
| return average | ||
| end | ||
|
|
||
|
|
||
| function juno.time.getFps() | ||
| return math.floor(1 / average + .5) | ||
| end | ||
|
|
| @@ -0,0 +1,49 @@ | ||
| /** | ||
| * Copyright (c) 2015 rxi | ||
| * | ||
| * This library is free software; you can redistribute it and/or modify it | ||
| * under the terms of the MIT license. See LICENSE for details. | ||
| */ | ||
|
|
||
|
|
||
| #ifndef FS_H | ||
| #define FS_H | ||
|
|
||
| typedef struct fs_FileListNode { | ||
| char *name; | ||
| struct fs_FileListNode *next; | ||
| } fs_FileListNode; | ||
|
|
||
| enum { | ||
| FS_ESUCCESS = 0, | ||
| FS_EFAILURE = -1, | ||
| FS_EOUTOFMEM = -2, | ||
| FS_EBADPATH = -3, | ||
| FS_EBADFILENAME = -4, | ||
| FS_ENOWRITEPATH = -5, | ||
| FS_ECANTOPEN = -6, | ||
| FS_ECANTREAD = -7, | ||
| FS_ECANTWRITE = -8, | ||
| FS_ECANTDELETE = -9, | ||
| FS_ECANTMKDIR = -10, | ||
| FS_ENOTEXIST = -11, | ||
| }; | ||
|
|
||
| const char *fs_errorStr(int err); | ||
| void fs_deinit(void); | ||
| int fs_mount(const char *path); | ||
| int fs_unmount(const char *path); | ||
| int fs_setWritePath(const char *path); | ||
| int fs_exists(const char *filename); | ||
| int fs_modified(const char *filename, unsigned *mtime); | ||
| int fs_size(const char *filename, size_t *size); | ||
| void *fs_read(const char *filename, size_t *size); | ||
| int fs_isDir(const char *filename); | ||
| fs_FileListNode *fs_listDir(const char *path); | ||
| void fs_freeFileList(fs_FileListNode *list); | ||
| int fs_write(const char *filename, const void *data, int size); | ||
| int fs_append(const char *filename, const void *data, int size); | ||
| int fs_delete(const char *filename); | ||
| int fs_makeDirs(const char *path); | ||
|
|
||
| #endif |
| @@ -0,0 +1,147 @@ | ||
| #ifndef LEXTLIB_LUA52_H | ||
| #define LEXTLIB_LUA52_H | ||
|
|
||
| /** | ||
| * The original version of this file is located at | ||
| * https://github.com/devurandom/lextlib/blob/master/lextlib_lua52.h | ||
| * | ||
| * Its license is as follows: | ||
| * | ||
| * Copyright (c) 2012 Dennis Schridde | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to | ||
| * deal in the Software without restriction, including without limitation the | ||
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| * sell copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in | ||
| * all copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| * IN THE SOFTWARE. | ||
| */ | ||
|
|
||
|
|
||
| #include <assert.h> | ||
|
|
||
| //#include <lua.h> | ||
| //#include <lauxlib.h> | ||
|
|
||
|
|
||
| #if LUA_VERSION_NUM < 502 | ||
| /* Error codes for lua_load: */ | ||
| # define LUA_OK 0 | ||
| /* WARNING: This error does not exist in Lua 5.1 */ | ||
| # define LUA_ERRGCMM (-1) | ||
|
|
||
| /* Comparison types for lua_compare: */ | ||
| # define LUA_OPEQ 0 | ||
| # define LUA_OPLT 1 | ||
| # define LUA_OPLE 2 | ||
|
|
||
| /* WARNING: Not entirely correct, but should work anyway */ | ||
| # define lua_rawlen lua_objlen | ||
|
|
||
| # define lua_absindex(L, i) (((i) > 0 || (i) < LUA_REGISTRYINDEX) ? (i) : lua_gettop(L)+(i)+1) | ||
|
|
||
| /* WARNING: Something very different, but it might get your job done */ | ||
| # define lua_getuservalue lua_getfenv | ||
| # define lua_setuservalue lua_setfenv | ||
|
|
||
| /* WARNING: Probably slower than Lua 5.2's implementation */ | ||
| # define lua_compare luaX52_lua_compare | ||
|
|
||
| # define lua_tonumberx(L,i,b) (lua_isnumber(L,(i)) ? (*(b)=1, lua_tonumber(L,(i))) : (*(b)=0, 0)) | ||
| # define lua_tointegerx(L,i,b) (lua_isnumber(L,(i)) ? (*(b)=1, lua_tointeger(L,(i))) : (*(b)=0, 0)) | ||
|
|
||
| # define luaL_getsubtable luaX52_luaL_getsubtable | ||
|
|
||
| # define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) | ||
|
|
||
| # define luaL_newlibtable(L,l) (lua_createtable(L,0,sizeof(l))) | ||
|
|
||
| # define luaL_requiref(L,l,f,g) luaX52_luaL_requiref(L,(l),(f),(g)) | ||
|
|
||
| # define luaL_setfuncs luaX52_luaL_setfuncs | ||
|
|
||
| # define luaL_setmetatable(L,t) (luaL_getmetatable(L,t), lua_setmetatable(L,-2)) | ||
|
|
||
| # define luaL_testudata(L,i,t) luaX52_luaL_testudata(L,(i),(t)) | ||
|
|
||
| static inline void luaX52_luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) { | ||
| luaL_checkstack(L, nup, "too many upvalues"); | ||
| for (; l->name != NULL; l++) { /* fill the table with given functions */ | ||
| for (int i = 0; i < nup; i++) /* copy upvalues to the top */ | ||
| lua_pushvalue(L, -nup); | ||
| lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ | ||
| lua_setfield(L, -(nup + 2), l->name); | ||
| } | ||
| lua_pop(L, nup); /* remove upvalues */ | ||
| } | ||
|
|
||
| static inline int luaX52_lua_compare(lua_State *L, int index1, int index2, int op) { | ||
| assert(op == LUA_OPEQ || op == LUA_OPLT || op == LUA_OPLE); | ||
| switch (op) { | ||
| case LUA_OPEQ: | ||
| return lua_equal(L, index1, index2); | ||
| case LUA_OPLT: | ||
| return lua_lessthan(L, index1, index2); | ||
| case LUA_OPLE: | ||
| return lua_lessthan(L, index1, index2) || lua_equal(L, index1, index2); | ||
| default: | ||
| return luaL_error(L, "Call to lua_compare with unsupported operator %d", op); | ||
| } | ||
| } | ||
|
|
||
| static inline int luaX52_luaL_getsubtable(lua_State *L, int idx, const char *fname) { | ||
| lua_getfield(L, idx, fname); | ||
| if (lua_istable(L, -1)) return 1; /* table already there */ | ||
| else { | ||
| lua_pop(L, 1); /* remove previous result */ | ||
| idx = lua_absindex(L, idx); | ||
| lua_newtable(L); | ||
| lua_pushvalue(L, -1); /* copy to be left at top */ | ||
| lua_setfield(L, idx, fname); /* assign new table to field */ | ||
| return 0; /* false, because did not find table there */ | ||
| } | ||
| } | ||
|
|
||
| static inline void luaX52_luaL_requiref(lua_State *L, const char *modname, lua_CFunction openf, int glb) { | ||
| lua_pushcfunction(L, openf); | ||
| lua_pushstring(L, modname); /* argument to open function */ | ||
| lua_call(L, 1, 1); /* open module */ | ||
| luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); | ||
| lua_pushvalue(L, -2); /* make copy of module (call result) */ | ||
| lua_setfield(L, -2, modname); /* _LOADED[modname] = module */ | ||
| lua_pop(L, 1); /* remove _LOADED table */ | ||
| if (glb) { | ||
| lua_pushvalue(L, -1); /* copy of 'mod' */ | ||
| lua_setglobal(L, modname); /* _G[modname] = module */ | ||
| } | ||
| } | ||
|
|
||
| static inline void *luaX52_luaL_testudata(lua_State *L, int ud, const char *tname) { | ||
| void *p = lua_touserdata(L, ud); | ||
| if (p != NULL) { /* value is a userdata? */ | ||
| if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ | ||
| luaL_getmetatable(L, tname); /* get correct metatable */ | ||
| if (!lua_rawequal(L, -1, -2)) /* not the same? */ | ||
| p = NULL; /* value is a userdata with wrong metatable */ | ||
| lua_pop(L, 2); /* remove both metatables */ | ||
| return p; | ||
| } | ||
| } | ||
| return NULL; /* value is not a userdata with a metatable */ | ||
| } | ||
|
|
||
| #endif | ||
|
|
||
|
|
||
| #endif |
| @@ -0,0 +1,16 @@ | ||
| /* | ||
| ** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ | ||
| ** Auxiliary functions from Lua API | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
| #ifndef lapi_h | ||
| #define lapi_h | ||
|
|
||
|
|
||
| #include "lobject.h" | ||
|
|
||
|
|
||
| LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); | ||
|
|
||
| #endif |
| @@ -0,0 +1,174 @@ | ||
| /* | ||
| ** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ | ||
| ** Auxiliary functions for building Lua libraries | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
|
|
||
| #ifndef lauxlib_h | ||
| #define lauxlib_h | ||
|
|
||
|
|
||
| #include <stddef.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "lua.h" | ||
|
|
||
|
|
||
| #if defined(LUA_COMPAT_GETN) | ||
| LUALIB_API int (luaL_getn) (lua_State *L, int t); | ||
| LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); | ||
| #else | ||
| #define luaL_getn(L,i) ((int)lua_objlen(L, i)) | ||
| #define luaL_setn(L,i,j) ((void)0) /* no op! */ | ||
| #endif | ||
|
|
||
| #if defined(LUA_COMPAT_OPENLIB) | ||
| #define luaI_openlib luaL_openlib | ||
| #endif | ||
|
|
||
|
|
||
| /* extra error code for `luaL_load' */ | ||
| #define LUA_ERRFILE (LUA_ERRERR+1) | ||
|
|
||
|
|
||
| typedef struct luaL_Reg { | ||
| const char *name; | ||
| lua_CFunction func; | ||
| } luaL_Reg; | ||
|
|
||
|
|
||
|
|
||
| LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, | ||
| const luaL_Reg *l, int nup); | ||
| LUALIB_API void (luaL_register) (lua_State *L, const char *libname, | ||
| const luaL_Reg *l); | ||
| LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); | ||
| LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); | ||
| LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); | ||
| LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); | ||
| LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, | ||
| size_t *l); | ||
| LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, | ||
| const char *def, size_t *l); | ||
| LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); | ||
| LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); | ||
|
|
||
| LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); | ||
| LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, | ||
| lua_Integer def); | ||
|
|
||
| LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); | ||
| LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); | ||
| LUALIB_API void (luaL_checkany) (lua_State *L, int narg); | ||
|
|
||
| LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); | ||
| LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); | ||
|
|
||
| LUALIB_API void (luaL_where) (lua_State *L, int lvl); | ||
| LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); | ||
|
|
||
| LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, | ||
| const char *const lst[]); | ||
|
|
||
| LUALIB_API int (luaL_ref) (lua_State *L, int t); | ||
| LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); | ||
|
|
||
| LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); | ||
| LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, | ||
| const char *name); | ||
| LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); | ||
|
|
||
| LUALIB_API lua_State *(luaL_newstate) (void); | ||
|
|
||
|
|
||
| LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, | ||
| const char *r); | ||
|
|
||
| LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, | ||
| const char *fname, int szhint); | ||
|
|
||
|
|
||
|
|
||
|
|
||
| /* | ||
| ** =============================================================== | ||
| ** some useful macros | ||
| ** =============================================================== | ||
| */ | ||
|
|
||
| #define luaL_argcheck(L, cond,numarg,extramsg) \ | ||
| ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) | ||
| #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) | ||
| #define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) | ||
| #define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) | ||
| #define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) | ||
| #define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) | ||
| #define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) | ||
|
|
||
| #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) | ||
|
|
||
| #define luaL_dofile(L, fn) \ | ||
| (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) | ||
|
|
||
| #define luaL_dostring(L, s) \ | ||
| (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) | ||
|
|
||
| #define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) | ||
|
|
||
| #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) | ||
|
|
||
| /* | ||
| ** {====================================================== | ||
| ** Generic Buffer manipulation | ||
| ** ======================================================= | ||
| */ | ||
|
|
||
|
|
||
|
|
||
| typedef struct luaL_Buffer { | ||
| char *p; /* current position in buffer */ | ||
| int lvl; /* number of strings in the stack (level) */ | ||
| lua_State *L; | ||
| char buffer[LUAL_BUFFERSIZE]; | ||
| } luaL_Buffer; | ||
|
|
||
| #define luaL_addchar(B,c) \ | ||
| ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ | ||
| (*(B)->p++ = (char)(c))) | ||
|
|
||
| /* compatibility only */ | ||
| #define luaL_putchar(B,c) luaL_addchar(B,c) | ||
|
|
||
| #define luaL_addsize(B,n) ((B)->p += (n)) | ||
|
|
||
| LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); | ||
| LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); | ||
| LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); | ||
| LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); | ||
| LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); | ||
| LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); | ||
|
|
||
|
|
||
| /* }====================================================== */ | ||
|
|
||
|
|
||
| /* compatibility with ref system */ | ||
|
|
||
| /* pre-defined references */ | ||
| #define LUA_NOREF (-2) | ||
| #define LUA_REFNIL (-1) | ||
|
|
||
| #define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ | ||
| (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) | ||
|
|
||
| #define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) | ||
|
|
||
| #define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) | ||
|
|
||
|
|
||
| #define luaL_reg luaL_Reg | ||
|
|
||
| #endif | ||
|
|
||
|
|
| @@ -0,0 +1,76 @@ | ||
| /* | ||
| ** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ | ||
| ** Code generator for Lua | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
| #ifndef lcode_h | ||
| #define lcode_h | ||
|
|
||
| #include "llex.h" | ||
| #include "lobject.h" | ||
| #include "lopcodes.h" | ||
| #include "lparser.h" | ||
|
|
||
|
|
||
| /* | ||
| ** Marks the end of a patch list. It is an invalid value both as an absolute | ||
| ** address, and as a list link (would link an element to itself). | ||
| */ | ||
| #define NO_JUMP (-1) | ||
|
|
||
|
|
||
| /* | ||
| ** grep "ORDER OPR" if you change these enums | ||
| */ | ||
| typedef enum BinOpr { | ||
| OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, | ||
| OPR_CONCAT, | ||
| OPR_NE, OPR_EQ, | ||
| OPR_LT, OPR_LE, OPR_GT, OPR_GE, | ||
| OPR_AND, OPR_OR, | ||
| OPR_NOBINOPR | ||
| } BinOpr; | ||
|
|
||
|
|
||
| typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; | ||
|
|
||
|
|
||
| #define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) | ||
|
|
||
| #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) | ||
|
|
||
| #define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) | ||
|
|
||
| LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); | ||
| LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); | ||
| LUAI_FUNC void luaK_fixline (FuncState *fs, int line); | ||
| LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); | ||
| LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); | ||
| LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); | ||
| LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); | ||
| LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); | ||
| LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); | ||
| LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); | ||
| LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); | ||
| LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); | ||
| LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); | ||
| LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); | ||
| LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); | ||
| LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); | ||
| LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); | ||
| LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); | ||
| LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); | ||
| LUAI_FUNC int luaK_jump (FuncState *fs); | ||
| LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); | ||
| LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); | ||
| LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); | ||
| LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); | ||
| LUAI_FUNC int luaK_getlabel (FuncState *fs); | ||
| LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); | ||
| LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); | ||
| LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); | ||
| LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); | ||
|
|
||
|
|
||
| #endif |
| @@ -0,0 +1,398 @@ | ||
| /* | ||
| ** $Id: ldblib.c,v 1.104.1.4 2009/08/04 18:50:18 roberto Exp $ | ||
| ** Interface from Lua to its debug API | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
|
|
||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| #define ldblib_c | ||
| #define LUA_LIB | ||
|
|
||
| #include "lua.h" | ||
|
|
||
| #include "lauxlib.h" | ||
| #include "lualib.h" | ||
|
|
||
|
|
||
|
|
||
| static int db_getregistry (lua_State *L) { | ||
| lua_pushvalue(L, LUA_REGISTRYINDEX); | ||
| return 1; | ||
| } | ||
|
|
||
|
|
||
| static int db_getmetatable (lua_State *L) { | ||
| luaL_checkany(L, 1); | ||
| if (!lua_getmetatable(L, 1)) { | ||
| lua_pushnil(L); /* no metatable */ | ||
| } | ||
| return 1; | ||
| } | ||
|
|
||
|
|
||
| static int db_setmetatable (lua_State *L) { | ||
| int t = lua_type(L, 2); | ||
| luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, | ||
| "nil or table expected"); | ||
| lua_settop(L, 2); | ||
| lua_pushboolean(L, lua_setmetatable(L, 1)); | ||
| return 1; | ||
| } | ||
|
|
||
|
|
||
| static int db_getfenv (lua_State *L) { | ||
| luaL_checkany(L, 1); | ||
| lua_getfenv(L, 1); | ||
| return 1; | ||
| } | ||
|
|
||
|
|
||
| static int db_setfenv (lua_State *L) { | ||
| luaL_checktype(L, 2, LUA_TTABLE); | ||
| lua_settop(L, 2); | ||
| if (lua_setfenv(L, 1) == 0) | ||
| luaL_error(L, LUA_QL("setfenv") | ||
| " cannot change environment of given object"); | ||
| return 1; | ||
| } | ||
|
|
||
|
|
||
| static void settabss (lua_State *L, const char *i, const char *v) { | ||
| lua_pushstring(L, v); | ||
| lua_setfield(L, -2, i); | ||
| } | ||
|
|
||
|
|
||
| static void settabsi (lua_State *L, const char *i, int v) { | ||
| lua_pushinteger(L, v); | ||
| lua_setfield(L, -2, i); | ||
| } | ||
|
|
||
|
|
||
| static lua_State *getthread (lua_State *L, int *arg) { | ||
| if (lua_isthread(L, 1)) { | ||
| *arg = 1; | ||
| return lua_tothread(L, 1); | ||
| } | ||
| else { | ||
| *arg = 0; | ||
| return L; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { | ||
| if (L == L1) { | ||
| lua_pushvalue(L, -2); | ||
| lua_remove(L, -3); | ||
| } | ||
| else | ||
| lua_xmove(L1, L, 1); | ||
| lua_setfield(L, -2, fname); | ||
| } | ||
|
|
||
|
|
||
| static int db_getinfo (lua_State *L) { | ||
| lua_Debug ar; | ||
| int arg; | ||
| lua_State *L1 = getthread(L, &arg); | ||
| const char *options = luaL_optstring(L, arg+2, "flnSu"); | ||
| if (lua_isnumber(L, arg+1)) { | ||
| if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { | ||
| lua_pushnil(L); /* level out of range */ | ||
| return 1; | ||
| } | ||
| } | ||
| else if (lua_isfunction(L, arg+1)) { | ||
| lua_pushfstring(L, ">%s", options); | ||
| options = lua_tostring(L, -1); | ||
| lua_pushvalue(L, arg+1); | ||
| lua_xmove(L, L1, 1); | ||
| } | ||
| else | ||
| return luaL_argerror(L, arg+1, "function or level expected"); | ||
| if (!lua_getinfo(L1, options, &ar)) | ||
| return luaL_argerror(L, arg+2, "invalid option"); | ||
| lua_createtable(L, 0, 2); | ||
| if (strchr(options, 'S')) { | ||
| settabss(L, "source", ar.source); | ||
| settabss(L, "short_src", ar.short_src); | ||
| settabsi(L, "linedefined", ar.linedefined); | ||
| settabsi(L, "lastlinedefined", ar.lastlinedefined); | ||
| settabss(L, "what", ar.what); | ||
| } | ||
| if (strchr(options, 'l')) | ||
| settabsi(L, "currentline", ar.currentline); | ||
| if (strchr(options, 'u')) | ||
| settabsi(L, "nups", ar.nups); | ||
| if (strchr(options, 'n')) { | ||
| settabss(L, "name", ar.name); | ||
| settabss(L, "namewhat", ar.namewhat); | ||
| } | ||
| if (strchr(options, 'L')) | ||
| treatstackoption(L, L1, "activelines"); | ||
| if (strchr(options, 'f')) | ||
| treatstackoption(L, L1, "func"); | ||
| return 1; /* return table */ | ||
| } | ||
|
|
||
|
|
||
| static int db_getlocal (lua_State *L) { | ||
| int arg; | ||
| lua_State *L1 = getthread(L, &arg); | ||
| lua_Debug ar; | ||
| const char *name; | ||
| if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ | ||
| return luaL_argerror(L, arg+1, "level out of range"); | ||
| name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); | ||
| if (name) { | ||
| lua_xmove(L1, L, 1); | ||
| lua_pushstring(L, name); | ||
| lua_pushvalue(L, -2); | ||
| return 2; | ||
| } | ||
| else { | ||
| lua_pushnil(L); | ||
| return 1; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| static int db_setlocal (lua_State *L) { | ||
| int arg; | ||
| lua_State *L1 = getthread(L, &arg); | ||
| lua_Debug ar; | ||
| if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ | ||
| return luaL_argerror(L, arg+1, "level out of range"); | ||
| luaL_checkany(L, arg+3); | ||
| lua_settop(L, arg+3); | ||
| lua_xmove(L, L1, 1); | ||
| lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); | ||
| return 1; | ||
| } | ||
|
|
||
|
|
||
| static int auxupvalue (lua_State *L, int get) { | ||
| const char *name; | ||
| int n = luaL_checkint(L, 2); | ||
| luaL_checktype(L, 1, LUA_TFUNCTION); | ||
| if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ | ||
| name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); | ||
| if (name == NULL) return 0; | ||
| lua_pushstring(L, name); | ||
| lua_insert(L, -(get+1)); | ||
| return get + 1; | ||
| } | ||
|
|
||
|
|
||
| static int db_getupvalue (lua_State *L) { | ||
| return auxupvalue(L, 1); | ||
| } | ||
|
|
||
|
|
||
| static int db_setupvalue (lua_State *L) { | ||
| luaL_checkany(L, 3); | ||
| return auxupvalue(L, 0); | ||
| } | ||
|
|
||
|
|
||
|
|
||
| static const char KEY_HOOK = 'h'; | ||
|
|
||
|
|
||
| static void hookf (lua_State *L, lua_Debug *ar) { | ||
| static const char *const hooknames[] = | ||
| {"call", "return", "line", "count", "tail return"}; | ||
| lua_pushlightuserdata(L, (void *)&KEY_HOOK); | ||
| lua_rawget(L, LUA_REGISTRYINDEX); | ||
| lua_pushlightuserdata(L, L); | ||
| lua_rawget(L, -2); | ||
| if (lua_isfunction(L, -1)) { | ||
| lua_pushstring(L, hooknames[(int)ar->event]); | ||
| if (ar->currentline >= 0) | ||
| lua_pushinteger(L, ar->currentline); | ||
| else lua_pushnil(L); | ||
| lua_assert(lua_getinfo(L, "lS", ar)); | ||
| lua_call(L, 2, 0); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| static int makemask (const char *smask, int count) { | ||
| int mask = 0; | ||
| if (strchr(smask, 'c')) mask |= LUA_MASKCALL; | ||
| if (strchr(smask, 'r')) mask |= LUA_MASKRET; | ||
| if (strchr(smask, 'l')) mask |= LUA_MASKLINE; | ||
| if (count > 0) mask |= LUA_MASKCOUNT; | ||
| return mask; | ||
| } | ||
|
|
||
|
|
||
| static char *unmakemask (int mask, char *smask) { | ||
| int i = 0; | ||
| if (mask & LUA_MASKCALL) smask[i++] = 'c'; | ||
| if (mask & LUA_MASKRET) smask[i++] = 'r'; | ||
| if (mask & LUA_MASKLINE) smask[i++] = 'l'; | ||
| smask[i] = '\0'; | ||
| return smask; | ||
| } | ||
|
|
||
|
|
||
| static void gethooktable (lua_State *L) { | ||
| lua_pushlightuserdata(L, (void *)&KEY_HOOK); | ||
| lua_rawget(L, LUA_REGISTRYINDEX); | ||
| if (!lua_istable(L, -1)) { | ||
| lua_pop(L, 1); | ||
| lua_createtable(L, 0, 1); | ||
| lua_pushlightuserdata(L, (void *)&KEY_HOOK); | ||
| lua_pushvalue(L, -2); | ||
| lua_rawset(L, LUA_REGISTRYINDEX); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| static int db_sethook (lua_State *L) { | ||
| int arg, mask, count; | ||
| lua_Hook func; | ||
| lua_State *L1 = getthread(L, &arg); | ||
| if (lua_isnoneornil(L, arg+1)) { | ||
| lua_settop(L, arg+1); | ||
| func = NULL; mask = 0; count = 0; /* turn off hooks */ | ||
| } | ||
| else { | ||
| const char *smask = luaL_checkstring(L, arg+2); | ||
| luaL_checktype(L, arg+1, LUA_TFUNCTION); | ||
| count = luaL_optint(L, arg+3, 0); | ||
| func = hookf; mask = makemask(smask, count); | ||
| } | ||
| gethooktable(L); | ||
| lua_pushlightuserdata(L, L1); | ||
| lua_pushvalue(L, arg+1); | ||
| lua_rawset(L, -3); /* set new hook */ | ||
| lua_pop(L, 1); /* remove hook table */ | ||
| lua_sethook(L1, func, mask, count); /* set hooks */ | ||
| return 0; | ||
| } | ||
|
|
||
|
|
||
| static int db_gethook (lua_State *L) { | ||
| int arg; | ||
| lua_State *L1 = getthread(L, &arg); | ||
| char buff[5]; | ||
| int mask = lua_gethookmask(L1); | ||
| lua_Hook hook = lua_gethook(L1); | ||
| if (hook != NULL && hook != hookf) /* external hook? */ | ||
| lua_pushliteral(L, "external hook"); | ||
| else { | ||
| gethooktable(L); | ||
| lua_pushlightuserdata(L, L1); | ||
| lua_rawget(L, -2); /* get hook */ | ||
| lua_remove(L, -2); /* remove hook table */ | ||
| } | ||
| lua_pushstring(L, unmakemask(mask, buff)); | ||
| lua_pushinteger(L, lua_gethookcount(L1)); | ||
| return 3; | ||
| } | ||
|
|
||
|
|
||
| static int db_debug (lua_State *L) { | ||
| for (;;) { | ||
| char buffer[250]; | ||
| fputs("lua_debug> ", stderr); | ||
| if (fgets(buffer, sizeof(buffer), stdin) == 0 || | ||
| strcmp(buffer, "cont\n") == 0) | ||
| return 0; | ||
| if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || | ||
| lua_pcall(L, 0, 0, 0)) { | ||
| fputs(lua_tostring(L, -1), stderr); | ||
| fputs("\n", stderr); | ||
| } | ||
| lua_settop(L, 0); /* remove eventual returns */ | ||
| } | ||
| } | ||
|
|
||
|
|
||
| #define LEVELS1 12 /* size of the first part of the stack */ | ||
| #define LEVELS2 10 /* size of the second part of the stack */ | ||
|
|
||
| static int db_errorfb (lua_State *L) { | ||
| int level; | ||
| int firstpart = 1; /* still before eventual `...' */ | ||
| int arg; | ||
| lua_State *L1 = getthread(L, &arg); | ||
| lua_Debug ar; | ||
| if (lua_isnumber(L, arg+2)) { | ||
| level = (int)lua_tointeger(L, arg+2); | ||
| lua_pop(L, 1); | ||
| } | ||
| else | ||
| level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ | ||
| if (lua_gettop(L) == arg) | ||
| lua_pushliteral(L, ""); | ||
| else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ | ||
| else lua_pushliteral(L, "\n"); | ||
| lua_pushliteral(L, "stack traceback:"); | ||
| while (lua_getstack(L1, level++, &ar)) { | ||
| if (level > LEVELS1 && firstpart) { | ||
| /* no more than `LEVELS2' more levels? */ | ||
| if (!lua_getstack(L1, level+LEVELS2, &ar)) | ||
| level--; /* keep going */ | ||
| else { | ||
| lua_pushliteral(L, "\n\t..."); /* too many levels */ | ||
| while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ | ||
| level++; | ||
| } | ||
| firstpart = 0; | ||
| continue; | ||
| } | ||
| lua_pushliteral(L, "\n\t"); | ||
| lua_getinfo(L1, "Snl", &ar); | ||
| lua_pushfstring(L, "%s:", ar.short_src); | ||
| if (ar.currentline > 0) | ||
| lua_pushfstring(L, "%d:", ar.currentline); | ||
| if (*ar.namewhat != '\0') /* is there a name? */ | ||
| lua_pushfstring(L, " in function " LUA_QS, ar.name); | ||
| else { | ||
| if (*ar.what == 'm') /* main? */ | ||
| lua_pushfstring(L, " in main chunk"); | ||
| else if (*ar.what == 'C' || *ar.what == 't') | ||
| lua_pushliteral(L, " ?"); /* C function or tail call */ | ||
| else | ||
| lua_pushfstring(L, " in function <%s:%d>", | ||
| ar.short_src, ar.linedefined); | ||
| } | ||
| lua_concat(L, lua_gettop(L) - arg); | ||
| } | ||
| lua_concat(L, lua_gettop(L) - arg); | ||
| return 1; | ||
| } | ||
|
|
||
|
|
||
| static const luaL_Reg dblib[] = { | ||
| {"debug", db_debug}, | ||
| {"getfenv", db_getfenv}, | ||
| {"gethook", db_gethook}, | ||
| {"getinfo", db_getinfo}, | ||
| {"getlocal", db_getlocal}, | ||
| {"getregistry", db_getregistry}, | ||
| {"getmetatable", db_getmetatable}, | ||
| {"getupvalue", db_getupvalue}, | ||
| {"setfenv", db_setfenv}, | ||
| {"sethook", db_sethook}, | ||
| {"setlocal", db_setlocal}, | ||
| {"setmetatable", db_setmetatable}, | ||
| {"setupvalue", db_setupvalue}, | ||
| {"traceback", db_errorfb}, | ||
| {NULL, NULL} | ||
| }; | ||
|
|
||
|
|
||
| LUALIB_API int luaopen_debug (lua_State *L) { | ||
| luaL_register(L, LUA_DBLIBNAME, dblib); | ||
| return 1; | ||
| } | ||
|
|
| @@ -0,0 +1,33 @@ | ||
| /* | ||
| ** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ | ||
| ** Auxiliary functions from Debug Interface module | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
| #ifndef ldebug_h | ||
| #define ldebug_h | ||
|
|
||
|
|
||
| #include "lstate.h" | ||
|
|
||
|
|
||
| #define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) | ||
|
|
||
| #define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) | ||
|
|
||
| #define resethookcount(L) (L->hookcount = L->basehookcount) | ||
|
|
||
|
|
||
| LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, | ||
| const char *opname); | ||
| LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); | ||
| LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, | ||
| const TValue *p2); | ||
| LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, | ||
| const TValue *p2); | ||
| LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); | ||
| LUAI_FUNC void luaG_errormsg (lua_State *L); | ||
| LUAI_FUNC int luaG_checkcode (const Proto *pt); | ||
| LUAI_FUNC int luaG_checkopenop (Instruction i); | ||
|
|
||
| #endif |
| @@ -0,0 +1,57 @@ | ||
| /* | ||
| ** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ | ||
| ** Stack and Call structure of Lua | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
| #ifndef ldo_h | ||
| #define ldo_h | ||
|
|
||
|
|
||
| #include "lobject.h" | ||
| #include "lstate.h" | ||
| #include "lzio.h" | ||
|
|
||
|
|
||
| #define luaD_checkstack(L,n) \ | ||
| if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ | ||
| luaD_growstack(L, n); \ | ||
| else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); | ||
|
|
||
|
|
||
| #define incr_top(L) {luaD_checkstack(L,1); L->top++;} | ||
|
|
||
| #define savestack(L,p) ((char *)(p) - (char *)L->stack) | ||
| #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) | ||
|
|
||
| #define saveci(L,p) ((char *)(p) - (char *)L->base_ci) | ||
| #define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) | ||
|
|
||
|
|
||
| /* results from luaD_precall */ | ||
| #define PCRLUA 0 /* initiated a call to a Lua function */ | ||
| #define PCRC 1 /* did a call to a C function */ | ||
| #define PCRYIELD 2 /* C funtion yielded */ | ||
|
|
||
|
|
||
| /* type of protected functions, to be ran by `runprotected' */ | ||
| typedef void (*Pfunc) (lua_State *L, void *ud); | ||
|
|
||
| LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); | ||
| LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); | ||
| LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); | ||
| LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); | ||
| LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, | ||
| ptrdiff_t oldtop, ptrdiff_t ef); | ||
| LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); | ||
| LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); | ||
| LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); | ||
| LUAI_FUNC void luaD_growstack (lua_State *L, int n); | ||
|
|
||
| LUAI_FUNC void luaD_throw (lua_State *L, int errcode); | ||
| LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); | ||
|
|
||
| LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); | ||
|
|
||
| #endif | ||
|
|
| @@ -0,0 +1,164 @@ | ||
| /* | ||
| ** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ | ||
| ** save precompiled Lua chunks | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
| #include <stddef.h> | ||
|
|
||
| #define ldump_c | ||
| #define LUA_CORE | ||
|
|
||
| #include "lua.h" | ||
|
|
||
| #include "lobject.h" | ||
| #include "lstate.h" | ||
| #include "lundump.h" | ||
|
|
||
| typedef struct { | ||
| lua_State* L; | ||
| lua_Writer writer; | ||
| void* data; | ||
| int strip; | ||
| int status; | ||
| } DumpState; | ||
|
|
||
| #define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) | ||
| #define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) | ||
|
|
||
| static void DumpBlock(const void* b, size_t size, DumpState* D) | ||
| { | ||
| if (D->status==0) | ||
| { | ||
| lua_unlock(D->L); | ||
| D->status=(*D->writer)(D->L,b,size,D->data); | ||
| lua_lock(D->L); | ||
| } | ||
| } | ||
|
|
||
| static void DumpChar(int y, DumpState* D) | ||
| { | ||
| char x=(char)y; | ||
| DumpVar(x,D); | ||
| } | ||
|
|
||
| static void DumpInt(int x, DumpState* D) | ||
| { | ||
| DumpVar(x,D); | ||
| } | ||
|
|
||
| static void DumpNumber(lua_Number x, DumpState* D) | ||
| { | ||
| DumpVar(x,D); | ||
| } | ||
|
|
||
| static void DumpVector(const void* b, int n, size_t size, DumpState* D) | ||
| { | ||
| DumpInt(n,D); | ||
| DumpMem(b,n,size,D); | ||
| } | ||
|
|
||
| static void DumpString(const TString* s, DumpState* D) | ||
| { | ||
| if (s==NULL || getstr(s)==NULL) | ||
| { | ||
| size_t size=0; | ||
| DumpVar(size,D); | ||
| } | ||
| else | ||
| { | ||
| size_t size=s->tsv.len+1; /* include trailing '\0' */ | ||
| DumpVar(size,D); | ||
| DumpBlock(getstr(s),size,D); | ||
| } | ||
| } | ||
|
|
||
| #define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) | ||
|
|
||
| static void DumpFunction(const Proto* f, const TString* p, DumpState* D); | ||
|
|
||
| static void DumpConstants(const Proto* f, DumpState* D) | ||
| { | ||
| int i,n=f->sizek; | ||
| DumpInt(n,D); | ||
| for (i=0; i<n; i++) | ||
| { | ||
| const TValue* o=&f->k[i]; | ||
| DumpChar(ttype(o),D); | ||
| switch (ttype(o)) | ||
| { | ||
| case LUA_TNIL: | ||
| break; | ||
| case LUA_TBOOLEAN: | ||
| DumpChar(bvalue(o),D); | ||
| break; | ||
| case LUA_TNUMBER: | ||
| DumpNumber(nvalue(o),D); | ||
| break; | ||
| case LUA_TSTRING: | ||
| DumpString(rawtsvalue(o),D); | ||
| break; | ||
| default: | ||
| lua_assert(0); /* cannot happen */ | ||
| break; | ||
| } | ||
| } | ||
| n=f->sizep; | ||
| DumpInt(n,D); | ||
| for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D); | ||
| } | ||
|
|
||
| static void DumpDebug(const Proto* f, DumpState* D) | ||
| { | ||
| int i,n; | ||
| n= (D->strip) ? 0 : f->sizelineinfo; | ||
| DumpVector(f->lineinfo,n,sizeof(int),D); | ||
| n= (D->strip) ? 0 : f->sizelocvars; | ||
| DumpInt(n,D); | ||
| for (i=0; i<n; i++) | ||
| { | ||
| DumpString(f->locvars[i].varname,D); | ||
| DumpInt(f->locvars[i].startpc,D); | ||
| DumpInt(f->locvars[i].endpc,D); | ||
| } | ||
| n= (D->strip) ? 0 : f->sizeupvalues; | ||
| DumpInt(n,D); | ||
| for (i=0; i<n; i++) DumpString(f->upvalues[i],D); | ||
| } | ||
|
|
||
| static void DumpFunction(const Proto* f, const TString* p, DumpState* D) | ||
| { | ||
| DumpString((f->source==p || D->strip) ? NULL : f->source,D); | ||
| DumpInt(f->linedefined,D); | ||
| DumpInt(f->lastlinedefined,D); | ||
| DumpChar(f->nups,D); | ||
| DumpChar(f->numparams,D); | ||
| DumpChar(f->is_vararg,D); | ||
| DumpChar(f->maxstacksize,D); | ||
| DumpCode(f,D); | ||
| DumpConstants(f,D); | ||
| DumpDebug(f,D); | ||
| } | ||
|
|
||
| static void DumpHeader(DumpState* D) | ||
| { | ||
| char h[LUAC_HEADERSIZE]; | ||
| luaU_header(h); | ||
| DumpBlock(h,LUAC_HEADERSIZE,D); | ||
| } | ||
|
|
||
| /* | ||
| ** dump Lua function as precompiled chunk | ||
| */ | ||
| int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) | ||
| { | ||
| DumpState D; | ||
| D.L=L; | ||
| D.writer=w; | ||
| D.data=data; | ||
| D.strip=strip; | ||
| D.status=0; | ||
| DumpHeader(&D); | ||
| DumpFunction(f,NULL,&D); | ||
| return D.status; | ||
| } |
| @@ -0,0 +1,174 @@ | ||
| /* | ||
| ** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ | ||
| ** Auxiliary functions to manipulate prototypes and closures | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
|
|
||
| #include <stddef.h> | ||
|
|
||
| #define lfunc_c | ||
| #define LUA_CORE | ||
|
|
||
| #include "lua.h" | ||
|
|
||
| #include "lfunc.h" | ||
| #include "lgc.h" | ||
| #include "lmem.h" | ||
| #include "lobject.h" | ||
| #include "lstate.h" | ||
|
|
||
|
|
||
|
|
||
| Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { | ||
| Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); | ||
| luaC_link(L, obj2gco(c), LUA_TFUNCTION); | ||
| c->c.isC = 1; | ||
| c->c.env = e; | ||
| c->c.nupvalues = cast_byte(nelems); | ||
| return c; | ||
| } | ||
|
|
||
|
|
||
| Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { | ||
| Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); | ||
| luaC_link(L, obj2gco(c), LUA_TFUNCTION); | ||
| c->l.isC = 0; | ||
| c->l.env = e; | ||
| c->l.nupvalues = cast_byte(nelems); | ||
| while (nelems--) c->l.upvals[nelems] = NULL; | ||
| return c; | ||
| } | ||
|
|
||
|
|
||
| UpVal *luaF_newupval (lua_State *L) { | ||
| UpVal *uv = luaM_new(L, UpVal); | ||
| luaC_link(L, obj2gco(uv), LUA_TUPVAL); | ||
| uv->v = &uv->u.value; | ||
| setnilvalue(uv->v); | ||
| return uv; | ||
| } | ||
|
|
||
|
|
||
| UpVal *luaF_findupval (lua_State *L, StkId level) { | ||
| global_State *g = G(L); | ||
| GCObject **pp = &L->openupval; | ||
| UpVal *p; | ||
| UpVal *uv; | ||
| while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { | ||
| lua_assert(p->v != &p->u.value); | ||
| if (p->v == level) { /* found a corresponding upvalue? */ | ||
| if (isdead(g, obj2gco(p))) /* is it dead? */ | ||
| changewhite(obj2gco(p)); /* ressurect it */ | ||
| return p; | ||
| } | ||
| pp = &p->next; | ||
| } | ||
| uv = luaM_new(L, UpVal); /* not found: create a new one */ | ||
| uv->tt = LUA_TUPVAL; | ||
| uv->marked = luaC_white(g); | ||
| uv->v = level; /* current value lives in the stack */ | ||
| uv->next = *pp; /* chain it in the proper position */ | ||
| *pp = obj2gco(uv); | ||
| uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ | ||
| uv->u.l.next = g->uvhead.u.l.next; | ||
| uv->u.l.next->u.l.prev = uv; | ||
| g->uvhead.u.l.next = uv; | ||
| lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); | ||
| return uv; | ||
| } | ||
|
|
||
|
|
||
| static void unlinkupval (UpVal *uv) { | ||
| lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); | ||
| uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ | ||
| uv->u.l.prev->u.l.next = uv->u.l.next; | ||
| } | ||
|
|
||
|
|
||
| void luaF_freeupval (lua_State *L, UpVal *uv) { | ||
| if (uv->v != &uv->u.value) /* is it open? */ | ||
| unlinkupval(uv); /* remove from open list */ | ||
| luaM_free(L, uv); /* free upvalue */ | ||
| } | ||
|
|
||
|
|
||
| void luaF_close (lua_State *L, StkId level) { | ||
| UpVal *uv; | ||
| global_State *g = G(L); | ||
| while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { | ||
| GCObject *o = obj2gco(uv); | ||
| lua_assert(!isblack(o) && uv->v != &uv->u.value); | ||
| L->openupval = uv->next; /* remove from `open' list */ | ||
| if (isdead(g, o)) | ||
| luaF_freeupval(L, uv); /* free upvalue */ | ||
| else { | ||
| unlinkupval(uv); | ||
| setobj(L, &uv->u.value, uv->v); | ||
| uv->v = &uv->u.value; /* now current value lives here */ | ||
| luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Proto *luaF_newproto (lua_State *L) { | ||
| Proto *f = luaM_new(L, Proto); | ||
| luaC_link(L, obj2gco(f), LUA_TPROTO); | ||
| f->k = NULL; | ||
| f->sizek = 0; | ||
| f->p = NULL; | ||
| f->sizep = 0; | ||
| f->code = NULL; | ||
| f->sizecode = 0; | ||
| f->sizelineinfo = 0; | ||
| f->sizeupvalues = 0; | ||
| f->nups = 0; | ||
| f->upvalues = NULL; | ||
| f->numparams = 0; | ||
| f->is_vararg = 0; | ||
| f->maxstacksize = 0; | ||
| f->lineinfo = NULL; | ||
| f->sizelocvars = 0; | ||
| f->locvars = NULL; | ||
| f->linedefined = 0; | ||
| f->lastlinedefined = 0; | ||
| f->source = NULL; | ||
| return f; | ||
| } | ||
|
|
||
|
|
||
| void luaF_freeproto (lua_State *L, Proto *f) { | ||
| luaM_freearray(L, f->code, f->sizecode, Instruction); | ||
| luaM_freearray(L, f->p, f->sizep, Proto *); | ||
| luaM_freearray(L, f->k, f->sizek, TValue); | ||
| luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); | ||
| luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); | ||
| luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); | ||
| luaM_free(L, f); | ||
| } | ||
|
|
||
|
|
||
| void luaF_freeclosure (lua_State *L, Closure *c) { | ||
| int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : | ||
| sizeLclosure(c->l.nupvalues); | ||
| luaM_freemem(L, c, size); | ||
| } | ||
|
|
||
|
|
||
| /* | ||
| ** Look for n-th local variable at line `line' in function `func'. | ||
| ** Returns NULL if not found. | ||
| */ | ||
| const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { | ||
| int i; | ||
| for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) { | ||
| if (pc < f->locvars[i].endpc) { /* is variable active? */ | ||
| local_number--; | ||
| if (local_number == 0) | ||
| return getstr(f->locvars[i].varname); | ||
| } | ||
| } | ||
| return NULL; /* not found */ | ||
| } | ||
|
|
| @@ -0,0 +1,34 @@ | ||
| /* | ||
| ** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ | ||
| ** Auxiliary functions to manipulate prototypes and closures | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
| #ifndef lfunc_h | ||
| #define lfunc_h | ||
|
|
||
|
|
||
| #include "lobject.h" | ||
|
|
||
|
|
||
| #define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ | ||
| cast(int, sizeof(TValue)*((n)-1))) | ||
|
|
||
| #define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ | ||
| cast(int, sizeof(TValue *)*((n)-1))) | ||
|
|
||
|
|
||
| LUAI_FUNC Proto *luaF_newproto (lua_State *L); | ||
| LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); | ||
| LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); | ||
| LUAI_FUNC UpVal *luaF_newupval (lua_State *L); | ||
| LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); | ||
| LUAI_FUNC void luaF_close (lua_State *L, StkId level); | ||
| LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); | ||
| LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); | ||
| LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); | ||
| LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, | ||
| int pc); | ||
|
|
||
|
|
||
| #endif |
| @@ -0,0 +1,110 @@ | ||
| /* | ||
| ** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ | ||
| ** Garbage Collector | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
| #ifndef lgc_h | ||
| #define lgc_h | ||
|
|
||
|
|
||
| #include "lobject.h" | ||
|
|
||
|
|
||
| /* | ||
| ** Possible states of the Garbage Collector | ||
| */ | ||
| #define GCSpause 0 | ||
| #define GCSpropagate 1 | ||
| #define GCSsweepstring 2 | ||
| #define GCSsweep 3 | ||
| #define GCSfinalize 4 | ||
|
|
||
|
|
||
| /* | ||
| ** some userful bit tricks | ||
| */ | ||
| #define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) | ||
| #define setbits(x,m) ((x) |= (m)) | ||
| #define testbits(x,m) ((x) & (m)) | ||
| #define bitmask(b) (1<<(b)) | ||
| #define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) | ||
| #define l_setbit(x,b) setbits(x, bitmask(b)) | ||
| #define resetbit(x,b) resetbits(x, bitmask(b)) | ||
| #define testbit(x,b) testbits(x, bitmask(b)) | ||
| #define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) | ||
| #define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) | ||
| #define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) | ||
|
|
||
|
|
||
|
|
||
| /* | ||
| ** Layout for bit use in `marked' field: | ||
| ** bit 0 - object is white (type 0) | ||
| ** bit 1 - object is white (type 1) | ||
| ** bit 2 - object is black | ||
| ** bit 3 - for userdata: has been finalized | ||
| ** bit 3 - for tables: has weak keys | ||
| ** bit 4 - for tables: has weak values | ||
| ** bit 5 - object is fixed (should not be collected) | ||
| ** bit 6 - object is "super" fixed (only the main thread) | ||
| */ | ||
|
|
||
|
|
||
| #define WHITE0BIT 0 | ||
| #define WHITE1BIT 1 | ||
| #define BLACKBIT 2 | ||
| #define FINALIZEDBIT 3 | ||
| #define KEYWEAKBIT 3 | ||
| #define VALUEWEAKBIT 4 | ||
| #define FIXEDBIT 5 | ||
| #define SFIXEDBIT 6 | ||
| #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) | ||
|
|
||
|
|
||
| #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) | ||
| #define isblack(x) testbit((x)->gch.marked, BLACKBIT) | ||
| #define isgray(x) (!isblack(x) && !iswhite(x)) | ||
|
|
||
| #define otherwhite(g) (g->currentwhite ^ WHITEBITS) | ||
| #define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) | ||
|
|
||
| #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) | ||
| #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) | ||
|
|
||
| #define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) | ||
|
|
||
| #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) | ||
|
|
||
|
|
||
| #define luaC_checkGC(L) { \ | ||
| condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ | ||
| if (G(L)->totalbytes >= G(L)->GCthreshold) \ | ||
| luaC_step(L); } | ||
|
|
||
|
|
||
| #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ | ||
| luaC_barrierf(L,obj2gco(p),gcvalue(v)); } | ||
|
|
||
| #define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ | ||
| luaC_barrierback(L,t); } | ||
|
|
||
| #define luaC_objbarrier(L,p,o) \ | ||
| { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ | ||
| luaC_barrierf(L,obj2gco(p),obj2gco(o)); } | ||
|
|
||
| #define luaC_objbarriert(L,t,o) \ | ||
| { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } | ||
|
|
||
| LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); | ||
| LUAI_FUNC void luaC_callGCTM (lua_State *L); | ||
| LUAI_FUNC void luaC_freeall (lua_State *L); | ||
| LUAI_FUNC void luaC_step (lua_State *L); | ||
| LUAI_FUNC void luaC_fullgc (lua_State *L); | ||
| LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); | ||
| LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); | ||
| LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); | ||
| LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); | ||
|
|
||
|
|
||
| #endif |
| @@ -0,0 +1,38 @@ | ||
| /* | ||
| ** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ | ||
| ** Initialization of libraries for lua.c | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
|
|
||
| #define linit_c | ||
| #define LUA_LIB | ||
|
|
||
| #include "lua.h" | ||
|
|
||
| #include "lualib.h" | ||
| #include "lauxlib.h" | ||
|
|
||
|
|
||
| static const luaL_Reg lualibs[] = { | ||
| {"", luaopen_base}, | ||
| {LUA_LOADLIBNAME, luaopen_package}, | ||
| {LUA_TABLIBNAME, luaopen_table}, | ||
| {LUA_IOLIBNAME, luaopen_io}, | ||
| {LUA_OSLIBNAME, luaopen_os}, | ||
| {LUA_STRLIBNAME, luaopen_string}, | ||
| {LUA_MATHLIBNAME, luaopen_math}, | ||
| {LUA_DBLIBNAME, luaopen_debug}, | ||
| {NULL, NULL} | ||
| }; | ||
|
|
||
|
|
||
| LUALIB_API void luaL_openlibs (lua_State *L) { | ||
| const luaL_Reg *lib = lualibs; | ||
| for (; lib->func; lib++) { | ||
| lua_pushcfunction(L, lib->func); | ||
| lua_pushstring(L, lib->name); | ||
| lua_call(L, 1, 0); | ||
| } | ||
| } | ||
|
|
| @@ -0,0 +1,81 @@ | ||
| /* | ||
| ** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ | ||
| ** Lexical Analyzer | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
| #ifndef llex_h | ||
| #define llex_h | ||
|
|
||
| #include "lobject.h" | ||
| #include "lzio.h" | ||
|
|
||
|
|
||
| #define FIRST_RESERVED 257 | ||
|
|
||
| /* maximum length of a reserved word */ | ||
| #define TOKEN_LEN (sizeof("function")/sizeof(char)) | ||
|
|
||
|
|
||
| /* | ||
| * WARNING: if you change the order of this enumeration, | ||
| * grep "ORDER RESERVED" | ||
| */ | ||
| enum RESERVED { | ||
| /* terminal symbols denoted by reserved words */ | ||
| TK_AND = FIRST_RESERVED, TK_BREAK, | ||
| TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, | ||
| TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, | ||
| TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, | ||
| /* other terminal symbols */ | ||
| TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, | ||
| TK_NAME, TK_STRING, TK_EOS | ||
| }; | ||
|
|
||
| /* number of reserved words */ | ||
| #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) | ||
|
|
||
|
|
||
| /* array with token `names' */ | ||
| LUAI_DATA const char *const luaX_tokens []; | ||
|
|
||
|
|
||
| typedef union { | ||
| lua_Number r; | ||
| TString *ts; | ||
| } SemInfo; /* semantics information */ | ||
|
|
||
|
|
||
| typedef struct Token { | ||
| int token; | ||
| SemInfo seminfo; | ||
| } Token; | ||
|
|
||
|
|
||
| typedef struct LexState { | ||
| int current; /* current character (charint) */ | ||
| int linenumber; /* input line counter */ | ||
| int lastline; /* line of last token `consumed' */ | ||
| Token t; /* current token */ | ||
| Token lookahead; /* look ahead token */ | ||
| struct FuncState *fs; /* `FuncState' is private to the parser */ | ||
| struct lua_State *L; | ||
| ZIO *z; /* input stream */ | ||
| Mbuffer *buff; /* buffer for tokens */ | ||
| TString *source; /* current source name */ | ||
| char decpoint; /* locale decimal point */ | ||
| } LexState; | ||
|
|
||
|
|
||
| LUAI_FUNC void luaX_init (lua_State *L); | ||
| LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, | ||
| TString *source); | ||
| LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); | ||
| LUAI_FUNC void luaX_next (LexState *ls); | ||
| LUAI_FUNC void luaX_lookahead (LexState *ls); | ||
| LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); | ||
| LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); | ||
| LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); | ||
|
|
||
|
|
||
| #endif |
| @@ -0,0 +1,128 @@ | ||
| /* | ||
| ** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ | ||
| ** Limits, basic types, and some other `installation-dependent' definitions | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
| #ifndef llimits_h | ||
| #define llimits_h | ||
|
|
||
|
|
||
| #include <limits.h> | ||
| #include <stddef.h> | ||
|
|
||
|
|
||
| #include "lua.h" | ||
|
|
||
|
|
||
| typedef LUAI_UINT32 lu_int32; | ||
|
|
||
| typedef LUAI_UMEM lu_mem; | ||
|
|
||
| typedef LUAI_MEM l_mem; | ||
|
|
||
|
|
||
|
|
||
| /* chars used as small naturals (so that `char' is reserved for characters) */ | ||
| typedef unsigned char lu_byte; | ||
|
|
||
|
|
||
| #define MAX_SIZET ((size_t)(~(size_t)0)-2) | ||
|
|
||
| #define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) | ||
|
|
||
|
|
||
| #define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ | ||
|
|
||
| /* | ||
| ** conversion of pointer to integer | ||
| ** this is for hashing only; there is no problem if the integer | ||
| ** cannot hold the whole pointer value | ||
| */ | ||
| #define IntPoint(p) ((unsigned int)(lu_mem)(p)) | ||
|
|
||
|
|
||
|
|
||
| /* type to ensure maximum alignment */ | ||
| typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; | ||
|
|
||
|
|
||
| /* result of a `usual argument conversion' over lua_Number */ | ||
| typedef LUAI_UACNUMBER l_uacNumber; | ||
|
|
||
|
|
||
| /* internal assertions for in-house debugging */ | ||
| #ifdef lua_assert | ||
|
|
||
| #define check_exp(c,e) (lua_assert(c), (e)) | ||
| #define api_check(l,e) lua_assert(e) | ||
|
|
||
| #else | ||
|
|
||
| #define lua_assert(c) ((void)0) | ||
| #define check_exp(c,e) (e) | ||
| #define api_check luai_apicheck | ||
|
|
||
| #endif | ||
|
|
||
|
|
||
| #ifndef UNUSED | ||
| #define UNUSED(x) ((void)(x)) /* to avoid warnings */ | ||
| #endif | ||
|
|
||
|
|
||
| #ifndef cast | ||
| #define cast(t, exp) ((t)(exp)) | ||
| #endif | ||
|
|
||
| #define cast_byte(i) cast(lu_byte, (i)) | ||
| #define cast_num(i) cast(lua_Number, (i)) | ||
| #define cast_int(i) cast(int, (i)) | ||
|
|
||
|
|
||
|
|
||
| /* | ||
| ** type for virtual-machine instructions | ||
| ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) | ||
| */ | ||
| typedef lu_int32 Instruction; | ||
|
|
||
|
|
||
|
|
||
| /* maximum stack for a Lua function */ | ||
| #define MAXSTACK 250 | ||
|
|
||
|
|
||
|
|
||
| /* minimum size for the string table (must be power of 2) */ | ||
| #ifndef MINSTRTABSIZE | ||
| #define MINSTRTABSIZE 32 | ||
| #endif | ||
|
|
||
|
|
||
| /* minimum size for string buffer */ | ||
| #ifndef LUA_MINBUFFER | ||
| #define LUA_MINBUFFER 32 | ||
| #endif | ||
|
|
||
|
|
||
| #ifndef lua_lock | ||
| #define lua_lock(L) ((void) 0) | ||
| #define lua_unlock(L) ((void) 0) | ||
| #endif | ||
|
|
||
| #ifndef luai_threadyield | ||
| #define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} | ||
| #endif | ||
|
|
||
|
|
||
| /* | ||
| ** macro to control inclusion of some hard tests on stack reallocation | ||
| */ | ||
| #ifndef HARDSTACKTESTS | ||
| #define condhardstacktests(x) ((void)0) | ||
| #else | ||
| #define condhardstacktests(x) x | ||
| #endif | ||
|
|
||
| #endif |
| @@ -0,0 +1,263 @@ | ||
| /* | ||
| ** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $ | ||
| ** Standard mathematical library | ||
| ** See Copyright Notice in lua.h | ||
| */ | ||
|
|
||
|
|
||
| #include <stdlib.h> | ||
| #include <math.h> | ||
|
|
||
| #define lmathlib_c | ||
| #define LUA_LIB | ||
|
|
||
| #include "lua.h" | ||
|
|
||
| #include "lauxlib.h" | ||
| #include "lualib.h" | ||
|
|
||
|
|
||
| #undef PI | ||
| #define PI (3.14159265358979323846) | ||
| #define RADIANS_PER_DEGREE (PI/180.0) | ||
|
|
||
|
|
||
|
|
||
| static int math_abs (lua_State *L) { | ||
| lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_sin (lua_State *L) { | ||
| lua_pushnumber(L, sin(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_sinh (lua_State *L) { | ||
| lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_cos (lua_State *L) { | ||
| lua_pushnumber(L, cos(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_cosh (lua_State *L) { | ||
| lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_tan (lua_State *L) { | ||
| lua_pushnumber(L, tan(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_tanh (lua_State *L) { | ||
| lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_asin (lua_State *L) { | ||
| lua_pushnumber(L, asin(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_acos (lua_State *L) { | ||
| lua_pushnumber(L, acos(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_atan (lua_State *L) { | ||
| lua_pushnumber(L, atan(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_atan2 (lua_State *L) { | ||
| lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_ceil (lua_State *L) { | ||
| lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_floor (lua_State *L) { | ||
| lua_pushnumber(L, floor(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_fmod (lua_State *L) { | ||
| lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_modf (lua_State *L) { | ||
| double ip; | ||
| double fp = modf(luaL_checknumber(L, 1), &ip); | ||
| lua_pushnumber(L, ip); | ||
| lua_pushnumber(L, fp); | ||
| return 2; | ||
| } | ||
|
|
||
| static int math_sqrt (lua_State *L) { | ||
| lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_pow (lua_State *L) { | ||
| lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_log (lua_State *L) { | ||
| lua_pushnumber(L, log(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_log10 (lua_State *L) { | ||
| lua_pushnumber(L, log10(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_exp (lua_State *L) { | ||
| lua_pushnumber(L, exp(luaL_checknumber(L, 1))); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_deg (lua_State *L) { | ||
| lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_rad (lua_State *L) { | ||
| lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); | ||
| return 1; | ||
| } | ||
|
|
||
| static int math_frexp (lua_State *L) { | ||
| int e; | ||
| lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); | ||
| lua_pushinteger(L, e); | ||
| return 2; | ||
| } | ||
|
|
||
| static int math_ldexp (lua_State *L) { | ||
| lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); | ||
| return 1; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| static int math_min (lua_State *L) { | ||
| int n = lua_gettop(L); /* number of arguments */ | ||
| lua_Number dmin = luaL_checknumber(L, 1); | ||
| int i; | ||
| for (i=2; i<=n; i++) { | ||
| lua_Number d = luaL_checknumber(L, i); | ||
| if (d < dmin) | ||
| dmin = d; | ||
| } | ||
| lua_pushnumber(L, dmin); | ||
| return 1; | ||
| } | ||
|
|
||
|
|
||
| static int math_max (lua_State *L) { | ||
| int n = lua_gettop(L); /* number of arguments */ | ||
| lua_Number dmax = luaL_checknumber(L, 1); | ||
| int i; | ||
| for (i=2; i<=n; i++) { | ||
| lua_Number d = luaL_checknumber(L, i); | ||
| if (d > dmax) | ||
| dmax = d; | ||
| } | ||
| lua_pushnumber(L, dmax); | ||
| return 1; | ||
| } | ||
|
|
||
|
|
||
| static int math_random (lua_State *L) { | ||
| /* the `%' avoids the (rare) case of r==1, and is needed also because on | ||
| some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ | ||
| lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; | ||
| switch (lua_gettop(L)) { /* check number of arguments */ | ||
| case 0: { /* no arguments */ | ||
| lua_pushnumber(L, r); /* Number between 0 and 1 */ | ||
| break; | ||
| } | ||
| case 1: { /* only upper limit */ | ||
| int u = luaL_checkint(L, 1); | ||
| luaL_argcheck(L, 1<=u, 1, "interval is empty"); | ||
| lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ | ||
| break; | ||
| } | ||
| case 2: { /* lower and upper limits */ | ||
| int l = luaL_checkint(L, 1); | ||
| int u = luaL_checkint(L, 2); | ||
| luaL_argcheck(L, l<=u, 2, "interval is empty"); | ||
| lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ | ||
| break; | ||
| } | ||
| default: return luaL_error(L, "wrong number of arguments"); | ||
| } | ||
| return 1; | ||
| } | ||
|
|
||
|
|
||
| static int math_randomseed (lua_State *L) { | ||
| srand(luaL_checkint(L, 1)); | ||
| return 0; | ||
| } | ||
|
|
||
|
|
||
| static const luaL_Reg mathlib[] = { | ||
| {"abs", math_abs}, | ||
| {"acos", math_acos}, | ||
| {"asin", math_asin}, | ||
| {"atan2", math_atan2}, | ||
| {"atan", math_atan}, | ||
| {"ceil", math_ceil}, | ||
| {"cosh", math_cosh}, | ||
| {"cos", math_cos}, | ||
| {"deg", math_deg}, | ||
| {"exp", math_exp}, | ||
| {"floor", math_floor}, | ||
| {"fmod", math_fmod}, | ||
| {"frexp", math_frexp}, | ||
| {"ldexp", math_ldexp}, | ||
| {"log10", math_log10}, | ||
| {"log", math_log}, | ||
| {"max", math_max}, | ||
| {"min", math_min}, | ||
| {"modf", math_modf}, | ||
| {"pow", math_pow}, | ||
| {"rad", math_rad}, | ||
| {"random", math_random}, | ||
| {"randomseed", math_randomseed}, | ||
| {"sinh", math_sinh}, | ||
| {"sin", math_sin}, | ||
| {"sqrt", math_sqrt}, | ||
| {"tanh", math_tanh}, | ||
| {"tan", math_tan}, | ||
| {NULL, NULL} | ||
| }; | ||
|
|
||
|
|
||
| /* | ||
| ** Open math library | ||
| */ | ||
| LUALIB_API int luaopen_math (lua_State *L) { | ||
| luaL_register(L, LUA_MATHLIBNAME, mathlib); | ||
| lua_pushnumber(L, PI); | ||
| lua_setfield(L, -2, "pi"); | ||
| lua_pushnumber(L, HUGE_VAL); | ||
| lua_setfield(L, -2, "huge"); | ||
| #if defined(LUA_COMPAT_MOD) | ||
| lua_getfield(L, -1, "fmod"); | ||
| lua_setfield(L, -2, "mod"); | ||
| #endif | ||
| return 1; | ||
| } | ||
|
|