1ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#!/usr/bin/env python
2ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
3ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#===- cindex-includes.py - cindex/Python Inclusion Graph -----*- python -*--===#
4ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#
5ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#                     The LLVM Compiler Infrastructure
6ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#
7ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao# This file is distributed under the University of Illinois Open Source
8ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao# License. See LICENSE.TXT for details.
9ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#
10ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#===------------------------------------------------------------------------===#
11ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
12ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao"""
13ea285162342df160e7860e26528bc7110bc6c0cdShih-wei LiaoA simple command line tool for dumping a Graphviz description (dot) that
14ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaodescribes include dependencies.
15ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao"""
16ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
17ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaodef main():
18ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    import sys
19ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    from clang.cindex import Index
20ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
21ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    from optparse import OptionParser, OptionGroup
22ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
23ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    parser = OptionParser("usage: %prog [options] {filename} [clang-args*]")
24ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    parser.disable_interspersed_args()
25ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    (opts, args) = parser.parse_args()
26ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    if len(args) == 0:
27ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        parser.error('invalid number arguments')
28ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
29ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    # FIXME: Add an output file option
30ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    out = sys.stdout
31ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
32ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    index = Index.create()
33ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    tu = index.parse(None, args)
34ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    if not tu:
35ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        parser.error("unable to load input")
36ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
37ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    # A helper function for generating the node name.
38ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    def name(f):
39ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        if f:
40ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao            return "\"" + f.name + "\""
41ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
42ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    # Generate the include graph
43ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    out.write("digraph G {\n")
44ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    for i in tu.get_includes():
45ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        line = "  ";
46ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        if i.is_input_file:
47ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao            # Always write the input file as a node just in case it doesn't
48ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao            # actually include anything. This would generate a 1 node graph.
49ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao            line += name(i.include)
50ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        else:
51ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao            line += '%s->%s' % (name(i.source), name(i.include))
52ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        line += "\n";
53ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        out.write(line)
54ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    out.write("}\n")
55ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
56ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoif __name__ == '__main__':
57ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    main()
58ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
59