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