2020-06-07 23:29:26 +10:00
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
2023-08-01 17:58:27 +10:00
function preproc . directives . includelib ( file , name ) -- string string -- string -- Returns a preprocessed inlined library
2023-08-03 12:15:03 +10:00
return string.format ( " package.loaded['%s'] = (function() \n %s \n end)() " , name , preproc.preproc ( file ) )
2023-08-01 17:58:27 +10:00
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
2023-08-03 12:15:03 +10:00
return string.format ( " package.loaded['%s'] = (function() \n %s \n end)() " , name , preproc.directives . includepkgfile ( package , file ) )
2023-08-01 17:58:27 +10:00
end
2023-08-04 20:32:42 +10:00
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+%} " , " } " }
}
2020-06-07 23:29:26 +10:00
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
2023-08-04 20:32:42 +10:00
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 )
2020-06-07 23:29:26 +10:00
f : close ( )
end } )