#!/usr/bin/python

print; print "---- pEventcnv4.py ----"

import re
import testmod
from cleave import cleave
from parseerror import ParseError
from seqbycategs import SeqByCategs
from cat import *

from eventdef import Eventdef, parseEventdefFile, test_parseEventdefRelation

class Eca:
  """Parsing output of eventcnv -e all"""
  def __init__(self):
    self.vIb = []
    self.vNRun = []
    self.sbByIb = {}

def parseBucketList(eca, ws):
  """ bucket: 0001 0002 0003 ..."""
  if eca.vIb != []:
    raise ParseError(" ".join(ws), "BucketList", "already got a vIb")
  if len(ws) < 2:
    raise ParseError(" ".join(ws), "BucketList", "len<2")
  eca.vIb = ws[1:]

def parseBucketRun(eca, ws):
  """    run:    3    3    1 ..."""
  if eca.vNRun != []:
    raise ParseError(" ".join(ws), "BucketList", "already got a vNRun")
  if len(ws) <= 1:
    raise ParseError(" ".join(ws), "BucketRun", "len<=1")
  eca.vNRun = ws[1:]

def parseEventStop(eca, ws):
  s = " ".join(ws[0:4])
  if s != "event clock stopped at":
    raise ParseError(s, "EventStop", "should say 'event clock stopped at'")

def parseBucketName(eca, ws):
  #print len(ws)
  #print `ws`
  if len(ws) != 2:
    raise ParseError(" ".join(ws), "BucketName", "len!=2")
    #return
  ib, sb = ws[0], ws[1]
  
  if ib in eca.sbByIb:
    raise ParseError(" ".join(ws), "BucketName", "already seen ib %d" % ib)
  eca.sbByIb[ib] = sb

def parseEcaFile(file, sEKOfsET):
  eca = Eca()
  parsetriggers = {
    "bucket:" : parseBucketList,
    "run:" : parseBucketRun,
    "event" : parseEventStop,
  }
    
  for l in file.readlines():
    ws = l.split()
    if len(ws) == 0:
      pass
    elif ws[0] in parsetriggers:
      parser = parsetriggers[ws[0]]
      parser(eca, ws)
    else:
      parseBucketName(eca, ws)

  b1s = []
  bs = zip(eca.vIb, eca.vNRun)
  for b in bs:
    if b[0] in eca.sbByIb:
      sb = eca.sbByIb[b[0]]
      # a bucket name is an EventType
      sET = sb
      sEK = sEKOfsET[sET]
    else:
      sb = "????"
      sEK = ""
    
    b1 = EcaBlock(b[0], b[1], sb, sEK)
    b1s.append(b1)
  return b1s

class Block:
  pass
  
class EcaBlock(Block):
  def __init__(self, sCode, sCount, sName, sEK):
    self.sCode = sCode
    self.sCount = sCount
    self.nCount = int(sCount)
    self.sName = sName
    self.sEK = sEK


class ETs:
  def BlockText(self, b):
    return b.sCode +" "+ b.sCount +" "+ b.sName +"("+ b.sEK +")"
  
  def BlockSum(self, bs, cat, tra):
    return "\n\n" + tra+ `len(bs)` + 30*"-" +"\n"

class ETsShow(CatShow, ETs):
  pass

class ETsSnip(CatSnip, ETs):
  def BlockSum(self, bs, cat, tra):
    return tra+ cat +" ("+ `len(bs)` +")" +"\n"

class ETsCountCeiling(Cat, ETs):
  def CatOfBlock(self, b):
    ceils = self.catspec
    for ceil in ceils:
      if ceil == "all":
        if b.sCode == "all":
          return "all"
      else:
        if b.nCount > ceil:
          return ceil
    else:
      return "other"

  def BlockSum(self, bs, cat, tra):
    cEvs = 0
    for b in bs:
      cEvs += b.nCount
    
    d, lsEK = SeqByCategs(bs, lambda b: b.sEK)
    sEKs = ", ".join(lsEK)
    
    if cat == "all":
      sCat = "All EventTypes"
    else:
      sCat = "EventTypes with count > %s" % cat
    return (
      "\n" + tra+ 
      sCat +
      ":  cEvs= %d  nEvTypes= %d,"%(cEvs, len(bs)) +
      "\n"+tra+ 
      "EKs= ("+ sEKs +")" +
      #"  "+30*"-"+
      "\n"
    )

class ETsKinds(CatFound, ETs):
  def CatOfBlock(self, b):
    return b.sEK

  def BlockSum(self, bs, cat, tra):
    cEvs = 0
    for b in bs:
      cEvs += b.nCount
    
    if cat == "all":
      sCat = "All EventTypes"
    else:
      sCat = "EventTypes with Kind %s" % cat
    return (
      "\n" + tra+ 
      sCat +
      ":  cEvs= %d  nEvTypes= %d,"%(cEvs, len(bs)) +
      "\n"
    )

def getEKs():
  test_parseEventdefRelation()
  nameFile = "/Users/richardk/mps/master/code/eventdef.h"
  print nameFile
  file = open(nameFile, "r")
  eds = parseEventdefFile(file)
  file.close()
  sEKOfsET = {}
  for ed in eds:
    sEK, sET = ed.sEvKind, ed.sEvType
    if sET in sEKOfsET: raise ValueError(sET)
    sEKOfsET[sET] = sEK
  return sEKOfsET

def ecaprint(file, cats):
  sEKOfsET = getEKs()
  bs = parseEcaFile(file, sEKOfsET)

  s = CatsDo(bs, cats)
  print s

def fileprint(file):
  for l in file.readlines():
    print l,

import os

def foo():
  #define EventKindArena      ((EventKind)0) /* Per space or arena */
  #define EventKindPool       ((EventKind)1) /* Per pool */
  #define EventKindTrace      ((EventKind)2) /* Per trace or scan */
  #define EventKindSeg        ((EventKind)3) /* Per seg */
  #define EventKindRef        ((EventKind)4) /* Per ref or fix */
  #define EventKindObject     ((EventKind)5) /* Per alloc or object */
  #define EventKindUser       ((EventKind)6) /* User-invoked */
  sID, nTC = "2", 227  #             xxx xxx xxxxx
  sID, nTC = "3", 247  #                 xxx
  sID, nTC = "4", 255  # User Object Ref Seg Trace Pool Arena
  #sID, nTC = "5",   4  #                     Trace
  gen = True
  gen = False
  analyse = True #False
  
  sDir = "/Users/richardk/mps/master/code/xcppgc/ti/"
  
  # generate logfile
  if gen:
    #697  export MPS_TELEMETRY_CONTROL=227
    #698  ./amcss
    sGen = sDir + "amcss"
    #sGen = "mpstelemetrycontrol"
    os.environ["MPS_TELEMETRY_CONTROL"] = str(nTC)
    sNoteTC = 'os.environ["MPS_TELEMETRY_CONTROL"] = str(%s)' % str(nTC)
    print sNoteTC
    fGen = os.popen(sGen)
    fileprint(fGen)
    fGen.close()

  # rename logfile
  # on MacOS, running python from BBEdit, logfile is /mpsio.log (!)
  #699  mv mpsio.log e3.log
  sLogDefault = "/mpsio.log"
  sLog = sDir + "e%s.log" % sID
  if gen:
    os.rename(sLogDefault, sLog)
  
  # analyse events
  if analyse:
    #700  ./eventcnv -f e3.log -e all >e3.eca.txt
    cats = [
      #ETsCountCeiling( [ "all", 10000, 1000, 100, 0] ),
      #ETsKinds( [ "", "Ref", "Seg", "Object", "Arena", "Trace", "Pool", "User", ] ),
      ETsKinds( [ '', 'User', 'Object', 'Ref', 'Seg', 'Trace', 'Pool', 'Arena' ] ),
      #ETsKinds( [] ),
      #ETsSnip( [ "Fix", ] ),
      #ETsShow( [] ),
    ]
    sEca = sDir + "eventcnv -f '%s' -e all" % sLog
    fEca = os.popen(sEca)
    #fileprint(fEca)
    ecaprint(fEca, cats)
  
  if 0:
    sEcv = sDir + "eventcnv -f '%s' -SC -e TraceStatScan" % sLog
    sEcv = sDir + "eventcnv -f '%s' -SC -b 200 -e TraceStatScan" % sLog
    fEcv = os.popen(sEcv)
    fileprint(fEcv)
  
if __name__ == "__main__":
  foo()
  #main()
  pass

