1#! /usr/bin/python2
2import os.path
3import sys
4import shlex
5import re
6
7from headerutils import *
8
9def pretty_name (name):
10  return name.replace(".","_").replace("-","_").replace("/","_").replace("+","_");
11
12
13include_files = list()
14edges = 0
15one_c = False
16clink = list()
17noterm = False
18
19def build_inclist (output, filen):
20  global edges
21  global one_c
22  global clink
23  global noterm
24  inc = build_include_list (filen)
25  if one_c and filen[-2:] == ".c":
26    pn = "all_c"
27  else:
28    pn = pretty_name(filen)
29  for nm in inc:
30    if pn == "all_c":
31      if nm not in clink:
32        if len(build_include_list(nm)) != 0 or not noterm:
33          output.write (pretty_name(nm) + " -> " + pn + ";\n")
34          edges = edges + 1
35          if nm not in include_files:
36            include_files.append(nm)
37        clink.append (nm)
38    else:
39      output.write (pretty_name(nm) + " -> " + pn + ";\n")
40      edges = edges + 1
41      if nm not in include_files:
42        include_files.append(nm)
43  return len(inc) == 0
44
45dotname = "graph.dot"
46graphname = "graph.png"
47
48def build_dot_file (file_list):
49  global one_c
50  output = open(dotname, "w")
51  output.write ("digraph incweb {\n");
52  if one_c:
53    output.write ("all_c [shape=box];\n");
54  for x in file_list:
55    if x[-2:] == ".h":
56      include_files.append (x)
57    elif os.path.exists (x):
58      build_inclist (output, x)
59      if not one_c:
60        output.write (pretty_name (x) + "[shape=box];\n")
61
62  for x in include_files:
63    term = build_inclist (output, x)
64    if term:
65      output.write (pretty_name(x) + " [style=filled];\n")
66
67  output.write ("}\n");
68
69
70files = list()
71dohelp = False
72edge_thresh = 0
73for arg in sys.argv[1:]:
74  if arg[0:2] == "-o":
75    dotname = arg[2:]+".dot"
76    graphname = arg[2:]+".png"
77  elif arg[0:2] == "-h":
78    dohelp = True
79  elif arg[0:2] == "-a":
80    one_c = True
81    if arg[0:3] == "-at":
82      noterm = True
83  elif arg[0:2] == "-f":
84    if not os.path.exists (arg[2:]):
85      print "Option " + arg +" doesn't specify a proper file"
86      dohelp = True
87    else:
88      sfile = open (arg[2:], "r")
89      srcdata = sfile.readlines()
90      sfile.close()
91      for x in srcdata:
92        files.append(x.rstrip())
93  elif arg[0:2] == "-n":
94    edge_thresh = int (arg[2:])
95  elif arg[0:1] == "-":
96    print "Unrecognized option " + arg
97    dohelp = True
98  else:
99    files.append (arg)
100
101if len(sys.argv) == 1:
102  dohelp = True
103
104if dohelp:
105  print "Generates a graph of the include web for specified files."
106  print "Usage:  [-finput_file] [-h] [-ooutput] [file1 ... [filen]]"
107  print "  -finput_file : Input file containing a list of files to process."
108  print "  -ooutput : Specifies output to output.dot and output.png."
109  print "             defaults to graph.dot and graph.png."
110  print "  -nnum : Specifies the # of edges beyond which sfdp is invoked. def=0."
111  print "  -a : Aggregate all .c files to 1 file.  Shows only include web."
112  print "  -at : Aggregate, but don't include terminal.h to .c links."
113  print "  -h : Print this help."
114else:
115  print files
116  build_dot_file (files)
117  if edges > edge_thresh:
118    os.system ("sfdp -Tpng " + dotname + " -o" + graphname)
119  else:
120    os.system ("dot -Tpng " + dotname + " -o" + graphname)
121
122
123