1#! /usr/bin/env python3
2
3"""Transform gprof(1) output into useful HTML."""
4
5import html
6import os
7import re
8import sys
9import webbrowser
10
11header = """\
12<html>
13<head>
14  <title>gprof output (%s)</title>
15</head>
16<body>
17<pre>
18"""
19
20trailer = """\
21</pre>
22</body>
23</html>
24"""
25
26def add_escapes(filename):
27    with open(filename) as fp:
28        for line in fp:
29            yield html.escape(line)
30
31def gprof2html(input, output, filename):
32    output.write(header % filename)
33    for line in input:
34        output.write(line)
35        if line.startswith(" time"):
36            break
37    labels = {}
38    for line in input:
39        m = re.match(r"(.*  )(\w+)\n", line)
40        if not m:
41            output.write(line)
42            break
43        stuff, fname = m.group(1, 2)
44        labels[fname] = fname
45        output.write('%s<a name="flat:%s" href="#call:%s">%s</a>\n' %
46                     (stuff, fname, fname, fname))
47    for line in input:
48        output.write(line)
49        if line.startswith("index % time"):
50            break
51    for line in input:
52        m = re.match(r"(.*  )(\w+)(( &lt;cycle.*&gt;)? \[\d+\])\n", line)
53        if not m:
54            output.write(line)
55            if line.startswith("Index by function name"):
56                break
57            continue
58        prefix, fname, suffix = m.group(1, 2, 3)
59        if fname not in labels:
60            output.write(line)
61            continue
62        if line.startswith("["):
63            output.write('%s<a name="call:%s" href="#flat:%s">%s</a>%s\n' %
64                         (prefix, fname, fname, fname, suffix))
65        else:
66            output.write('%s<a href="#call:%s">%s</a>%s\n' %
67                         (prefix, fname, fname, suffix))
68    for line in input:
69        for part in re.findall(r"(\w+(?:\.c)?|\W+)", line):
70            if part in labels:
71                part = '<a href="#call:%s">%s</a>' % (part, part)
72            output.write(part)
73    output.write(trailer)
74
75
76def main():
77    filename = "gprof.out"
78    if sys.argv[1:]:
79        filename = sys.argv[1]
80    outputfilename = filename + ".html"
81    input = add_escapes(filename)
82    with open(outputfilename, "w") as output:
83        gprof2html(input, output, filename)
84    webbrowser.open("file:" + os.path.abspath(outputfilename))
85
86if __name__ == '__main__':
87    main()
88