From 29cdcb18099d58eaa2d9092f32d69ea37df144ad Mon Sep 17 00:00:00 2001 From: XeonSquared Date: Wed, 3 Jun 2020 09:55:22 +1000 Subject: [PATCH] added the preproc library, meaning PsychOS is nominally self-hosting --- build.lua | 3 +++ build.sh | 2 +- lib/preproc.lua | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ preproc.lua | 1 + 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 build.lua create mode 100644 lib/preproc.lua create mode 120000 preproc.lua diff --git a/build.lua b/build.lua new file mode 100644 index 0000000..39298ff --- /dev/null +++ b/build.lua @@ -0,0 +1,3 @@ +local preproc = require "preproc" +--local tA = {...} +preproc(...) diff --git a/build.sh b/build.sh index a20c7b7..1fbb833 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ LUA=${LUA:-lua} rm -r target/* mkdir -p target/doc &>/dev/null -$LUA luapreproc.lua module/init.lua target/init.lua +$LUA build.lua module/init.lua target/init.lua echo _OSVERSION=\"PsychOS 2.0a2-$(git rev-parse --short HEAD)\" > target/version.lua cat target/version.lua target/init.lua > target/tinit.lua mv target/tinit.lua target/init.lua diff --git a/lib/preproc.lua b/lib/preproc.lua new file mode 100644 index 0000000..1cdac5a --- /dev/null +++ b/lib/preproc.lua @@ -0,0 +1,69 @@ +local preproc = {} +preproc.directives = {} + +function preproc.parsewords(line) -- string -- table -- Returns a table of words from the string *line*, parsing quotes and escapes. + local rt = {""} + local escaped, quoted = false, false + for c in line:gmatch(".") do + if escaped then + rt[#rt] = rt[#rt]..c + elseif c == '"' or c == "'" then + quoted = not quoted + elseif c == "\\" then + escaped = true + elseif c:match("%s") and not quoted and rt[#rt]:len() > 0 then + rt[#rt+1] = "" + else + rt[#rt] = rt[#rt]..c + end + end + return rt +end + +function preproc.line(line) -- string -- -- Returns either a function - which can be called to get lines until it returns nil - or a string from processing *line* using preprocessor directives. + if line:match("^%-%-#") then + local directive, args = line:match("^%-%-#(%S+)%s(.+)") + print(directive,args) + local args = preproc.parsewords(args) + if preproc.directives[directive] then + return preproc.directives[directive](table.unpack(args)) + else + error("unknown preprocessor directive: "..directive) + end + else + return line + end +end + +function preproc.preproc(...) -- string -- string -- Returns the output from preprocessing the files listed in *...*. + local tA = {...} + local output = "" + for _,fname in ipairs(tA) do + local f,e = io.open(fname) + if not f then error("unable to open file "..fname..": "..e) end + for line in f:lines() do + local r = preproc.line(line) + if type(r) == "function" then + while true do + local rs = r() + if not rs then break end + output = output .. rs .. "\n" + end + else + output = output .. r .. "\n" + end + end + end + return output +end + +preproc.directives.include = preproc.preproc + +return setmetatable(preproc,{__call=function(_,...) + local tA = {...} + local out = table.remove(tA,#tA) + local f,e = io.open(out,"wb") + if not f then error("unable to open file "..out..": "..e) end + f:write(preproc.preproc(table.unpack(tA))) + f:close() +end}) diff --git a/preproc.lua b/preproc.lua new file mode 120000 index 0000000..fdc06ae --- /dev/null +++ b/preproc.lua @@ -0,0 +1 @@ +lib/preproc.lua \ No newline at end of file