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
31
32def main():
33    filename = "gprof.out"
34    if sys.argv[1:]:
35        filename = sys.argv[1]
36    outputfilename = filename + ".html"
37    input = add_escapes(filename)
38    output = open(outputfilename, "w")
39    output.write(header % filename)
40    for line in input:
41        output.write(line)
42        if line.startswith(" time"):
43            break
44    labels = {}
45    for line in input:
46        m = re.match(r"(.*  )(\w+)\n", line)
47        if not m:
48            output.write(line)
49            break
50        stuff, fname = m.group(1, 2)
51        labels[fname] = fname
52        output.write('%s<a name="flat:%s" href="#call:%s">%s</a>\n' %
53                     (stuff, fname, fname, fname))
54    for line in input:
55        output.write(line)
56        if line.startswith("index % time"):
57            break
58    for line in input:
59        m = re.match(r"(.*  )(\w+)(( &lt;cycle.*&gt;)? \[\d+\])\n", line)
60        if not m:
61            output.write(line)
62            if line.startswith("Index by function name"):
63                break
64            continue
65        prefix, fname, suffix = m.group(1, 2, 3)
66        if fname not in labels:
67            output.write(line)
68            continue
69        if line.startswith("["):
70            output.write('%s<a name="call:%s" href="#flat:%s">%s</a>%s\n' %
71                         (prefix, fname, fname, fname, suffix))
72        else:
73            output.write('%s<a href="#call:%s">%s</a>%s\n' %
74                         (prefix, fname, fname, suffix))
75    for line in input:
76        for part in re.findall(r"(\w+(?:\.c)?|\W+)", line):
77            if part in labels:
78                part = '<a href="#call:%s">%s</a>' % (part, part)
79            output.write(part)
80    output.write(trailer)
81    output.close()
82    webbrowser.open("file:" + os.path.abspath(outputfilename))
83
84if __name__ == '__main__':
85    main()
86