122 lines
3.4 KiB
Lua
122 lines
3.4 KiB
Lua
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
|
|
|
|
function preproc.directives.includelib(file, name) -- string string -- string -- Returns a preprocessed inlined library
|
|
return string.format("package.loaded['%s'] = (function()\n%s\nend)()", name, preproc.preproc(file))
|
|
end
|
|
|
|
function preproc.directives.includepkgfile(package, file)
|
|
if (_OSVERSION or ""):sub(1,7) == "PsychOS" then
|
|
return preproc.preproc(string.format("/pkg/%s", file))
|
|
else
|
|
for path in (os.getenv("PSYCHOSPACKAGES") or "../PsychOSPackages"):gmatch("[^:]+") do
|
|
local f = io.open(string.format("%s/%s/%s", path, package, file), "r")
|
|
if f then
|
|
f:close()
|
|
return preproc.preproc(string.format("%s/%s/%s", path, package, file))
|
|
end
|
|
end
|
|
end
|
|
error(string.format("unable to locate file %s from package %s", file, package))
|
|
end
|
|
|
|
function preproc.directives.includepkglib(package, file, name) -- string string -- string -- Returns a preprocessed inlined library
|
|
return string.format("package.loaded['%s'] = (function()\n%s\nend)()", name, preproc.directives.includepkgfile(package, file))
|
|
end
|
|
|
|
local minify = true
|
|
local minifyFilters = {
|
|
{"%-%-%[%[.-%]%]",""},
|
|
{"%-%-.-\n","\n"},
|
|
{"\n[ \t]+","\n"},
|
|
{"%s?%.%.%s?",".."},
|
|
{"%s?==%s?","=="},
|
|
{"%s?~=%s?","~="},
|
|
{"%s?>=%s?",">="},
|
|
{"%s?<=%s?","<="},
|
|
{"%s?>%s?",">"},
|
|
{"%s?<%s?","<"},
|
|
{"%s?=%s?","="},
|
|
{"%s?,%s?",","},
|
|
{",\n",","},
|
|
{"\n\n+","\n"},
|
|
{"[ \t]\n","\n"},
|
|
{"%{%s+","{"},
|
|
{"%s+%}","}"}
|
|
}
|
|
|
|
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
|
|
local out = preproc.preproc(table.unpack(tA))
|
|
if preproc.minify then
|
|
local olen = #out
|
|
for k,v in ipairs(minifyFilters) do
|
|
out = out:gsub(v[1],v[2])
|
|
end
|
|
print(olen, #out)
|
|
end
|
|
f:write(out)
|
|
f:close()
|
|
end})
|