Operating system for OpenComputers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
3.4KB

  1. local preproc = {}
  2. preproc.directives = {}
  3. function preproc.parsewords(line) -- string -- table -- Returns a table of words from the string *line*, parsing quotes and escapes.
  4. local rt = {""}
  5. local escaped, quoted = false, false
  6. for c in line:gmatch(".") do
  7. if escaped then
  8. rt[#rt] = rt[#rt]..c
  9. elseif c == '"' or c == "'" then
  10. quoted = not quoted
  11. elseif c == "\\" then
  12. escaped = true
  13. elseif c:match("%s") and not quoted and rt[#rt]:len() > 0 then
  14. rt[#rt+1] = ""
  15. else
  16. rt[#rt] = rt[#rt]..c
  17. end
  18. end
  19. return rt
  20. end
  21. 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.
  22. if line:match("^%-%-#") then
  23. local directive, args = line:match("^%-%-#(%S+)%s(.+)")
  24. print(directive,args)
  25. local args = preproc.parsewords(args)
  26. if preproc.directives[directive] then
  27. return preproc.directives[directive](table.unpack(args))
  28. else
  29. error("unknown preprocessor directive: "..directive)
  30. end
  31. else
  32. return line
  33. end
  34. end
  35. function preproc.preproc(...) -- string -- string -- Returns the output from preprocessing the files listed in *...*.
  36. local tA = {...}
  37. local output = ""
  38. for _,fname in ipairs(tA) do
  39. local f,e = io.open(fname)
  40. if not f then error("unable to open file "..fname..": "..e) end
  41. for line in f:lines() do
  42. local r = preproc.line(line)
  43. if type(r) == "function" then
  44. while true do
  45. local rs = r()
  46. if not rs then break end
  47. output = output .. rs .. "\n"
  48. end
  49. else
  50. output = output .. r .. "\n"
  51. end
  52. end
  53. end
  54. return output
  55. end
  56. preproc.directives.include = preproc.preproc
  57. function preproc.directives.includelib(file, name) -- string string -- string -- Returns a preprocessed inlined library
  58. return string.format("package.loaded['%s'] = (function()\n%s\nend)()", name, preproc.preproc(file))
  59. end
  60. function preproc.directives.includepkgfile(package, file)
  61. if (_OSVERSION or ""):sub(1,7) == "PsychOS" then
  62. return preproc.preproc(string.format("/pkg/%s", file))
  63. else
  64. for path in (os.getenv("PSYCHOSPACKAGES") or "../PsychOSPackages"):gmatch("[^:]+") do
  65. local f = io.open(string.format("%s/%s/%s", path, package, file), "r")
  66. if f then
  67. f:close()
  68. return preproc.preproc(string.format("%s/%s/%s", path, package, file))
  69. end
  70. end
  71. end
  72. error(string.format("unable to locate file %s from package %s", file, package))
  73. end
  74. function preproc.directives.includepkglib(package, file, name) -- string string -- string -- Returns a preprocessed inlined library
  75. return string.format("package.loaded['%s'] = (function()\n%s\nend)()", name, preproc.directives.includepkgfile(package, file))
  76. end
  77. local minify = true
  78. local minifyFilters = {
  79. {"%-%-%[%[.-%]%]",""},
  80. {"%-%-.-\n","\n"},
  81. {"\n[ \t]+","\n"},
  82. {"%s?%.%.%s?",".."},
  83. {"%s?==%s?","=="},
  84. {"%s?~=%s?","~="},
  85. {"%s?>=%s?",">="},
  86. {"%s?<=%s?","<="},
  87. {"%s?>%s?",">"},
  88. {"%s?<%s?","<"},
  89. {"%s?=%s?","="},
  90. {"%s?,%s?",","},
  91. {",\n",","},
  92. {"\n\n+","\n"},
  93. {"[ \t]\n","\n"},
  94. {"%{%s+","{"},
  95. {"%s+%}","}"}
  96. }
  97. return setmetatable(preproc,{__call=function(_,...)
  98. local tA = {...}
  99. local out = table.remove(tA,#tA)
  100. local f,e = io.open(out,"wb")
  101. if not f then error("unable to open file "..out..": "..e) end
  102. local out = preproc.preproc(table.unpack(tA))
  103. if preproc.minify then
  104. local olen = #out
  105. for k,v in ipairs(minifyFilters) do
  106. out = out:gsub(v[1],v[2])
  107. end
  108. print(olen, #out)
  109. end
  110. f:write(out)
  111. f:close()
  112. end})