#!/usr/bin/python
#
# This script is used to analyze, tabulate, and graph data generated by
# the JAM weaver and by JAMScript performance instrumentation. It was
# used to produce figures presented in the experimental results section
# of ``Efficient Runtime Enforcement Techniques for Policy Weaving,''
# published at FSE 2014.
#

import sys
MAJOR = sys.version_info[0]

import os
import re
import subprocess
from subprocess import PIPE
import shutil
import time
import imp
from optparse import OptionParser
#import warnings

import grapher

from resultsutil import AppStats, SourceVariant, Action, Section

def collect_results_from_file(filepath, results):
  lns = cfg.get_lines(filepath)
    
  # Detect whether the file contains any results via the format.
  # %%% Does this short-circuit when it finds a match?
  isresults = any([True for ln in lns if ln.startswith(cfg.PROFILE_MARKER)])
  if isresults:
    results.extend(lns)

def collect_results(filelist):
  lines = []
  for respath in filelist:
    assert os.path.exists(respath), "Results source does not exist: %s" % respath
    collect_results_from_file(respath, lines)

  if len(lines) == 0:
    cfg.warn("No results found")

  return lines
#/collect_results

def collect_separate_results(filelist):
  results = []
  for respath in filelist:
    lines = []
    assert os.path.exists(respath), "Results source does not exist: %s" % respath
    collect_results_from_file(respath, lines)
    if len(lines) == 0:
      cfg.warn("No results found for file: %s" % respath)
    results.append(lines)

  return results
#/collect_separate_results

def parse_profile_header(ln):
  assert ln.startswith(cfg.PROFILE_MARKER)
  action = ln[len(cfg.PROFILE_MARKER):-len(cfg.PROFILE_MARKER_TAIL)]
  if len(action) < 1:
    cfg.err("Action name is empty: %s" % ln)
  return action
#/parse_profile_header

def parse_section_header(ln):
  assert ln.startswith(cfg.SECTION_MARKER)
  info = None
  section = ln[len(cfg.SECTION_MARKER):-len(cfg.SECTION_MARKER)]
  if section.startswith(cfg.TIME_SECTION_NAME):
    info = section[len(cfg.TIME_SECTION_NAME):]
    info = info.lstrip(": ")
    section = cfg.TIME_SECTION_NAME
  if len(section) < 1:
    cfg.err("Section name is empty: %s" % ln)

  return section, info
#/parse_section_header

def parse_stack(lines):
  appinfo = None
  stackinfo = [] # Will contain (file, lineno) pairs in order.
  for ln in lines:
    parts = ln.split(None)