define __KERNEL_STRICT_NAMES to avoid inclusion of kernel types on systems that carry...
[cake.git] / tools / cxref / contrib / xrefgraph.py
blob91ce7869043af181aeede2b9ee42e6def713cb54
1 #! /usr/bin/env python
3 # This program reads the output of cxref:
4 # http://www.gedanken.demon.co.uk/cxref/
5 # and produces input for Graphviz:
6 # http://www.research.att.com/sw/tools/graphviz/
7 # and of course you'll need Python:
8 # http://www.python.org/
9 # 10/12/99, Dr. Tom Holroyd, tomh@po.crl.go.jp
11 # Notes:
12 # * You can give a dummy file to cxref (or edit cxref.function) and use -k
13 # to include some specific functions you're interested in such as malloc(),
14 # etc., without including all the standard libraries.
15 # * If the graph is big, the node labels may be small. Try editing the .dot
16 # file and adding 'node [fontsize = 24]' or similar, or set 'ratio = auto'
17 # and let it output multiple pages. Also, see the dot user's guide.
19 import sys
20 import getopt
21 import re
22 import string
24 __usage = """[-k] [-n] [-t a4|a4r|us|usr] filename
25 Parse the cxref.function file produced by "cxref -xref-func <file>...", and
26 produce .dot file output suitable for use with graphviz programs like 'dot'
27 or 'neato' that will create a postscript version of the call graph. If -k
28 is specified, only nodes that are 'known', in the sense of being defined
29 within the group of files sent to cxref, are output. Otherwise all called
30 functions are included, e.g., stdio functions, etc. If -n is specified, the
31 node is labeled with the file where the function is defined, if known. -t
32 sets the paper size and orientation (a4r default). Send the output of this
33 script to, e.g., dot -Tps > xref.ps"""
35 __scriptname = sys.argv[0]
36 def printusage():
37 sys.stderr.write("usage: %s %s\n" % (__scriptname, __usage))
39 nodeflag = 0
40 knownflag = 0
42 # Various paper sizes with .5 inch margins. Note: I used inches here because
43 # dot uses inches. Complain to AT&T.
45 A4paper = {
46 'page' : "8.26, 11.69", 'rotate' : "", 'size' : "7.2, 10.6"
48 A4Rpaper = {
49 'page' : "8.26, 11.69", 'rotate' : "rotate = 90;", 'size' : "10.6, 7.2"
51 USpaper = {
52 'page' : "8.5, 11", 'rotate' : "", 'size' : "7.5, 10"
54 USRpaper = {
55 'page' : "8.5, 11", 'rotate' : "rotate = 90;", 'size' : "10, 7.5"
57 papertypes = { 'a4' : A4paper, 'a4r' : A4Rpaper,
58 'us' : USpaper, 'usr' : USRpaper }
60 paperdef = A4Rpaper
62 try:
63 optlist, args = getopt.getopt(sys.argv[1:], "nkt:")
64 for opt, arg in optlist:
65 if opt == '-n':
66 nodeflag = 1
67 if opt == '-k':
68 knownflag = 1
69 if opt == '-t':
70 if papertypes.has_key(arg):
71 paperdef = papertypes[arg]
72 else:
73 raise getopt.error, "unknown paper type '%s'" % arg
75 except getopt.error, msg:
76 sys.stderr.write("%s: %s\n" % (__scriptname, msg))
77 printusage()
78 sys.exit(1)
80 if len(args) != 1:
81 printusage()
82 sys.exit(1)
84 filename = args[0]
86 profile = open(filename).readlines()
88 # Build the call tree.
90 nodelist = [] # list of known nodes
91 calls = {} # key: node, value: call list (includes unknown nodes)
92 filename = {} # key: node, value: filename
94 sp = re.compile(r'\s%|\s')
95 for line in profile:
96 l = sp.split(string.strip(line))
97 node = l[1]
98 nodelist.append(node)
99 if filename.has_key(node) or calls.has_key(node):
100 sys.stderr.write("duplicate function '%s', ignoring previous definition\n" % node)
101 filename[node] = l[0]
102 calls[node] = []
103 for i in range(3, len(l)):
104 calls[node].append(l[i])
106 # Output the graph.
108 print 'digraph call {'
109 print 'page = "%(page)s"; %(rotate)s size = "%(size)s"' % paperdef
110 print 'ratio = fill; center = 1'
112 for node in nodelist:
113 if nodeflag:
114 label = '%s\\n%s' % (node, filename[node])
115 print '%s [label = "%s"]' % (node, label)
116 for n in calls[node]:
117 if not knownflag or n in nodelist:
118 print node, '->', n
120 print '}'