diff --git a/src/ast.lua b/src/ast.lua deleted file mode 100644 index 09a0c83..0000000 --- a/src/ast.lua +++ /dev/null @@ -1,286 +0,0 @@ ---[[ - ast.lua - Generates a structure for use in preprocessing. -]] --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this --- file, You can obtain one at https://mozilla.org/MPL/2.0/. - -local function nextc(f, c) - c = c or 1 - return f:read(c) -end - -local function peek(f, c) - c = c or 1 - local z = f:read(c) - f:seek("cur", -c) - return z -end - -local function skip(f, c) - c = c or 1 - return f:seek("cur", c) -end - -local ws = { - ["\t"] = true, - [" "] = true -} - -local function parse_hex(f) - local lc = " " - local hex = "" - while (48 <= lc:byte() and lc:byte() <= 57) or (97 <= lc:byte() and lc:byte() <= 102) or (65 <= lc:byte() and lc:byte() <= 70) and lc do - lc = nextc(f) - if (48 <= lc:byte() and lc:byte()) <= 57 or (97 <= lc:byte() and lc:byte() <= 102) or (65 <= lc:byte() and lc:byte() <= 70) and lc then - hex = hex .. lc - end - end - return tonumber(hex, 16) -end - -local function parse_number(f, c) - local lc = " " - local num = c - while 48 <= lc:byte() and lc:byte() <= 57 and lc do - lc = nextc(f) - if (48 <= lc:byte() and lc:byte() <= 57) and lc then - num = num .. lc - end - end - return tonumber(hex, 10) -end - -local esct = { - ["t"] = "\t", - ["n"] = "\n", - ["r"] = "\r", - ["\\"] = "\\\\" -} - -for i=0, 9 do - esct[tostring(i)] = string.char(i) -end - -local function parse_dblquote(f) - local val = "" - while peek(f) ~= "\"" do - local c = nextc(f) - if (peek(f) == "\n" or peek(f) == "\r") then - return nil, "Unexpected end of line" - elseif (not peek(f)) then - return nil, "Unexpected end of file" - end - if (c == "\\") then - if (esct[peek(f)]) then - c = esct[peek(f)] - skip(f) - else - c = nextc(f) - end - end - val = val .. c - end - skip(f) - return val -end - -local function parse_snglquote(f) - local val = "" - while peek(f) ~= "\'" do - local c = nextc(f) - if (peek(f) == "\n" or peek(f) == "\r") then - return nil, "Unexpected end of line" - elseif (not peek(f)) then - return nil, "Unexpected end of file" - end - if (c == "\\") then - if (esct[peek(f)]) then - c = esct[peek(f)] - skip(f) - else - c = nextc(f) - end - end - val = val .. c - end - skip(f) - return val -end - -local function parse_envarg(f) - local val = "" - while peek(f) ~= ")" do - if (peek(f) == "\n" or peek(f) == "\r") then - return nil, "Unexpected end of line" - elseif (not peek(f)) then - return nil, "Unexpected end of file" - end - val = val .. nextc(f) - end - skip(f) - return val -end - -local function parse_directive(f) - local lc = "_" - local name = "" - local args = {} - local carg = "" - while not ws[lc] do - lc = nextc(f) - if (lc == "\n" or lc == "\r") then - if (lc == "\r" and peek(f) == "\n") then skip(f) end - return {type="directive", name=name} - elseif not ws[lc] then - name = name .. lc - end - end - while true do - lc = nextc(f) - if (lc == "\n" or lc == "\r") then - if (lc == "\r" and peek(f) == "\n") then skip(f) end - return {type="directive", name=name, args=args} - elseif lc == "0" and peek(f) == "x" then - skip(f) - local val = parse_hex(f) - args[#args+1] = val - elseif 48 <= lc:byte() and lc:byte() <= 57 then - local val = parse_number(f, lc) - args[#args+1] = val - elseif lc == "\"" then - local val, e = parse_dblquote(f) - if not val then return val, e end - args[#args+1] = val - elseif lc == "\'" then - local val, e = parse_snglquote(f) - if not val then return val, e end - args[#args+1] = val - elseif lc == "$" and peek(f) == "(" then - skip(f) - local val = parse_envarg(f) - if not os.getenv(val) then return nil, "Enviroment variable `"..val.."' does not exist." end - args[#args+1] = os.getenv(val) - elseif lc == "@" and peek(f, 2) == "[{" then - skip(f, 2) - local val = "" - while peek(f, 2) ~= "}]" do - val = val .. nextc(f) - end - args[#args+1] = {type="lua_var", val} - skip(f, 2) - elseif not ws[lc] then - return nil, "Syntax error" - end - end -end - -local function mkast(f, n) - io.stderr:write("PROC\t",n,"\n") - local lc = " " - local lpos = 1 - local ilpos = 1 - local tree = {} - local code = "" - local branches = {} - local function add_code() - tree[#tree+1] = {type="code", data=code, file=n, line=lpos} - code = "" - end - local function parse_error(e) - io.stderr:write("ERROR:"..n..":"..lpos..": "..e.."\n") - os.exit(1) - end - while lc and lc ~= "" do - lc = nextc(f) - if (lc == "-" and ilpos == 1) then - if (peek(f, 2) == "-#") then --Directive - add_code() - skip(f, 2) - local d, r = parse_directive(f) - if not d then - parse_error(r) - end - d.line = lpos - d.file = n - lpos = lpos+1 - tree[#tree+1] = d - else - code = code .. lc - ilpos = ilpos+1 - end - elseif (lc == "/" and ilpos == 1) then - if (peek(f, 2) == "/#") then --Directive - add_code() - skip(f, 2) - local d, r = parse_directive(f) - if not d then - parse_error(r) - end - d.line = lpos - d.file = n - lpos = lpos+1 - tree[#tree+1] = d - else - code = code .. lc - ilpos = ilpos+1 - end - elseif (lc == "$" and peek(f) == "(") then - add_code() - skip(f) - local val, e = parse_envarg(f) - if not val then - parse_error(e) - end - tree[#tree+1] = {type="envvar", var=val, file=n, line=lpos} - elseif (lc == "@" and peek(f, 2) == "[[") then - add_code() - skip(f, 2) - local val = "" - while peek(f, 2) ~= "]]" do - val = val .. nextc(f) - end - tree[#tree+1] = {type="lua", code=val, file=n, line=lpos} - skip(f, 2) - elseif (lc == "@" and peek(f, 2) == "[{") then - add_code() - skip(f, 2) - local val = "" - while peek(f, 2) ~= "}]" do - val = val .. nextc(f) - end - tree[#tree+1] = {type="lua_r", code=val, file=n, line=lpos} - skip(f, 2) - elseif (lc == "$" and peek(f, 2) == "[[") then - add_code() - skip(f, 2) - local val = "" - while peek(f, 2) ~= "]]" do - val = val .. nextc(f) - end - tree[#tree+1] = {type="shell", code=val, file=n, line=lpos} - skip(f, 2) - elseif (lc == "$" and peek(f, 2) == "[{") then - add_code() - skip(f, 2) - local val = "" - while peek(f, 2) ~= "}]" do - val = val .. nextc(f) - end - tree[#tree+1] = {type="shell_r", code=val, file=n, line=lpos} - skip(f, 2) - elseif (lc == "\r" or lc == "\n") then - if (lc == "\r" and peek(f) == "\n") then - skip(f) - end - lpos = lpos+1 - ilpos = 1 - code = code .. "\n" - else - code = code .. (lc or "") - ilpos = ilpos+1 - end - end - add_code() - return tree -end \ No newline at end of file diff --git a/src/directives/pragma.lua b/src/directives/pragma.lua index 20431bd..af3a36c 100644 --- a/src/directives/pragma.lua +++ b/src/directives/pragma.lua @@ -2,6 +2,14 @@ -- License, v. 2.0. If a copy of the MPL was not distributed with this -- file, You can obtain one at https://mozilla.org/MPL/2.0/. +local pragma_hooks = { + include_once = function(env, value) + if value and value ~= 0 then + + end + end +} + function directives.pragma(env, key, value) if not env.pragmas[key] then return nil, "unknown pragma "..key diff --git a/src/generator.lua b/src/generator.lua deleted file mode 100644 index ac463ea..0000000 --- a/src/generator.lua +++ /dev/null @@ -1,138 +0,0 @@ ---[[ - generator.lua - Generates the code. -]] - --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this --- file, You can obtain one at https://mozilla.org/MPL/2.0/. - -local function lua_escape(code) - return code:gsub("\\", "\\\\"):gsub("\"", "\\\""):gsub("\n", "\\n") -end - -local function shell_escape(code) - return code:gsub("\\%[", "[") -end - -local function svar_escape(code) - return code:gsub("\"", "\\\""):gsub("\'", "\\\'"):gsub("`", "\\`") -end - -local directives = {} - -local function generate(ast, gencode) - local lua_code = "" - for i=1, #ast do - local leaf = ast[i] - if (leaf.type == "lua") then - lua_code = lua_code .. leaf.code - elseif (leaf.type == "directive") then - local stargs = {} - for i=1, #leaf.args do - local arg = leaf.args[i] - if (type(arg) == "string") then - stargs[i] = "\""..lua_escape(arg).."\"" - elseif (type(arg) == "number") then - stargs[i] = tostring(arg) - elseif (type(arg) == "table" and arg.type=="lua_var") then - stargs[i] = arg[1] - end - end - lua_code = lua_code .. "call_directive(\""..leaf.file..":"..tostring(leaf.line).."\",\""..leaf.name.."\","..table.concat(stargs, ",")..")" - elseif (leaf.type == "envvar") then - lua_code = lua_code .. "put_env(\""..leaf.file..":"..tostring(leaf.line).."\",\""..leaf.var.."\")" - elseif (leaf.type == "code") then - lua_code = lua_code .. "put_code(\""..leaf.file..":"..tostring(leaf.line).."\",\"" .. lua_escape(leaf.data) .. "\")" - elseif (leaf.type == "lua_r") then - lua_code = lua_code .. "put_code(\""..leaf.file..":"..tostring(leaf.line).."\",tostring("..leaf.code.."))" - elseif (leaf.type == "shell") then - lua_code = lua_code .. "put_shell_out(\""..leaf.file..":"..tostring(leaf.line).."\",\""..lua_escape(leaf.code).."\")" - elseif (leaf.type == "shell_r") then - lua_code = lua_code .. "put_svar(\""..leaf.file..":"..tostring(leaf.line).."\",\""..leaf.code.."\")" - else - io.stderr:write("ERROR: Internal catastrophic failure, unknown type "..leaf.type.."\n") - os.exit(1) - end - lua_code = lua_code .. "\n" - end - local env = {code = ""} - local function run_away_screaming(fpos, err) - io.stdout:write("ERROR: "..fpos..": "..err.."\n") - os.exit(1) - end - local function bitch(fpos, err) - io.stdout:write("WARNING: "..fpos..": "..err.."\n") - end - local function call_directive(fpos, dname, ...) - if (not directives[dname]) then - run_away_screaming(fpos, "Invalid directive name `"..dname.."'") - end - local r, er = directives[dname](env, ...) - if (not r) then - run_away_screaming(fpos, er) - end - end - local function put_env(fpos, evar) - local e = svar.get(evar) - if not e then - run_away_screaming(fpos, "Enviroment variable `"..evar.."' does not exist!") - end - env.code = env.code .. "\""..lua_escape(e).."\"" - end - local function put_code(fpos, code) - env.code = env.code .. code --not much that can fail here... - end - local function put_shell_out(fpos, code) - local tname = os.tmpname() - local f = os.tmpname() - local fh = io.open(f, "w") - fh:write(code) - fh:close() - os.execute("chmod +x "..f) - local vars = svar.get_all() - local vstr = "" - for k, v in pairs(vars) do - vstr = vstr .. k.."=".."\""..svar_escape(v).."\" " - end - dprint("Shell", vstr .. f.." "..tname) - local h = io.popen(vstr .. f.." "..tname, "r") - local output = h:read("*a"):gsub("\n$", "") - local ok, sig, code = h:close() - fh = io.open(tname, "r") - local stderr = fh:read("*a"):gsub("\n$", "") - fh:close() - os.remove(f) - os.remove(tname) - if not ok then - run_away_screaming(fpos, "Shell exit code "..code..", SIG_"..sig:upper().."\n"..stderr) - elseif #stderr > 0 then - bitch(fpos, stderr) - end - env.code = env.code .. output - end - local function put_svar(fpos, evar) - local e = svar.get(evar) - if not e then - run_away_screaming(fpos, "Enviroment variable `"..evar.."' does not exist!") - end - env.code = env.code .. e - end - local fenv = {} - for k, v in pairs(_G) do - fenv[k] = v - end - if gencode then - return lua_code - end - fenv._G = fenv - fenv._ENV = fenv - fenv.call_directive = call_directive - fenv.put_code = put_code - fenv.put_env = put_env - fenv.put_svar = put_svar - fenv.put_shell_out = put_shell_out - fenv._GENERATOR=env - local func = assert(load(lua_code, "=(generated code: "..ast.file..")", "t", fenv)) - func() - return env.code -end \ No newline at end of file