-- PerfInterface.mesa Edited by
-- Sandman Oct 21, 1980 3:06 PM
-- Karlton June 25, 1980  2:05 AM

DIRECTORY
  FormSW USING [
    AllocateItemDescriptor, ClientItemsProcType, CommandItem, Enumerated,
    EnumeratedItem, line0, line1, line2, line3, line4, line5, line6, line7, line8,
    line9, StringItem, TagOnlyItem],
  PerfCommonOps USING [],
  PerfOps USING [
    BpNumToNodeID, FindIndex, GetNodeTable, GetPCR, ParamEnumNotify, ParamIndex,
    ParamNotify, Params],
  PerfPrivate USING [
    AllNodes, HistClass, HistType, LegAddClass, LegIndex, LegTrackClass,
    NodeIndex, NoLegSlot, NullNode, Number],
  Runtime USING [GetBcdTime],
  String USING [AppendString, InvalidNumber, StringToDecimal, StringToLongNumber],
  Time USING [Append, Unpack],
  Tool USING [Create, MakeFileSW, MakeFormSW, MakeMsgSW, MakeSWsProc],
  Window USING [Handle, Place];

PerfInterface: PROGRAM
  IMPORTS FormSW, Runtime, PerfOps, String, Time, Tool
  EXPORTS PerfOps, PerfCommonOps =PUBLIC

  BEGIN OPEN PerfOps, PerfPrivate;

  logSW: Window.Handle ← NIL;
  msgSW: Window.Handle;
  cmdSW: Window.Handle;
  toolWindow: Window.Handle;

  herald: STRING ← [60];

  Init: PROCEDURE =
    BEGIN
    title: STRING = "Performance Tool 6.0 of "L;
    String.AppendString[to: herald, from: title];
    Time.Append[herald, Time.Unpack[Runtime.GetBcdTime[]]];
    herald.length ← herald.length - 3;
    toolWindow ← Tool.Create[name: herald, makeSWsProc: MakeSWs];
    END;

  MakeSWs: Tool.MakeSWsProc =
    BEGIN
    msgSW ← Tool.MakeMsgSW[window: window, lines: 1];
    cmdSW ← Tool.MakeFormSW[window: window, formProc: MakeParams];
    logSW ← Tool.MakeFileSW[window: window, name: "Perf.log"L];
    END;

  monitorOn: BOOLEAN ← FALSE;
  fromNode: STRING ← NIL;
  toNode: STRING ← NIL;
  deleteLeg: STRING ← NIL;
  process: STRING ← NIL;
  histNode: STRING ← NIL;
  histLeg: STRING ← NIL;
  buckets: STRING ← NIL;
  scale: STRING ← NIL;
  base: STRING ← NIL;
  addMode: LegAddClass ← none;
  trackMode: LegTrackClass ← all;
  histClass: HistClass ← FIRST[HistClass];
  histType: HistType ← FIRST[HistType];

  monPlace: Window.Place = [x: 0*7, y: FormSW.line0];
  collectPlace: Window.Place = [x: 20*7, y: FormSW.line0];
  initPlace: Window.Place = [x: 36*7, y: FormSW.line0];
  zeroPlace: Window.Place = [x: 56*7, y: FormSW.line0];
  condPlace: Window.Place = [x: 0*7, y: FormSW.line1];
  ptPlace: Window.Place = [x: 22*7, y: FormSW.line1];
  pnPlace: Window.Place = [x: 40*7, y: FormSW.line1];
  plPlace: Window.Place = [x: 57*7, y: FormSW.line1];
  alPlace: Window.Place = [x: 0*7, y: FormSW.line2];
  fromPlace: Window.Place = [x: 10*7, y: FormSW.line2];
  toPlace: Window.Place = [x: 27*7, y: FormSW.line2];
  dlPlace: Window.Place = [x: 42*7, y: FormSW.line2];
  legPlace: Window.Place = [x: 54*7, y: FormSW.line2];
  mcPlace: Window.Place = [x: 24*7, y: FormSW.line3];
  amPlace: Window.Place = [x: 0*7, y: FormSW.line4];
  tmPlace: Window.Place = [x: 30*7, y: FormSW.line4];
  spPlace: Window.Place = [x: 0*7, y: FormSW.line5];
  pPlace: Window.Place = [x: 20*7, y: FormSW.line5];
  histPlace: Window.Place = [x: 22*7, y: FormSW.line6];
  ahPlace: Window.Place = [x: 0*7, y: FormSW.line7];
  dhPlace: Window.Place = [x: 8*7, y: FormSW.line7];
  phPlace: Window.Place = [x: 18*7, y: FormSW.line7];
  htPlace: Window.Place = [x: 28*7, y: FormSW.line7];
  hcPlace: Window.Place = [x: 48*7, y: FormSW.line7];
  hnPlace: Window.Place = [x: 0*7, y: FormSW.line8];
  hlPlace: Window.Place = [x: 30*7, y: FormSW.line8];
  bucketsPlace: Window.Place = [x: 0*7, y: FormSW.line9];
  scalePlace: Window.Place = [x: 20*7, y: FormSW.line9];
  basePlace: Window.Place = [x: 40*7, y: FormSW.line9];

  MakeParams: FormSW.ClientItemsProcType =
    BEGIN OPEN FormSW;
    addEnumRec: ARRAY LegAddClass OF Enumerated ←
      [[string: "none"L, value: LegAddClass[none]],
	[string: "successor"L, value: LegAddClass[successor]]];
    trackEnumRec: ARRAY LegTrackClass OF Enumerated ←
      [[string: "none"L, value: LegTrackClass[none]],
	[string: "successor"L, value: LegTrackClass[successor]],
	[string: "all"L, value: LegTrackClass[all]]];
    histClassEnumRec: ARRAY HistClass OF Enumerated ←
      [[string: "linear"L, value: HistClass[linear]],
	[string: "log"L, value: HistClass[log]]];
    histTypeEnumRec: ARRAY HistType OF Enumerated ←
      [[string: "node"L, value: HistType[node]],
	[string: "leg"L, value: HistType[leg]]];
    monitorEnumRec: ARRAY BOOLEAN OF Enumerated ←
      [[string: "off"L, value: FALSE], [string: "on"L, value: TRUE]];
    nParams: CARDINAL = LOOPHOLE[LAST[ParamIndex], CARDINAL] + 1;
    params: Params ← LOOPHOLE[AllocateItemDescriptor[nParams]];
    params[mon] ← EnumeratedItem[
      tag: "Monitor"L, place: monPlace, feedback: all,
      choices: LOOPHOLE[DESCRIPTOR[monitorEnumRec]], proc: ParamEnumNotify,
      value: @monitorOn];
    params[collect] ← CommandItem[
      tag: "Collect Nodes"L, place: collectPlace, proc: ParamNotify];
    params[init] ← CommandItem[
      tag: "Initialize Tables"L, place: initPlace, proc: ParamNotify];
    params[zero] ← CommandItem[
      tag: "Zero Tables"L, place: zeroPlace, proc: ParamNotify];
    params[condition] ← CommandItem[
      tag: "Condition Breaks"L, place: condPlace, proc: ParamNotify];
    params[printtables] ← CommandItem[
      tag: "Print Tables"L, place: ptPlace, proc: ParamNotify];
    params[printnodes] ← CommandItem[
      tag: "Print Nodes"L, place: pnPlace, proc: ParamNotify];
    params[printlegs] ← CommandItem[
      tag: "Print Legs"L, place: plPlace, proc: ParamNotify];
    params[addleg] ← CommandItem[
      tag: "Add Leg"L, place: alPlace, proc: ParamNotify];
    params[from] ← StringItem[
      tag: "From Node"L, place: fromPlace, string: @fromNode, inHeap: TRUE];
    params[to] ← StringItem[
      tag: "To Node"L, place: toPlace, string: @toNode, inHeap: TRUE];
    params[delete] ← CommandItem[
      tag: "Delete Leg"L, place: dlPlace, proc: ParamNotify];
    params[leg] ← StringItem[
      tag: "Leg"L, place: legPlace, string: @deleteLeg, inHeap: TRUE];
    params[mode] ← TagOnlyItem[tag: "Mode Commands"L, place: mcPlace];
    params[add] ← EnumeratedItem[
      tag: "Add"L, place: amPlace, feedback: all,
      choices: LOOPHOLE[DESCRIPTOR[addEnumRec]], proc: ParamEnumNotify,
      value: @addMode];
    params[track] ← EnumeratedItem[
      tag: "Track"L, place: tmPlace, feedback: all, value: @trackMode,
      choices: LOOPHOLE[DESCRIPTOR[trackEnumRec]], proc: ParamEnumNotify];
    params[setProcess] ← CommandItem[
      tag: "Set Process"L, place: spPlace, proc: ParamNotify];
    params[process] ← StringItem[
      tag: "Process"L, place: pPlace, string: @process, inHeap: TRUE];
    params[histcommands] ← TagOnlyItem[
      tag: "Histogram Commands"L, place: histPlace];
    params[addhist] ← CommandItem[tag: "Add"L, place: ahPlace, proc: ParamNotify];
    params[delhist] ← CommandItem[
      tag: "Delete"L, place: dhPlace, proc: ParamNotify];
    params[printhist] ← CommandItem[
      tag: "Print"L, place: phPlace, proc: ParamNotify];
    params[histType] ← EnumeratedItem[
      tag: "Type"L, place: htPlace, feedback: all, value: @histType,
      choices: LOOPHOLE[DESCRIPTOR[histTypeEnumRec]]];
    params[histClass] ← EnumeratedItem[
      tag: "Class"L, place: hcPlace, feedback: all, value: @histClass,
      choices: LOOPHOLE[DESCRIPTOR[histClassEnumRec]]];
    params[histNode] ← StringItem[
      tag: "Histogram Node"L, place: hnPlace, string: @histNode, inHeap: TRUE];
    params[histLeg] ← StringItem[
      tag: "Histogram Leg"L, place: hlPlace, string: @histLeg, inHeap: TRUE];
    params[buckets] ← StringItem[
      tag: "Buckets"L, place: bucketsPlace, string: @buckets, inHeap: TRUE];
    params[scale] ← StringItem[
      tag: "Scale"L, place: scalePlace, string: @scale, inHeap: TRUE];
    params[base] ← StringItem[
      tag: "Base"L, place: basePlace, string: @base, inHeap: TRUE];
    RETURN[LOOPHOLE[params], TRUE];
    END;

  GetFromNode: PROCEDURE RETURNS [node: NodeIndex] = {RETURN[GetNode[fromNode]]};

  GetToNode: PROCEDURE RETURNS [node: NodeIndex] = {RETURN[GetNode[toNode]]};

  GetNode: PROCEDURE [s: STRING] RETURNS [node: NodeIndex] =
    BEGIN OPEN String;
    bpNum: CARDINAL ← 0;
    node ← NullNode;
    bpNum ← StringToDecimal[ s !
      InvalidNumber => {
	node ← IF toNode.length = 1 AND toNode[0] = '* THEN AllNodes ELSE NullNode;
	CONTINUE}];
    IF bpNum = 0 THEN RETURN;
    node ← FindIndex[BpNumToNodeID[bpNum], GetNodeTable[read], GetPCR[read]];
    RETURN
    END;

  GetDeleteLeg: PROCEDURE RETURNS [leg: LegIndex] =
    BEGIN
    leg ← String.StringToDecimal[
      deleteLeg ! String.InvalidNumber => BEGIN leg ← NoLegSlot; CONTINUE END];
    RETURN
    END;

  GetHistNode: PROCEDURE RETURNS [node: NodeIndex] =
    BEGIN
    node ← GetNode[histNode];
    IF node = AllNodes THEN node ← NullNode;
    RETURN
    END;

  GetHistLeg: PROCEDURE RETURNS [leg: LegIndex] =
    BEGIN
    leg ← String.StringToDecimal[
      histLeg ! String.InvalidNumber => BEGIN leg ← NoLegSlot; CONTINUE END];
    RETURN
    END;

  GetBuckets: PROCEDURE RETURNS [nBuckets: CARDINAL] =
    BEGIN
    nBuckets ← String.StringToDecimal[
      buckets ! String.InvalidNumber => BEGIN nBuckets ← 0; CONTINUE END];
    RETURN
    END;

  GetScale: PROCEDURE RETURNS [s: CARDINAL] =
    BEGIN
    s ← String.StringToDecimal[
      scale ! String.InvalidNumber => BEGIN s ← NullNode; CONTINUE END];
    RETURN
    END;

  GetBase: PROCEDURE RETURNS [b: Number] =
    BEGIN
    b ← String.StringToLongNumber[
      base, 10 ! String.InvalidNumber => BEGIN b ← 0; CONTINUE END];
    RETURN
    END;

  -- Mainline code

  Init[];

  END...