#! /usr/bin/python2
import os.path
import sys
import shlex
import re

from headerutils import *

header_roots = { }
extra_edges = list()
verbose = False
verbosity = 0
nodes = list()

def unpretty (name):
  if name[-2:] == "_h":
    name = name[:-2] + ".h"
  return name.replace("_", "-")

def pretty_name (name):
  name = os.path.basename (name)
  return name.replace(".","_").replace("-","_").replace("/","_").replace("+","_");

depstring = ("In file included from", "                 from")

# indentation indicates nesting levels of included files
ignore = [ "coretypes_h",
             "insn_modes_h",
             "signop_h",
             "wide_int_h",
             "wide_int_print_h",
             "insn_modes_inline_h",
             "machmode_h",
             "double_int_h",
             "real_h",
             "fixed_value_h",
             "hash_table_h",
               "statistics_h",
               "ggc_h",
               "vec_h",
               "hashtab_h",
               "inchash_h",
               "mem_stats_traits_h",
               "hash_map_traits_h",
               "mem_stats_h",
               "hash_map_h",
             "hash_set_h",
             "input_h",
               "line_map_h",
             "is_a_h",
           "system_h",
           "config_h" ]

def process_log_file (header, logfile):
  if header_roots.get (header) != None:
    print "Error: already processed log file: " + header + ".log"
    return
  hname = pretty_name (header)
  header_roots[hname] = { }
  
  sline = list();
  incfrom = list()
  newinc = True
  for line in logfile:
    if len (line) > 21 and line[:21] in depstring:
      if newinc:
        incfrom = list()
        newinc = False
      fn = re.findall(ur".*/(.*?):", line)
      if len(fn) != 1:
        continue
      if fn[0][-2:] != ".h":
        continue
      n = pretty_name (fn[0])
      if n not in ignore:
        incfrom.append (n)
      continue
    newinc = True
    note = re.findall (ur"^.*note: (.*)", line)
    if len(note) > 0:
      sline.append (("note", note[0]))
    else:
      err_msg = re.findall (ur"^.*: error: (.*)", line)
      if len(err_msg) == 1:
        msg = err_msg[0]
        if (len (re.findall("error: forward declaration", line))) != 0:
          continue
        path = re.findall (ur"^(.*?):.*error: ", line)
        if len(path) != 1:
          continue
        if path[0][-2:] != ".h":
          continue
        fname = pretty_name (path[0])
        if fname in ignore or fname[0:3] == "gt_":
          continue
        sline.append (("error", msg, fname, incfrom))

  print str(len(sline)) + " lines to process"
  lastline = "note"
  for line in sline:
    if line[0] != "note" and lastline[0] == "error":
      fname = lastline[2]
      msg = lastline[1]
      incfrom = lastline[3]
      string = ""
      ofname = fname
      if len(incfrom) != 0:
        for t in incfrom:
          string = string + t + " : "
          ee = (fname, t)
          if ee not in extra_edges:
            extra_edges.append (ee)
          fname = t
          print string

      if hname not in nodes:
        nodes.append(hname)
      if fname not in nodes:
        nodes.append (ofname)
      for y in incfrom:
        if y not in nodes:
          nodes.append (y)


      if header_roots[hname].get(fname) == None:
        header_roots[hname][fname] = list()
      if msg not in header_roots[hname][fname]:
        print string + ofname + " : " +msg
        header_roots[hname][fname].append (msg)
    lastline = line;


dotname = "graph.dot"
graphname = "graph.png"


def build_dot_file (file_list):
  output = open(dotname, "w")
  output.write ("digraph incweb {\n");
  for x in file_list:
    if os.path.exists (x) and x[-4:] == ".log":
      header =  x[:-4]
      logfile = open(x).read().splitlines()
      process_log_file (header, logfile)
    elif os.path.exists (x + ".log"):
      logfile = open(x + ".log").read().splitlines()
      process_log_file (x, logfile)

  for n in nodes:
    fn = unpretty(n)
    label = n + " [ label = \"" + fn  + "\" ];"
    output.write (label + "\n")
    if os.path.exists (fn):
      h = open(fn).read().splitlines()
      for l in h:
        t = find_pound_include (l, True, False)
        if t != "":
          t = pretty_name (t)
          if t in ignore or t[-2:] != "_h":
            continue
          if t not in nodes:
            nodes.append (t)
          ee = (t, n)
          if ee not in extra_edges:
            extra_edges.append (ee)

  depcount = list()
  for h in header_roots:
    for dep in header_roots[h]:
      label = " [ label = "+ str(len(header_roots[h][dep])) + " ];"
      string = h + " -> " + dep + label
      output.write (string + "\n");
      if verbose:
        depcount.append ((h, dep, len(header_roots[h][dep])))

  for ee in extra_edges:
    string = ee[0] + " -> " + ee[1] + "[ color=red ];"
    output.write (string + "\n");

  
  if verbose:
    depcount.sort(key=lambda tup:tup[2])
    for x in depcount:
      print " ("+str(x[2])+ ") : " + x[0] + " -> " + x[1]
      if (x[2] <= verbosity):
        for l in header_roots[x[0]][x[1]]:
          print "            " + l

  output.write ("}\n");


files = list()
dohelp = False
edge_thresh = 0
for arg in sys.argv[1:]:
  if arg[0:2] == "-o":
    dotname = arg[2:]+".dot"
    graphname = arg[2:]+".png"
  elif arg[0:2] == "-h":
    dohelp = True
  elif arg[0:2] == "-v":
    verbose = True
    if len(arg) > 2:
      verbosity = int (arg[2:])
      if (verbosity == 9):
        verbosity = 9999
  elif arg[0:1] == "-":
    print "Unrecognized option " + arg
    dohelp = True
  else:
    files.append (arg)
    
if len(sys.argv) == 1:
  dohelp = True

if dohelp:
  print "Parses the log files from the reduce-headers tool to generate"
  print "dependency graphs for the include web for specified files."
  print "Usage:  [-nnum] [-h] [-v[n]] [-ooutput] file1 [[file2] ... [filen]]"
  print "       -ooutput : Specifies output to output.dot and output.png"
  print "                  Defaults to 'graph.dot and graph.png"
  print "       -vn : verbose mode, shows the number of connections, and if n"
  print "             is specified, show the messages if # < n. 9 is infinity"
  print "       -h : help"
else:
  print files
  build_dot_file (files)
  os.system ("dot -Tpng " + dotname + " -o" + graphname)


