1 #! /usr/bin/env python3
2
3 """Transform gprof(1) output into useful HTML."""
4
5 import html
6 import os
7 import re
8 import sys
9 import webbrowser
10
11 header = """\
12 <html>
13 <head>
14 <title>gprof output (%s)</title>
15 </head>
16 <body>
17 <pre>
18 """
19
20 trailer = """\
21 </pre>
22 </body>
23 </html>
24 """
25
26 def add_escapes(filename):
27 with open(filename, encoding="utf-8") as fp:
28 for line in fp:
29 yield html.escape(line)
30
31 def 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+)(( <cycle.*>)? \[\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
76 def 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", encoding="utf-8") as output:
83 gprof2html(input, output, filename)
84 webbrowser.open("file:" + os.path.abspath(outputfilename))
85
86 if __name__ == '__main__':
87 main()