############################################################################ # # File: opersum.icn # # Subject: Program to tabulate operation activity # # Author: Ralph E. Griswold # # Date: March 10, 1998 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This tool tabulates operation activity. It is called as # # opersum prog # # where prog is a program compiled under MT Icon whose events are to # be tabulated. # # The options supported are: # # -m s sets the event mask named s. The supported masks are # FncMask (the default), OperMask, ProcMask, ScanMask, # and Oper+Mask, which includes both ScanMask and # OperMask. # # -o s write output to file s; default &output. # # -t record time spent in monitoring. # ############################################################################ # # Requires: MT Icon and event monitoring. # ############################################################################ # # Links: evinit, evnames, options, procname # ############################################################################ # # Includes: evdefs.icn # ############################################################################ link evaltree link evinit link evnames link options link procname $include "evdefs.icn" global namemap, output, fncset, scan, fnames, mask global calltbl, retntbl, susptbl, failtbl, resmtbl, remvtbl procedure main(args) local opts, itime namemap := evnames() opts := options(args, "m:o:t") mask := FncMask mask := case \opts["m"] of { "ProcMask": ProcMask "FncMask": FncMask "OperMask": OperMask "ScanMask": { scan := 1 ScanMask } "Oper+Mask": { scan := 1 OperMask ++ ScanMask } default: stop("*** invalid event mask name") } if mask === FncMask then { # beware record constructors fnames := set() # valid function names every insert(fnames, function() || "()") } output := open(\opts["o"], "w") | &output if \opts["t"] then itime := &time EvInit(args) | stop("*** cannot load program") # initialize interface calltbl := table(0) retntbl := table(0) susptbl := table(0) failtbl := table(0) resmtbl := table(0) remvtbl := table(0) fncset := set() EvInit(args) | stop("*** cannot load program") # initialize interface evaltree(mask, note) write(output, left("name", 14), right("calls", 10), right("returns", 10), right("suspends", 10), right("failures", 10), right("resumps", 10), right("removals", 10) ) write(output) every name := !sort(fncset) do write(output, left(name, 14), right(calltbl[name], 10), right(retntbl[name], 10), right(susptbl[name], 10), right(failtbl[name], 10), right(resmtbl[name], 10), right(remvtbl[name], 10) ) write(output, "\n", left("total", 14), right(tblsum(calltbl), 10), right(tblsum(retntbl), 10), right(tblsum(susptbl), 10), right(tblsum(failtbl), 10), right(tblsum(resmtbl), 10), right(tblsum(remvtbl), 10) ) write(output, "\nelapsed time: ", &time - \itime, "ms") end procedure note(new, old) case &eventcode of { !CallCodes: { name := ename(new.node) if (mask === FncMask) & not(member(fnames, name)) then return calltbl[name] +:= 1 insert(fncset, name) } !ReturnCodes: { name := ename(old.node) if (mask === FncMask) & not(member(fnames, name)) then return retntbl[name] +:= 1 } !SuspendCodes: { name := ename(old.node) if (mask === FncMask) & not(member(fnames, name)) then return susptbl[name] +:= 1 } !FailCodes: { name := ename(old.node) if (mask === FncMask) & not(member(fnames, name)) then return failtbl[name] +:= 1 } !ResumeCodes: { name := ename(new.node) if (mask === FncMask) & not(member(fnames, name)) then return resmtbl[name] +:= 1 } !RemoveCodes: { name := ename(old.node) if (mask === FncMask) & not(member(fnames, name)) then return remvtbl[name] +:= 1 } } return end procedure ename(x) if /x then return "bogon" else if \scan & not(proc(x)) then return "e1 ? e2" else return procname(x, 1) # use the expanded form end procedure tblsum(tbl) local count count := 0 every count +:= !tbl return count end