-- File: CountCommands.mesa
-- Last edited by Sandman on October 21, 1980 3:00 PM
DIRECTORY
Ascii USING [CR, SP],
CountDefs USING [
condition, groups, loadmatrix, mode, modePos, module, mon, monitorOn,
printmodule, printsorted, printtables, process, processPos, setProcess,
sortClass, window, zero],
CountPrivate USING [
ControlRecord, GroupHandle, GroupIndex, MaxGroup, Mode, PCR, TableHandle,
VersionID],
DebugUsefulDefs USING [
Frame, GFHandle, Name, ShortCopyREAD, ShortCopyWRITE, ShortREAD, ShortWRITE],
Event USING [AddNotifier, Item, Masks, Notifier],
Format USING [NumberFormat],
FormSW USING [DisplayItem, EnumeratedNotifyProcType, NotifyProcType],
Gf USING [GFI, Handle, Validate],
Lookup USING [Fail],
MachineDefs USING [GFHandle, GfiToFrame, GfiToOffset, NullGF],
MsgSW USING [Clear, Post],
PerfCommonOps USING [
cmdSW, ConditionBreaks, logSW, msgSW, Number, WriteConvertedTicksToMs,
WriteLongNumber, WritePercent, Zero],
PerfStructures USING [IndexToHandle, NullPsbHandle, PsbIndex],
Put USING [Blanks, Char, CR, Decimal, Line, Number, Text],
SDDefs USING [sBreak, SD, sXferTrapMonitor],
Selection USING [Convert, Number],
Storage USING [FreeString, FreeWords, Words],
Streams USING [Destroy, End, GetByte, Handle, NewStream],
String USING [
AppendChar, AppendOctal, AppendString, InvalidNumber, StringToNumber],
Time USING [Append, Current, Unpack],
ToolWindow USING [GetName],
UserInput USING [userAbort];
CountCommands: PROGRAM
IMPORTS
CountDefs, DebugUsefulDefs, Event, FormSW, Gf, Lookup, MachineDefs, MsgSW,
PerfCommonOps, Put, Selection, Streams, String, Storage, Time, ToolWindow,
UserInput, PerfStructures
EXPORTS CountDefs =
PUBLIC
BEGIN OPEN CountDefs, CountPrivate, DebugUsefulDefs, PerfCommonOps;
cr: ControlRecord;
counts, times: TableHandle;
groups: PRIVATE GroupHandle;
counterOn: BOOLEAN ← FALSE;
haveTable, dirtyTable: PACKED ARRAY {counts, times, cr, groups} OF BOOLEAN ←
[FALSE, FALSE, FALSE, FALSE];
GetCounts: PROCEDURE [mode: {read, write}] RETURNS [TableHandle] =
BEGIN OPEN DebugUsefulDefs;
IF ~haveTable[counts] THEN
BEGIN
length: CARDINAL;
[] ← GetCR[read];
length ← cr.length*SIZE[LONG CARDINAL];
counts ← Storage.Words[length];
ShortCopyREAD[to: counts, from: cr.counts, nwords: length];
haveTable[counts] ← TRUE;
END;
dirtyTable[counts] ← dirtyTable[counts] OR mode = write;
RETURN[counts];
END;
GetTimes: PROCEDURE [mode: {read, write}] RETURNS [TableHandle] =
BEGIN OPEN DebugUsefulDefs;
IF ~haveTable[times] THEN
BEGIN
length: CARDINAL;
[] ← GetCR[read];
length ← cr.length*SIZE[LONG CARDINAL];
times ← Storage.Words[length];
ShortCopyREAD[to: times, from: cr.times, nwords: length];
haveTable[times] ← TRUE;
END;
dirtyTable[times] ← dirtyTable[times] OR mode = write;
RETURN[times];
END;
GetCR: PROCEDURE [mode: {read, write}] RETURNS [POINTER TO ControlRecord] =
BEGIN OPEN DebugUsefulDefs;
IF ~haveTable[cr] THEN
BEGIN
rec: PCR ← ShortREAD[@SDDefs.SD[SDDefs.sXferTrapMonitor]];
ShortCopyREAD[to: @cr, from: rec, nwords: SIZE[ControlRecord]];
haveTable[cr] ← TRUE;
END;
dirtyTable[cr] ← dirtyTable[cr] OR mode = write;
RETURN[@cr];
END;
GetGroups: PROCEDURE [mode: {read, write}] RETURNS [GroupHandle] =
BEGIN OPEN DebugUsefulDefs;
IF ~haveTable[groups] THEN
BEGIN
length: CARDINAL;
[] ← GetCR[read];
length ← cr.length*SIZE[GroupIndex];
groups ← Storage.Words[length];
ShortCopyREAD[to: groups, from: cr.groups, nwords: length];
haveTable[groups] ← TRUE;
END;
dirtyTable[groups] ← dirtyTable[groups] OR mode = write;
RETURN[groups];
END;
TablesExist: PROCEDURE RETURNS [BOOLEAN] =
BEGIN
RETURN[DebugUsefulDefs.ShortREAD[@SDDefs.SD[SDDefs.sXferTrapMonitor]] # NIL];
END;
TablesCorrectVersion: PROCEDURE RETURNS [BOOLEAN] =
BEGIN RETURN[GetCR[read].version = VersionID]; END;
PutTables: PUBLIC PROCEDURE [flush: BOOLEAN] =
BEGIN OPEN DebugUsefulDefs;
rec: PCR ← ShortREAD[@SDDefs.SD[SDDefs.sXferTrapMonitor]];
length: CARDINAL = cr.length*SIZE[LONG CARDINAL];
IF flush AND haveTable[cr] AND dirtyTable[cr] THEN
ShortCopyWRITE[to: rec, from: @cr, nwords: SIZE[ControlRecord]];
IF haveTable[counts] THEN
BEGIN
IF flush AND dirtyTable[counts] THEN
ShortCopyWRITE[from: counts, to: cr.counts, nwords: length];
Storage.FreeWords[counts];
END;
IF haveTable[times] THEN
BEGIN
IF flush AND dirtyTable[times] THEN
ShortCopyWRITE[from: times, to: cr.times, nwords: length];
Storage.FreeWords[times];
END;
IF haveTable[groups] THEN
BEGIN
IF flush AND dirtyTable[groups] THEN
ShortCopyWRITE[from: groups, to: cr.groups, nwords: cr.length*SIZE[GroupIndex]];
Storage.FreeWords[groups];
END;
haveTable ← dirtyTable ← [FALSE, FALSE, FALSE, FALSE];
END;
TurnOn: PROCEDURE =
BEGIN OPEN SDDefs;
cr.saveBreakHandler ← DebugUsefulDefs.ShortREAD[@SD[sBreak]];
DebugUsefulDefs.ShortWRITE[@SD[sBreak], cr.self];
END;
TurnOff: PROCEDURE RETURNS [BOOLEAN] =
-- this procedure turns off the measurements
BEGIN OPEN SDDefs;
IF cr.saveBreakHandler # NIL AND cr.self = DebugUsefulDefs.ShortREAD[
@SD[sBreak]] THEN
BEGIN
DebugUsefulDefs.ShortWRITE[@SD[sBreak], cr.saveBreakHandler];
RETURN[TRUE]
END;
RETURN[FALSE];
END;
ZeroCounts: PROCEDURE =
BEGIN
table: TableHandle ← GetCounts[write];
length: CARDINAL = GetCR[read].length*SIZE[LONG CARDINAL];
PerfCommonOps.Zero[table, length];
table ← GetTimes[write];
PerfCommonOps.Zero[table, length];
GetCR[write].gfi ← 0;
Put.Line[logSW, "Tables zeroed"L];
GetCR[write].newMeasurement ← TRUE;
RETURN
END;
SetProcess: PROCEDURE =
BEGIN OPEN PerfStructures;
pCR: PCR ← GetCR[write];
index: PsbIndex;
IF process = NIL OR process.length = 0 THEN
BEGIN pCR.process ← NullPsbHandle; Put.Line[logSW, "All processes now tracked"L]; END
ELSE
BEGIN
index ← String.StringToNumber[
process, 8 ! String.InvalidNumber => GOTO badProcess];
Put.Text[logSW, "Track process: "L];
Put.Line[logSW, process];
pCR.process ← IndexToHandle[index];
EXITS badProcess => PostError[badProcess];
END;
END;
PrintTables: PROCEDURE =
BEGIN
sort: Sorting ← GetSorting[];
PrintSorted[sort ! UNWIND => ReleaseSorting[sort]];
ReleaseSorting[sort];
END;
DisplaySorted: PROCEDURE =
BEGIN
sort: Sorting;
IF mode = matrix THEN {PostError[badMode]; RETURN};
sort ← GetSorting[];
SortTable[
table: IF sortClass = count THEN GetCounts[read] ELSE GetTimes[read],
sorting: sort];
PrintSorted[sort ! UNWIND => ReleaseSorting[sort]];
ReleaseSorting[sort];
END;
DisplayModule: PROCEDURE =
BEGIN
gfi: CARDINAL;
IF mode = matrix THEN {PostError[badMode]; RETURN};
IF module = NIL OR module.length = 0 THEN
BEGIN PostError[badModule]; RETURN END;
IF module[0] IN ['0..'9] THEN gfi ← String.StringToNumber[module, 8]
ELSE gfi ← LOOPHOLE[DebugUsefulDefs.Frame[module]];
IF gfi >= GetCR[read].length THEN gfi ← Gf.GFI[LOOPHOLE[gfi]];
Put.CR[logSW];
DisplayLine[
gfi, GetCount[gfi], TotalCounts[plain], GetTime[gfi], TotalTimes[plain]];
Put.CR[logSW];
RETURN
END;
PrintSorted: PROCEDURE [sort: Sorting] =
BEGIN
i, gfi: CARDINAL;
count, time, totalCounts, totalTime: Number;
[totalCounts, totalTime] ← PrintHeader[];
FOR i IN [0..GetCR[read].length) DO
IF (gfi ← sort[i]) = 0 THEN LOOP;
IF MachineDefs.GfiToOffset[gfi] # 0 THEN LOOP;
count ← GetCount[gfi];
IF count = 0 THEN LOOP;
Put.CR[logSW];
time ← GetTime[gfi];
DisplayLine[gfi, count, totalCounts, time, totalTime];
ENDLOOP;
Put.CR[logSW];
PrintTrailer[plain];
Put.CR[logSW];
END;
DisplayLine: PROCEDURE [
gfi: CARDINAL, count, totalCounts, time, totalTime: Number] =
BEGIN
f: Format.NumberFormat =
[base: 8, unsigned: TRUE, zerofill: FALSE, columns: 7];
g: Format.NumberFormat =
[base: 8, unsigned: TRUE, zerofill: FALSE, columns: 3];
module: STRING ← [40];
frame: MachineDefs.GFHandle;
IF UserInput.userAbort THEN SIGNAL Aborted;
frame ← MachineDefs.GfiToFrame[gfi];
CheckFrame[frame ! Aborted => GOTO bailout];
Put.Number[logSW, gfi, g];
Put.Char[logSW, 'B];
Put.Number[logSW, frame, f];
Put.Text[logSW, "B "L];
WriteFrameName[frame, 18];
WriteLongNumber[count, 12];
WritePercent[count, totalCounts, 8];
WriteConvertedTicksToMs[time, GetCR[read].pulseConversion, 12];
WritePercent[time, totalTime, 7];
RETURN;
EXITS bailout => RETURN
END;
CheckFrame: PROCEDURE [frame: MachineDefs.GFHandle] =
BEGIN
s: STRING ← [24];
IF frame # NIL AND Gf.Validate[frame] THEN RETURN;
String.AppendString[s, "! Invalid frame "L];
String.AppendOctal[s, frame];
MsgSW.Post[sw: msgSW, string: s, endOfMsg: TRUE];
Put.Text[logSW, s];
SIGNAL Aborted;
RETURN
END;
Aborted: SIGNAL = CODE;
PrintTotals: PROCEDURE [mode: Mode] RETURNS [totalCounts, totalTime: Number] =
BEGIN
Put.CR[logSW];
totalCounts ← TotalCounts[mode];
totalTime ← TotalTimes[mode];
Put.Text[logSW, "Total Xfers"L];
WriteLongNumber[totalCounts, 14];
Put.CR[logSW];
Put.Text[logSW, "Total Time "L];
WriteConvertedTicksToMs[totalTime, GetCR[read].pulseConversion, 14];
END;
PrintHeader: PROCEDURE RETURNS [totalCounts, totalTime: Number] =
BEGIN
[totalCounts: totalCounts, totalTime: totalTime] ← PrintTotals[plain];
Put.Text[
logSW,
"
Gfi Frame Module #Xfers %Xfers Time %Time
---- ------- ------------------ ----------- ------- ----------- ------"L];
END;
PrintTrailer: PROCEDURE [mode: Mode] =
BEGIN
Put.Text[logSW, "Ignored Xfers"L];
WriteLongNumber[Ignored[GetCounts[read], mode], 14];
Put.CR[logSW];
Put.Text[logSW, "Ignored Time "L];
WriteConvertedTicksToMs[
Ignored[GetTimes[read], mode], GetCR[read].pulseConversion, 14];
END;
WriteFrameName: PROCEDURE [frame: MachineDefs.GFHandle, columns: CARDINAL ← 0] =
BEGIN
module: STRING ← [40];
DebugUsefulDefs.Name[gf: frame, name: module];
PrintString[module, columns];
RETURN;
END;
TotalCounts: PROCEDURE [mode: CountPrivate.Mode] RETURNS [Number] =
BEGIN RETURN[Total[GetCounts[read], mode]] END;
TotalTimes: PROCEDURE [mode: CountPrivate.Mode] RETURNS [Number] =
BEGIN RETURN[Total[GetTimes[read], mode]] END;
Total: PROCEDURE [table: TableHandle, mode: CountPrivate.Mode]
RETURNS [total: Number] =
BEGIN
to, from, i: CARDINAL;
total ← 0;
IF mode = plain THEN
FOR i IN [1..GetCR[read].length) DO total ← total + table.plain[i]; ENDLOOP
ELSE
FOR to IN [1..MaxGroup] DO
FOR from IN [1..MaxGroup] DO
total ← total + table.matrix[to][from]; ENDLOOP;
ENDLOOP;
RETURN
END;
Ignored: PROCEDURE [table: TableHandle, mode: CountPrivate.Mode]
RETURNS [total: Number] =
BEGIN
to, from: CARDINAL;
total ← 0;
IF mode = plain THEN RETURN[table.plain[0]]
ELSE {
FOR to IN [0..MaxGroup] DO total ← total + table.matrix[to][0]; ENDLOOP;
FOR from IN [1..MaxGroup] DO total ← total + table.matrix[0][from]; ENDLOOP};
RETURN
END;
GetCount: PROCEDURE [gfi: CARDINAL] RETURNS [Number] =
BEGIN RETURN[GetValue[gfi, GetCounts[read]]] END;
GetTime: PROCEDURE [gfi: CARDINAL] RETURNS [Number] =
BEGIN RETURN[GetValue[gfi, GetTimes[read]]] END;
GetValue: PROCEDURE [gfi: CARDINAL, table: TableHandle]
RETURNS [count: Number] =
BEGIN
count ← 0;
DO
count ← count + table.plain[gfi];
gfi ← gfi + 1;
IF MachineDefs.GfiToOffset[gfi] = 0 OR GetCR[read].length = gfi THEN EXIT;
ENDLOOP;
RETURN
END;
SortTable: PROCEDURE [table: TableHandle, sorting: Sorting] =
BEGIN
SiftUp: PROCEDURE [low, high: CARDINAL] =
BEGIN
t: CARDINAL;
k, son: CARDINAL;
k ← low;
DO
IF k*2 > high THEN EXIT;
IF k*2 + 1 > high OR table.plain[sorting[k*2 + 1 - 1]] > table.plain[
sorting[k*2 - 1]] THEN son ← k*2
ELSE son ← k*2 + 1;
IF table.plain[sorting[son - 1]] > table.plain[sorting[k - 1]] THEN EXIT;
t ← sorting[son - 1];
sorting[son - 1] ← sorting[k - 1];
sorting[k - 1] ← t;
k ← son;
ENDLOOP;
RETURN
END;
t, i: CARDINAL;
length: CARDINAL = GetCR[read].length;
NormalizeTable[table];
FOR i DECREASING IN [1..length/2] DO SiftUp[i, length] ENDLOOP;
FOR i DECREASING IN [1..length) DO
t ← sorting[1 - 1];
sorting[1 - 1] ← sorting[i + 1 - 1];
sorting[i + 1 - 1] ← t;
SiftUp[1, i];
ENDLOOP;
RETURN
END;
NormalizeTable: PROCEDURE [table: TableHandle] =
BEGIN
count: LONG CARDINAL ← 0;
gfi: CARDINAL;
length: CARDINAL = GetCR[read].length;
FOR gfi DECREASING IN [0..length) DO
count ← count + table.plain[gfi];
IF MachineDefs.GfiToOffset[gfi] = 0 THEN
BEGIN table.plain[gfi] ← count; count ← 0; END
ELSE table.plain[gfi] ← 0;
ENDLOOP;
RETURN
END;
GetSorting: PROCEDURE RETURNS [sorting: Sorting] =
BEGIN
i: CARDINAL;
length: CARDINAL = GetCR[read].length;
sorting ← Storage.Words[length*SIZE[LONG CARDINAL]];
FOR i IN [0..length) DO sorting[i] ← i; ENDLOOP;
RETURN
END;
ReleaseSorting: PROCEDURE [sorting: Sorting] =
BEGIN Storage.FreeWords[sorting]; RETURN END;
Sorting: TYPE = POINTER TO ARRAY [0..0) OF CARDINAL;
PrintString: PROCEDURE [s: STRING, columns: CARDINAL] =
BEGIN
Put.Text[logSW, s];
IF columns > s.length THEN Put.Blanks[logSW, columns - s.length];
RETURN
END;
PrintMatrix: PROCEDURE =
BEGIN
g: Format.NumberFormat =
[base: 10, unsigned: TRUE, zerofill: FALSE, columns: 3];
to, from: GroupIndex;
count, time, totalCounts, totalTime: Number;
[totalCounts, totalTime] ← PrintTotals[matrix];
Put.Text[
logSW,
"
From -> To #Xfers %Xfers Time %Time
---- --- ----------- ------- ----------- ------"L];
Put.CR[logSW];
FOR from IN [1..MaxGroup] DO
FOR to IN [1..MaxGroup] DO
count ← counts.matrix[to][from];
time ← times.matrix[to][from];
IF count = 0 AND time = 0 THEN LOOP;
Put.Char[logSW, Ascii.SP];
Put.Number[logSW, from, g];
Put.Text[logSW, " ->"L];
Put.Number[logSW, to, g];
WriteLongNumber[count, 16];
WritePercent[count, totalCounts, 9];
WriteConvertedTicksToMs[time, GetCR[read].pulseConversion, 15];
WritePercent[time, totalTime, 8];
Put.CR[logSW];
IF UserInput.userAbort THEN SIGNAL Aborted;
ENDLOOP;
ENDLOOP;
Put.CR[logSW];
PrintTrailer[matrix];
Put.CR[logSW];
RETURN
END;
LoadMatrix: PROCEDURE =
BEGIN
groups: GroupHandle ← GetGroups[write];
gfi: CARDINAL;
group: GroupIndex;
stream: Streams.Handle ← GetFile[];
PerfCommonOps.Zero[groups, GetCR[read].length];
IF stream = NIL THEN RETURN;
prevGroup ← 0;
DO
ENABLE Streams.End[] => EXIT;
[gfi: gfi, group: group] ← GetNextPair[
stream ! BadFile => {PostError[badFile]; EXIT}];
DO
groups[gfi] ← group;
gfi ← gfi + 1;
IF gfi >= cr.length OR MachineDefs.GfiToOffset[gfi] = 0 THEN EXIT;
ENDLOOP;
ENDLOOP;
Streams.Destroy[stream];
Put.Line[logSW, "Matrix loaded"L];
RETURN
END;
GetFile: PROCEDURE RETURNS [stream: Streams.Handle] =
BEGIN
name: STRING ← Selection.Convert[string];
stream ← NIL;
IF name # NIL THEN stream ← Streams.NewStream[name ! ANY => CONTINUE];
IF stream = NIL THEN {
Storage.FreeString[name]; PostError[noFile]; RETURN[NIL]};
Storage.FreeString[name];
RETURN
END;
BadFile: SIGNAL = CODE;
prevGroup: GroupIndex;
GetNextPair: PROCEDURE [stream: Streams.Handle]
RETURNS [gfi: CARDINAL, group: GroupIndex] =
BEGIN OPEN String;
c: CHARACTER;
s: STRING ← [60];
DO
c ← GetToken[stream, s];
IF c = ': AND s.length = 3 AND s[0] = 'g AND s[1] = 'f AND s[2] = 'i THEN {
c ← GetToken[stream, s];
gfi ← StringToNumber[s, 10 ! InvalidNumber => GOTO badNumber];
SELECT c FROM
Ascii.CR => {group ← prevGroup; RETURN};
Ascii.SP => {
c ← GetToken[stream, s];
prevGroup ← group ← StringToNumber[
s, 10 ! InvalidNumber => GOTO badNumber];
RETURN};
ENDCASE => SIGNAL BadFile};
ENDLOOP;
EXITS badNumber => SIGNAL BadFile;
END;
GetToken: PROC [stream: Streams.Handle, s: STRING] RETURNS [c: CHARACTER] = {
s.length ← 0;
DO
SELECT c ← Streams.GetByte[stream] FROM
Ascii.SP, Ascii.CR => IF s.length # 0 THEN RETURN ELSE LOOP;
',, ': => RETURN;
ENDCASE => String.AppendChar[s, c];
ENDLOOP};
ShowGroups: PROCEDURE =
BEGIN
group: CARDINAL ← 177777B;
gfi: CARDINAL;
group ← Selection.Number[10 ! String.InvalidNumber => CONTINUE];
IF group NOT IN GroupIndex THEN GOTO noGood;
Put.Text[logSW, "Modules for group "L];
Put.Decimal[logSW, group];
Put.Char[logSW, ':];
Put.CR[logSW];
FOR gfi IN [1..GetCR[read].length) DO
IF group = GetGroups[read][gfi] THEN
BEGIN
name: STRING ← [40];
frame: MachineDefs.GFHandle ← MachineDefs.GfiToFrame[gfi];
IF frame = MachineDefs.NullGF THEN LOOP;
CheckFrame[frame ! Aborted => GOTO noGood];
WriteFrameName[frame];
Put.Text[logSW, name];
Put.Char[logSW, Ascii.SP];
END;
IF UserInput.userAbort THEN SIGNAL Aborted;
ENDLOOP;
Put.CR[logSW];
Put.CR[logSW];
EXITS noGood => PostError[badGroup];
END;
Error: TYPE = {
notOn, goofUp, version, noContext, badModule, badProcess, noFile, badFile,
badMode, badGroup};
PostError: PROCEDURE [error: Error] =
BEGIN
MsgSW.Post[
sw: msgSW,
string:
SELECT error FROM
notOn => "!Please Start CountTool and then try again"L,
goofUp =>
"!Goofed up CountTool by use of Worry on/off during measurements"L,
version => "!CountTool has Incorrect Version"L,
noContext => "!No Context"L,
badModule => "!No Module specified"L,
badProcess => "!Invalid Process specified"L,
noFile => "!Can't find input file"L,
badFile => "!Bad matrix input file"L,
badMode => "!Can't do in matrix mode"L,
badGroup => "!Bad group specified"L,
ENDCASE => "?"L];
END;
PutHerald: PROCEDURE =
BEGIN OPEN Time;
s: STRING ← [22];
name: STRING ← ToolWindow.GetName[window];
Put.Line[logSW, name];
Append[s, Unpack[Current[]]];
s.length ← s.length - 3;
Put.Line[logSW, s];
Put.CR[logSW];
Storage.FreeString[name];
RETURN
END;
SetDefaults: PROCEDURE [index: CARDINAL] =
BEGIN
pcr: PCR ← GetCR[write];
MakeSureOff[index];
IF index # setProcess THEN {
IF process # NIL THEN process.length ← 0;
[] ← FormSW.DisplayItem[cmdSW, processPos]};
IF index # modePos THEN {
mode ← plain; [] ← FormSW.DisplayItem[cmdSW, modePos]};
pcr.newSession ← FALSE;
PutHerald[];
RETURN
END;
MakeSureOff: PROCEDURE [index: CARDINAL] = {
IF index # mon THEN {monitorOn ← FALSE; [] ← FormSW.DisplayItem[cmdSW, mon]};
RETURN};
EnumerateNotify: FormSW.EnumeratedNotifyProcType = {
ParamNotify[sw: sw, item: item, index: index]};
ParamNotify: FormSW.NotifyProcType =
BEGIN
MsgSW.Clear[msgSW];
IF ~TablesExist[] THEN GOTO noTables;
IF ~TablesCorrectVersion[] THEN GOTO badVersion;
IF GetCR[read].newSession THEN SetDefaults[index];
SELECT index FROM
mon => IF monitorOn THEN TurnOn[] ELSE IF ~TurnOff[] THEN PostError[goofUp];
zero => ZeroCounts[];
condition => ConditionBreaks[];
printtables =>
IF mode = plain THEN PrintTables[
! Aborted => {Put.Line[logSW, "... aborted!"L]; CONTINUE}]
ELSE PrintMatrix[ ! Aborted => {Put.Line[logSW, "... aborted!"L]; CONTINUE}];
printsorted =>
DisplaySorted[ ! Aborted => {Put.Line[logSW, "... aborted!"L]; CONTINUE}];
printmodule =>
DisplayModule[ !
Lookup.Fail => BEGIN CantFind[s]; CONTINUE END;
Aborted => {Put.Line[logSW, "... aborted!"L]; CONTINUE}];
setProcess => SetProcess[];
modePos => GetCR[write].mode ← mode;
loadmatrix => LoadMatrix[];
CountDefs.groups =>
ShowGroups[ ! Aborted => {Put.Line[logSW, "... aborted!"L]; CONTINUE}];
ENDCASE;
EXITS
noTables => {PostError[notOn]; MakeSureOff[index]};
badVersion => {PostError[version]; MakeSureOff[index]}
END;
CantFind: PROCEDURE [name: STRING] =
BEGIN
MsgSW.Post[sw: msgSW, string: "!"L, endOfMsg: FALSE];
MsgSW.Post[sw: msgSW, string: name];
RETURN
END;
Cleanup: Event.Notifier =
BEGIN
PutTables[why = resumeDebuggee];
SELECT why FROM
newSession, abortSession =>
BEGIN monitorOn ← counterOn ← FALSE; FormSW.DisplayItem[cmdSW, mon]; END;
ENDCASE;
RETURN
END;
-- Mainline code
cleanupItem: Event.Item ←
[eventMask:
Event.Masks[abortSession] + Event.Masks[newSession] + Event.Masks[
resumeDebuggee], eventProc: Cleanup];
Event.AddNotifier[@cleanupItem];
END.