~jimis/+junk/callgrind_parser

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/python3

# Copyleft 2012, Dimitrios Apostolou <jimis@gmx.net>
# Licence GPLv3+ http://www.gnu.org/licenses/gpl.html


# Read data files from this pattern.
# They are pickle files produced with "callgrind_parser.py -c"
DATA_FILE_TEMPLATE = "/path/to/results/{SNAP_VAR}/{TEST_VAR}.cg.pickle"

# Where the python source located, better don't serve this path with CGI exec
# allowed, or even don't serve it at all.
UNIT_DIR = "/path/to/callgrind_parser"

import sys
import string
import cgi
# import cgitb
# cgitb.enable ()

sys.path.append (UNIT_DIR)
# import * is necessary to import dummy classes for unpickling
from callgrind_svg import *
sys.path.pop ()


# dummy class for command line arguments of callgrind_svg.py
class FakeArgs:
	infile = None		# DATA_FILE_TEMPLATE + "r" CGI variable
	cached_input = True
	outfile = sys.stdout
	funcName = None		# "f" CGI variable
	funcNo = None		# "F" CGI variable
	typ = None		# "t" CGI variable
	query_string = ""
	def create_qs (self, funcName=None, funcNo=None, typ=None,
		       only_args=False):
		"""Produce the query string from the supplied arguments or if
		not supplied from the class' properties. If only_args then
		don't even bother with class' properties."""
		assert self.query_string != ""

		qs = self.query_string

		if (typ is not None):
			if (typ != "pos"):
				qs += "&amp;t=" + typ
		elif (not only_args and self.typ is not None):
			if (self.typ != "pos"):
				qs += "&amp;t=" + self.typ
		if (funcNo is not None):
			qs += "&amp;F=" + str (funcNo)
		elif (funcName is not None):
			qs += "&amp;f=" + funcName
		elif (not only_args):
			if (self.funcNo is not None):
				qs += "&amp;F=" + str (self.funcNo)
			elif (self.funcName is not None):
				qs += "&amp;f=" + self.funcName

		return qs

description = """
As a CGI accepts GET requests with the
following options:
	r=%s		id of file to open
	F=%d		function id number
	f=%s		function name
	t={pos,cost}	functions in pos or cost order
"""

form = cgi.FieldStorage ()
args = FakeArgs()
snap_var = form.getfirst ("snap")
test_var = form.getfirst ("test")
args.funcName = form.getfirst ("f")
f0 = form.getfirst ("F")
if (f0 is not None):
	args.funcNo = int (f0)
args.typ = form.getfirst ("t", "pos")
if (snap_var == None or test_var == None):
	# TODO err function printing HTML instead of SVG
	print ("You must specify snapshot name and test name!",
	       file=sys.stderr)
	exit (1)

# Disallow all relative paths in r_var before actually creating filename
# with DATA_FILE_TEMPLATE.
# For simplicity don't allow anything other than [a-zA-Z0-9_\-\.]
def variable_clean (v):
	good_chars = string.ascii_letters + string.digits + "_-."
	if (v.lstrip (good_chars) != "") or (".." in v):
		return False
	else:
		return True

if (not variable_clean (snap_var) or not variable_clean (test_var)):
	print ("Bad characters in snap or test variable!", file=sys.stderr)
	exit (1)

args.infile = DATA_FILE_TEMPLATE.format (SNAP_VAR=snap_var,
					 TEST_VAR=test_var)

# This will always be the base of our query string
args.query_string = "?snap=" + snap_var + "&amp;test=" + test_var

print ("Content-Type: image/svg+xml")
print ()
output_svg (sys.stdout, args)