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
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.
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]
37 sys
.stderr
.write("usage: %s %s\n" % (__scriptname
, __usage
))
42 # Various paper sizes with .5 inch margins. Note: I used inches here because
43 # dot uses inches. Complain to AT&T.
46 'page' : "8.26, 11.69", 'rotate' : "", 'size' : "7.2, 10.6"
49 'page' : "8.26, 11.69", 'rotate' : "rotate = 90;", 'size' : "10.6, 7.2"
52 'page' : "8.5, 11", 'rotate' : "", 'size' : "7.5, 10"
55 'page' : "8.5, 11", 'rotate' : "rotate = 90;", 'size' : "10, 7.5"
57 papertypes
= { 'a4' : A4paper
, 'a4r' : A4Rpaper
,
58 'us' : USpaper
, 'usr' : USRpaper
}
63 optlist
, args
= getopt
.getopt(sys
.argv
[1:], "nkt:")
64 for opt
, arg
in optlist
:
70 if papertypes
.has_key(arg
):
71 paperdef
= papertypes
[arg
]
73 raise getopt
.error
, "unknown paper type '%s'" % arg
75 except getopt
.error
, msg
:
76 sys
.stderr
.write("%s: %s\n" % (__scriptname
, msg
))
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')
96 l
= sp
.split(string
.strip(line
))
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]
103 for i
in range(3, len(l
)):
104 calls
[node
].append(l
[i
])
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
:
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
: