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: STREAM _ NIL, in: STREAM _ NIL, pleaseStop: BOOLEAN _ FALSE, user: PROCESS _ NIL]; Info: TYPE = REF InfoRec; InfoRec: TYPE = RECORD [ stop: PROC [data: ClientData] _ Stop, start: PROC [data: ClientData] _ Start, fileName: ROPE _ NIL]; 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 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: CHAR _ IO.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: ROPE _ NIL] = 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. ˜PrintMB.mesa Hal Murray July 9, 1985 5:50:02 pm PDT [viewer: ViewerClasses.Viewer, event: ViewerEvent, before: BOOL] RETURNS[abort: BOOL _ FALSE] Κ ˜šœ ™ Icode™&—J˜šΟk ˜ Jšœ œ˜(Jšœ œ˜,Jšœœ˜Jšœœ˜Jšœœ* œ˜AJšœœ˜Jšœœœ˜Jšœ œ˜'Jšœœ ˜Jšœ œ ˜2Jšœ œ˜%Jšœ œ.˜=šœœ5œ˜KJ˜——šœ œ˜š˜Jšœ œœB˜h—Jš˜J˜Jšœœœ˜Jšœœœœ˜Jšœœ˜%Jšœ œœ˜%šœœœ˜Jšœ#œ˜'J˜J˜Jšœœœ˜Jšœœœ˜Jšœ œœ˜Jšœœœ˜—Jšœœœ ˜šœ œœ˜Jšœœ˜%Jšœœ˜'Jšœ œœ˜J˜—šœ#˜*Jš˜šœ,˜,J˜Jšœ.œœ˜I—Jšœœ˜+Jšœœ˜J˜Jšœ>œ˜DJšœ-˜-J˜Jšœ œ˜šœ˜Jšœ˜JšœW˜WJšœ=œ œ˜S—J˜šœ˜Jšœjœœ˜y—šœ4˜4JšœOœ˜V—Jšœ*˜*Jšœ*˜*Jšœ#˜#JšœL˜NJšœ˜Jšœ˜—J˜šœ˜Jš˜Jšœ;œ™@Jšœœœ™Jšœœ(˜AJš œœ œœœ˜/Jšœ ˜ Jšœ œΟc ˜Jšœ˜J˜—šΟnœœ œ˜2Jš˜Jšœœ˜Jšœ œœœ ˜'Jšœ œ˜Jšœ˜Jšœ˜J˜—šŸœœ œ˜+Jš˜Jšœ œœ ˜#Jšœœ˜Jšœ œ˜Jšœ˜J˜—šŸœ œ˜'Jšœœœ˜)Jšœ œ˜šœ œœœ˜+Jšœœ˜Jšœ œœœ˜)—Jšœœ˜Jšœ œ˜Jšœ œ˜Jšœœœ˜Jšœœ"œ œ˜?šœœœ˜JšœF˜FJ˜ Jšœ˜ —šœ˜Jšœ œ˜ Jšœœ œ)˜Ošœ ˜šœ˜Jšœ"˜"Jšœ˜—šœ˜Jšœ œ˜#Jšœ œ˜šœ œœ˜-JšœO˜OJšœ˜—Jšœ1˜1šœœ˜Jšœ˜Jšœ˜—Jšœ˜šœœœ˜$Jšœ˜Jšœ˜—Jšœ˜Jšœœ˜(šœ œ˜Jšœ/œ˜7—šœœ˜Jšœ]˜]—Jšœœ)˜@Jšœ˜—šœ˜Jšœœ˜Jšœœ˜JšœF˜FJšœ>˜>Jšœ˜Jšœ˜—šœ˜Jšœœ˜Jšœ œ˜$Jšœ œ˜Jšœ(˜(š˜Jšœœœ ˜Jšœ˜Jšœ œœ˜Jšœ˜Jšœ˜—Jšœ œœœ ˜3Jšœ<˜