PrintMB.mesa
Hal Murray July 9, 1985 5:50:02 pm PDT
DIRECTORY
Commander USING [CommandProc, Register],
Containers USING [ChildXBound, ChildYBound],
Convert USING [RopeFromCard],
FS USING [Error, StreamOpen],
IO USING [GetChar, Flush, PutChar, PutF, PutRope, STREAM, Value],
Loader USING [BCDBuildTime],
Rope USING [ROPE],
TypeScript USING [ChangeLooks, Create],
ViewerClasses USING [Viewer],
ViewerEvents USING [EventProc, RegisterEventProc],
ViewerIO USING [CreateViewerStreams],
ViewerOps USING [AddProp, CreateViewer, FetchProp, OpenIcon],
ViewRec USING [BindAllOfATypeFromRefs, RecordViewer, RVQuaViewer, ViewRef];
PrintMB: CEDAR MONITOR
IMPORTS
Commander, Containers, Convert, FS, IO, Loader, TypeScript, ViewerEvents, ViewerIO, ViewerOps, ViewRec =
BEGIN
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Viewer: TYPE = ViewerClasses.Viewer;
ClientData: TYPE = REF ClientDataRep;
ClientDataRep: TYPE = RECORD [
nameViewer: ViewerClasses.Viewer ← NIL,
info: Info ← NIL,
rv: ViewRec.RecordViewer ← NIL,
log: STREAMNIL,
in: STREAMNIL,
pleaseStop: BOOLEANFALSE,
user: PROCESSNIL];
Info: TYPE = REF InfoRec;
InfoRec: TYPE = RECORD [
stop: PROC [data: ClientData] ← Stop,
start: PROC [data: ClientData] ← Start,
fileName: ROPENIL];
BuildTool: Commander.CommandProc = TRUSTED
BEGIN
container: Viewer ← ViewerOps.CreateViewer [
flavor: $Container,
info: [name: "PrintMB", column: left, iconic: TRUE, scrollable: FALSE]];
data: ClientData ← NEW[ClientDataRep ← []];
viewer: Viewer ← NIL;
[] ← ViewerEvents.RegisterEventProc[Poof, destroy, container, TRUE];
ViewerOps.AddProp[container, $PrintMB, data];
data.info ← NEW[InfoRec ← []];
data.rv ← ViewRec.ViewRef[
agg: data.info,
specs: ViewRec.BindAllOfATypeFromRefs[rec: data.info, handle: NEW[ClientData ← data] ],
viewerInit: [parent: container, ww: 380, wh: 14, scrollable: TRUE, border: TRUE] ];
viewer ← TypeScript.Create[
[name: "PrintMB.log", wy: data.rv.RVQuaViewer[].wy+data.rv.RVQuaViewer[].wh+4, parent: container, border: FALSE], FALSE];
[data.in, data.log] ← ViewerIO.CreateViewerStreams [
name: "PrintMB.log", backingFile: "PrintMB.log", viewer: viewer, editedStream: FALSE];
Containers.ChildXBound[container, viewer];
Containers.ChildYBound[container, viewer];
TypeScript.ChangeLooks[viewer, 'f];
IO.PutF[data.log, "PrintMB of %G.\n", [time[Loader.BCDBuildTime[BuildTool]]]];
ViewerOps.OpenIcon[container];
END;
Poof: ViewerEvents.EventProc =
BEGIN
[viewer: ViewerClasses.Viewer, event: ViewerEvent, before: BOOL]
RETURNS[abort: BOOLFALSE]
data: ClientData ← NARROW[ViewerOps.FetchProp[viewer, $PrintMB]];
IF event # destroy OR before # TRUE THEN ERROR;
Stop[data];
data.log ← NIL; -- Help GC
END;
Stop: ENTRY PROCEDURE [data: ClientData] = TRUSTED
BEGIN
data.pleaseStop ← TRUE;
IF data.user # NIL THEN JOIN data.user;
data.user ← NIL;
IO.Flush[data.log];
END;
Start: ENTRY PROCEDURE [data: ClientData] =
BEGIN
IF data.user # NIL THEN Stop[data];
data.pleaseStop ← FALSE;
data.user ← FORK Printer[data];
END;
Printer: PROCEDURE [data: ClientData] =
BEGIN ENABLE UNWIND => { ByeBye[data]; };
maxMemories: CARDINAL = 100;
goodies: ARRAY [0..maxMemories) OF RECORD [
known: BOOLEAN,
bitsPerWord: CARDINAL] ← ALL[[FALSE, 0]];
currentMemory: CARDINAL ← 999;
currentPC: CARDINAL ← 0;
wordsSoFar: CARDINAL ← 0;
mb: IO.STREAM;
mb ← FS.StreamOpen[data.info.fileName, ! FS.Error => CONTINUE];
IF mb = NIL THEN {
Report[data, "Couldn't open input file: ", data.info.fileName, ".\n"];
ByeBye[data];
RETURN; };
UNTIL data.pleaseStop DO
command: CARDINAL = GetWord[mb];
IF wordsSoFar # 0 AND command # 1 THEN { Report[data, "\n"]; wordsSoFar ← 0; };
SELECT command FROM
0 => {
Report[data, "\nNo more data.\n"];
EXIT; };
1 => {
sourceLine: CARDINAL = GetWord[mb];
bitsPerWord: CARDINAL;
IF goodies[currentMemory].known # TRUE THEN {
Report[data, "Name/Size of current memory is not known => invalid MB file.\n"];
EXIT; };
bitsPerWord ← goodies[currentMemory].bitsPerWord;
IF wordsSoFar = 0 THEN {
PrintHex[data, currentPC];
Report[data, "/"]; };
Report[data, " "];
FOR i: INT IN [0..bitsPerWord/16) DO
PrintHex[data, GetWord[mb]];
ENDLOOP;
wordsSoFar ← wordsSoFar + 1;
IF bitsPerWord > 16 THEN wordsSoFar ← 8;
IF bitsPerWord MOD 16 # 0 THEN
PrintPartialHex[data, GetWord[mb], bitsPerWord MOD 16];
IF sourceLine # 0 THEN {
Report[data, " (Source line ", Convert.RopeFromCard[sourceLine], ").\n"];
wordsSoFar ← 0; };
IF wordsSoFar >= 8 THEN { Report[data, "\n"]; wordsSoFar ← 0; };
currentPC ← currentPC + 1; };
2 => {
memory: CARDINAL = GetWord[mb];
pc: CARDINAL = GetWord[mb];
Report[data, "Set current memory to ", Convert.RopeFromCard[memory]];
Report[data, , ", PC to ", Convert.RopeFromCard[pc], ".\n\n"];
currentMemory ← memory;
currentPC ← pc; };
4 => {
memory: CARDINAL = GetWord[mb];
bitsPerWord: CARDINAL = GetWord[mb];
characters: CARDINAL ← 0;
Report[data, "\nNew memory: name = \""];
DO
char: CHARIO.GetChar[mb];
characters ← characters+1;
IF char = 0C THEN EXIT;
IO.PutChar[data.log, char];
ENDLOOP;
IF (characters MOD 2) = 1 THEN [] ← IO.GetChar[mb];
Report[data, "\", number = ", Convert.RopeFromCard[memory]];
Report[data, ", bitsPerWord = ", Convert.RopeFromCard[bitsPerWord], ".\n"];
goodies[memory] ← [TRUE, bitsPerWord]; };
ENDCASE => {
Report[data, "Unknown command byte: ", Convert.RopeFromCard[command], ".\n"];
EXIT;};
ENDLOOP;
ByeBye[data];
END;
ByeBye: ENTRY PROCEDURE [data: ClientData] =
BEGIN
IO.Flush[data.log];
data.user ← NIL;
END;
GetWord: PROC [stream: IO.STREAM] RETURNS [CARDINAL] =
BEGIN
first, second: CARDINAL;
first ← GetByte[stream];
second ← GetByte[stream];
RETURN[first*256+second];
END;
GetByte: PROC [stream: IO.STREAM] RETURNS [byte: CARDINAL] = TRUSTED
BEGIN
RETURN[LOOPHOLE[IO.GetChar[stream], CARDINAL]];
END;
PrintHex: PROC [data: ClientData, word: WORD] =
BEGIN
n1, n2, n3, n4: WORD;
n4 ← word MOD 16;
word ← word / 16;
n3 ← word MOD 16;
word ← word / 16;
n2 ← word MOD 16;
word ← word / 16;
n1 ← word MOD 16;
IO.PutChar[data.log, ' ];
PrintHexNibble[data, n1];
PrintHexNibble[data, n2];
PrintHexNibble[data, n3];
PrintHexNibble[data, n4];
END;
PrintPartialHex: PROC [data: ClientData, word: WORD, bits: CARDINAL] =
BEGIN
n1, n2, n3, n4: WORD;
FOR i: INT IN [bits..16) DO word ← word/2; ENDLOOP;
n4 ← word MOD 16;
word ← word / 16;
n3 ← word MOD 16;
word ← word / 16;
n2 ← word MOD 16;
word ← word / 16;
n1 ← word MOD 16;
IO.PutChar[data.log, ' ];
IF bits > 12 THEN PrintHexNibble[data, n1];
IF bits > 8 THEN PrintHexNibble[data, n2];
IF bits > 4 THEN PrintHexNibble[data, n3];
PrintHexNibble[data, n4];
END;
PrintHexNibble: PROC [data: ClientData, nibble: WORD] =
BEGIN
SELECT nibble FROM
IN [0..9] => IO.PutChar[data.log, '0+nibble];
IN [10..15] => IO.PutChar[data.log, 'A+nibble-10];
ENDCASE => ERROR;
END;
Report: PROC [data: ClientData, r1, r2, r3, r4: ROPENIL] =
BEGIN
IF r1 # NIL THEN {IO.PutRope[data.log, r1]};
IF r2 # NIL THEN {IO.PutRope[data.log, r2]};
IF r3 # NIL THEN {IO.PutRope[data.log, r3]};
IF r4 # NIL THEN {IO.PutRope[data.log, r4]};
END;
Commander.Register["PrintMB", BuildTool, "Print contents of MB files used to blow Proms."];
END.