Fri, 13 Nov 2009 16:32:33 +0000
Add README and COPYING files
1 | 1 | -- Copyright (C) 2008-2009 Matthew Wild |
2 | -- | |
3 | -- This project is MIT/X11 licensed. Please see the | |
4 | -- COPYING file in the source package for more information. | |
0 | 5 | |
6 | local keywords = { "function", "for", "if", "elseif", "then", "else", "do", "repeat", "until", "end", "return", "true", "false", "and", "not", "or", "local", "nil", "break" } | |
7 | for _, keyword in ipairs(keywords) do keywords[keyword] = true; end | |
8 | ||
9 | local ops = {}; | |
10 | ||
11 | local bytelisting, err = io.popen("luac -l -p "..arg[1]); | |
12 | if not bytelisting then print(err); return 1; end | |
13 | ||
14 | for line in bytelisting:lines() do | |
15 | local opnum, linenum, opname, comments = line:match("^\t(%d+)%s*%[(%d+)%]%s*(%u+)[^;]*;? ?(.*)$"); | |
16 | if opnum then | |
17 | linenum = tonumber(linenum); | |
18 | -- print(string.format("opnum: %d line: %d op: %s ; %s", opnum, linenum, opname, comments)); | |
19 | if not ops[linenum] then | |
20 | ops[linenum] = { }; | |
21 | if ops[linenum-1] then | |
22 | table.sort(ops[linenum-1], function (a,b) return a.comment and b.comment and #a.comment > #b.comment; end); | |
23 | end | |
24 | end | |
25 | table.insert(ops[linenum], { name = opname, comment = comments }); | |
26 | end | |
27 | end | |
28 | ||
29 | local test_coverage = {}; | |
30 | ||
31 | local test_report, test_report_err = io.open("tests/reports/coverage_"..arg[1]:gsub("^%W", ""):gsub("%W+", "_")..".report"); | |
32 | if test_report then | |
33 | for line in test_report:lines() do | |
34 | local f, linenum, test, success = line:match("^(.-)|(.-)|(.-)|(.-)$"); | |
35 | if linenum and success then | |
36 | test_coverage[tonumber(linenum)] = success; | |
37 | else | |
38 | io.stderr:write("Warning: Can't parse this: [[", line, "]] in test report\n"); | |
39 | end | |
40 | end | |
41 | else | |
42 | test_coverage = nil; | |
43 | end | |
44 | ||
45 | ||
46 | ||
47 | local linenum = 1; | |
48 | local html_spaces = { ["\t"] = " ", [" "] = " " }; | |
49 | function escape_html(s) | |
50 | return (s and s:gsub("[^%w]", { ["<"] = "<", [">"] = ">", ["&"] = "&", ["\""] = """, ["'"] = "'" })) or ""; | |
51 | end | |
52 | ||
53 | function escape_pattern(s) | |
54 | return s:gsub("(%p)", "%%%1"); | |
55 | end | |
56 | ||
57 | local sub; | |
58 | ||
59 | print("<html><head><title>"..escape_html(arg[1]).."</title><style type='text/css'>"); | |
60 | print [[ | |
61 | .getglobal { color:#cc0000 !important; text-decoration:underline; } | |
62 | .setglobal { color:#ff0000; font-weight:bold; text-decoration:underline; } | |
63 | .getupval { color:#00cc00; } | |
64 | .nop { color:#cccccc; } | |
65 | .keyword { color:#0000cc; } | |
66 | .comment, .comment .keyword { color:#007733; } | |
67 | .string, .string * { color:#007755; } | |
68 | ||
69 | td .test-false, .test-false { background-color:#ffa6be !important; display:block; width:100%; } | |
70 | td .test-true, .test-true { background-color:#beffa6; display:block; width:100%; } | |
71 | td .test-miss, .test-miss { background-color:#a6beff; display:block; width:100%; } | |
72 | ||
73 | table { border-collapse: collapse; } | |
74 | span, tr, *, table { padding:2px; } | |
75 | td { padding:0px; padding-right:2em; } | |
76 | ]] | |
77 | print("</style></head><body>\n<br/>\n<table>"); | |
78 | for line in io.lines(arg[1]) do | |
79 | line = " "..line:gsub("%s", html_spaces).." "; | |
80 | line = line:gsub("FIXME:?", "<b>%1</b>"); | |
81 | line = line:gsub("TODO:?", "<b>%1</b>"); | |
82 | line = line:gsub("%-%-.*$", "<span class='comment'>%1</span>"); | |
83 | line = line:gsub("\".-[^\\]\"", "<span class='string'>%1</span>"); | |
84 | if ops[linenum] then | |
85 | for _, op in pairs(ops[linenum]) do | |
86 | if op.comment and #op.comment > 0 and op.name ~= "JMP" then | |
87 | --print("Replacing "..escape_pattern(op.comment).."("..op.comment..") for "..op.name); | |
88 | line, sub = line:gsub("([^%w_])("..escape_pattern(op.comment)..")([^%w_])", "%1<span class='"..op.name:lower().."'>"..escape_html(op.comment).."</span>%3"); | |
89 | if sub == 0 and op.name == "GETTABLE" then | |
90 | --print("Trying again..."); | |
91 | local id = op.comment:match("[%w_]+"); | |
92 | if id then | |
93 | --print("Got "..id); | |
94 | line = line:gsub(escape_pattern("."..id), ".<span class='"..op.name:lower().."'>"..escape_html(id).."</span>"); | |
95 | end | |
96 | end | |
97 | else | |
98 | --print("??", tostring(op.comment), tostring(#op.comment)); | |
99 | end | |
100 | end | |
101 | line = line:gsub("[%w_]+", function (id) if keywords[id] then return "<span class='keyword'>"..id.."</span>"; end end); | |
102 | local classes = { "line" }; | |
103 | ||
104 | if test_coverage and test_coverage[linenum] ~= nil then | |
105 | table.insert(classes, "test-"..test_coverage[linenum]); | |
106 | end | |
107 | print("<tr><td><span class='"..table.concat(classes, " ").."'>"..linenum.."</span></td><td>", line, "</td></tr>"); | |
108 | else | |
109 | line = line:gsub("[%w_]+", function (id) if keywords[id] then return "<span class='keyword'>"..id.."</span>"; end end); | |
110 | print("<tr><td><span class='line nop'>"..linenum.."</span></td><td>", line, "</td></tr>"); | |
111 | end | |
112 | linenum = linenum + 1; | |
113 | end | |
114 | ||
115 | print("</table>\n</body>\n</html>"); |