chiark / gitweb /
e16239530632b035ed4b7e10f1397596e499d997
[disorder] / scripts / format-gcov-report
1 #! /usr/bin/env python
2 #
3 # This file is part of DisOrder.
4 # Copyright (C) 2007 Richard Kettlewell
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19 import re,sys,os,string
20
21 def fatal(msg):
22   sys.stderr.write("%s\n" % msg)
23   sys.exit(1)
24
25 def sgmlquotechar(c):
26   if c == '&' or c == '<' or ord(c) < 32 or ord(c) > 126:
27     return "&#%d;" % ord(c)
28   else:
29     return c
30
31 def sgmlquote(s):
32   return string.join(map(sgmlquotechar, s),'')
33
34 missing = {}
35 percent = {}
36 total_lines = 0
37 covered_lines = 0
38 args = sys.argv[1:]
39 htmldir = None
40 while len(args) > 0 and re.match("^--", args[0]):
41   if args[0] == "--html":
42     htmldir = args[1]
43     args = args[2:]
44   else:
45     fatal("unknown option '%s'" % args[0])
46 for s in args:
47   missing[s] = True
48
49 name = None
50 for line in sys.stdin:
51   line = line[:-1]
52   r = re.match("File ['`](?:.*/)?([^/]+.c)'", line)
53   if r:
54     name = r.group(1)
55     if name in missing:
56       del missing[name]
57   r = re.match("Lines executed:([0-9\\.]+)% of ([0-9]+)", line)
58   if r:
59     if name:
60       this_pc = float(r.group(1))
61       this_lines = int(r.group(2))
62       percent[name] = this_pc
63       total_lines += this_lines
64       covered_lines += this_lines * this_pc / 100.0
65     name = None
66
67 def cmp(a,b):
68   if percent[a] < percent[b]: return -1 
69   elif percent[a] > percent[b]: return 1
70   else: return 0
71
72 keys = percent.keys()
73 keys.sort(cmp)
74
75 if len(keys):
76   for k in keys:
77     print "%20s: %d%%" % (k, percent[k])
78   print "Total coverage: %d%%" % (100 * (covered_lines / total_lines))
79
80 if htmldir is not None and len(keys):
81   index = open(os.path.join(htmldir, "index.html"), "w")
82   index.write("<html><head><title>gcov report</title>\n")
83   index.write("<body><h1>gcov report</h1>\n")
84   index.write("<table><tr><th>File</th><th>Coverage</th></tr>\n")
85   for k in keys:
86     index.write("<tr><td><a href=\"%s.html\">%s</a><td>%d%%\n" %
87                 (sgmlquote(k), sgmlquote(k), percent[k]))
88   index.write("</table>\n")
89   index.write("<p>Total coverage: %d%%</p>\n" % (100 * (covered_lines / total_lines)))
90   missing_files = missing.keys()
91   missing_files.sort()
92   if len(missing_files) > 0:
93     index.write("<p>Missing files:</p>\n")
94     index.write("<ul>\n")
95     for mf in missing_files:
96       index.write("<li><a href=\"%s\">%s</a></li>\n" % (mf, mf))
97     index.write("</lu>\n")
98   for k in keys:
99     html = open(os.path.join(htmldir, "%s.html" % k), "w")
100     html.write("<html><head><title>%s</title>\n" % sgmlquote(k))
101     html.write("<body><h1>%s</h1>\n" % sgmlquote(k))
102     html.write("<pre>")
103     r = re.compile("^ *#####:.*")
104     for line in open("%s.gcov" % k, "r"):
105       if len(line) > 0 and line[-1] == '\n':
106         line = line[:-1]
107       if r.match(line):
108         html.write("<span style='background-color:#ffff00'>%s</span>\n" % sgmlquote(line))
109       else:
110         html.write("%s\n" % sgmlquote(line))
111     html.write("</pre>\n")