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.

70 lines
1.9KB

  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. return setmetatable(preproc,{__call=function(_,...)
  58. local tA = {...}
  59. local out = table.remove(tA,#tA)
  60. local f,e = io.open(out,"wb")
  61. if not f then error("unable to open file "..out..": "..e) end
  62. f:write(preproc.preproc(table.unpack(tA)))
  63. f:close()
  64. end})