-- DumpCold.mesa; modified by Bruce, October 25, 1980 10:00 PM DIRECTORY Ascii USING [SP], DebugFormat USING [BitAddress, Fob, Foo, OctalFormat], DebugOps USING [Display, DisplayFoo, Foo, FooProc, Interpret, LongREAD, UserAborted], DI USING [ BitAddress, CheckClass, CSEIndex, DerefProcDesc, Foo, GetControlLink, GetDesc, GetLongDesc, LongDesc, Normalize, NotAProcedure, SEIndex, TransferSEIndex, TypeForSe, FindField, GetValue, SequenceSEIndex], DOutput USING [Char, Decimal, Number, Octal, Text], Dump USING [ ArrayHandle, ArrayInfo, BadNum, HashVal, LongNum, Printer, PrintRec, PrintUCS, NullVariant], Frames USING [Invalid], Gf USING [Display, DisplayInMsg, FrameGfi, Handle, OldLink, Validate], DHeap USING [AllocFob], Init USING [], Inline USING [LongDivMod, LongMult], Lookup USING [Signal], MachineDefs USING [WordLength], Pc USING [LinkToIsei], PrincOps USING [ControlLink, Port, ProcDesc, SignalDesc], State USING [GetGS, GSHandle], Storage USING [Node], SymbolOps USING [BitsPerElement, Cardinality], SymbolPack, Symbols USING [ ArraySEIndex, CSEIndex, HTIndex, HTNull, ISEIndex, ISENull, SEIndex, SENull, RecordSEIndex, seType, TransferMode, TypeClass], Table USING [AddNotify, Base, DropNotify, Notifier], TajoMisc USING [initialToolStateDefault], Types USING [Equivalent, Handle], UserInput USING [ResetUserAbort, userAbort]; DumpCold: PROGRAM IMPORTS DebugOps, DI, DOutput, Dump, Frames, Gf, DHeap, Inline, Lookup, Pc, State, Storage, SymbolOps, MyBase: SymbolPack, Table, TajoMisc, Types, UserInput EXPORTS Dump, Init = BEGIN OPEN DI, Dump, SymbolOps, Symbols; TriedToPrintWrongType: ERROR [foo: Foo] = CODE; BadTag: ERROR = CODE; seb: Table.Base; data: State.GSHandle ← State.GetGS[]; printers: PUBLIC POINTER TO PrintRec ← NIL; entryDepth: CARDINAL ← 0; ArrayLimit: PUBLIC CARDINAL ← LAST[CARDINAL]; Enter: PROCEDURE = { IF entryDepth = 0 THEN Table.AddNotify[Notify]; entryDepth ← entryDepth + 1}; Exit: PROC = {IF (entryDepth ← entryDepth-1) = 0 THEN Table.DropNotify[Notify]}; Notify: Table.Notifier = {seb ← base[seType]}; AddPrinter: PUBLIC PROCEDURE [type: STRING, proc: Printer] = BEGIN Type: DebugOps.FooProc = {p.tsei ← f.tsei}; p: POINTER TO PrintRec ← Storage.Node[SIZE[PrintRec]]; p↑ ← [ link: printers, sym: type, tsei: SENull, proc: proc]; IF TajoMisc.initialToolStateDefault # inactive THEN DebugOps.Interpret[p.sym, Type ! ANY => {p.tsei ← SENull; CONTINUE}]; printers ← p; END; ResetPrinters: PUBLIC PROCEDURE = BEGIN Type: DebugOps.FooProc = {p.tsei ← f.tsei}; p: POINTER TO PrintRec; FOR p ← printers, p.link UNTIL p = NIL DO DebugOps.Interpret[p.sym, Type ! ANY => {p.tsei ← SENull; CONTINUE}]; ENDLOOP; END; CompareSes: PUBLIC PROC [sei1, sei2: Symbols.SEIndex] RETURNS [print: BOOLEAN] = BEGIN left: Types.Handle ← [LOOPHOLE[MyBase],TypeForSe[sei1]]; right: Types.Handle ← [LOOPHOLE[MyBase],TypeForSe[sei2]]; RETURN[Types.Equivalent[type1: left, type2: right]]; END; Sequence: PUBLIC PROC [f: Foo, pad: CARDINAL, sei: DI.SequenceSEIndex, variant: PROC RETURNS [Symbols.RecordSEIndex] ← NullVariant] = BEGIN tag: Foo; ai: ArrayInfo; ba: BitAddress; words: CARDINAL; Enter[]; IF ~seb[sei].controlled THEN {DOutput.Text["(?) ..."L]; Exit[]; RETURN}; tag ← DI.FindField[f,pad,seb[sei].tagSei]; IF tag.bits + tag.addr.offset > MachineDefs.WordLength THEN ERROR BadTag; ba ← [base: tag.addr.base, offset: ]; [words, ba.offset] ← Normalize[tag.addr.offset+tag.bits]; ba.base ← tag.words + ba.base + words; DI.GetValue[tag]; ai ← [start: 0, stop: tag.addr.base↑, length: tag.addr.base↑, addr: ba, packing: SymbolOps.BitsPerElement[seb[sei].componentType, seb[sei].packed], type: seb[sei].componentType]; Elements[@ai ! DebugOps.UserAborted => {ControlDel[]; CONTINUE}; UNWIND => Exit[]]; Exit[]; END; Array: PUBLIC PROCEDURE [f: Foo] = BEGIN sei: ArraySEIndex ← CheckClass[array, f]; Enter[]; ArrayCommon[sei, f.addr, Cardinality[seb[sei].indexType] ! UNWIND => Exit[]]; Exit[]; END; ArrayCommon: PROCEDURE [tsei: SEIndex, ba: BitAddress, length: CARDINAL] = BEGIN csei: CSEIndex ← DI.TypeForSe[tsei]; sei: ArraySEIndex; ai: ArrayInfo; Enter[]; IF seb[csei].typeTag = array THEN sei ← LOOPHOLE[csei] ELSE {Exit[]; ERROR TriedToPrintWrongType[NIL]}; ai ← [start: 0, stop: length, length: length, addr: ba, packing: SymbolOps.BitsPerElement[seb[sei].componentType, seb[sei].packed], type: seb[sei].componentType]; Elements[@ai ! DebugOps.UserAborted => {ControlDel[]; CONTINUE}; UNWIND => Exit[]]; Exit[]; END; LongArrayDesc: PUBLIC PROCEDURE [f: Foo] = BEGIN OPEN DOutput; d: DI.LongDesc; sei: ArraySEIndex; [d,sei] ← DI.GetLongDesc[f]; Text["DESCRIPTOR["L]; LongNum[d.base, [pointer[]]]; Char[',]; MyDecimal[d.length]; Char[']]; IF d.base = NIL THEN RETURN; ArrayCommon[sei, [d.base,0], d.length]; END; ArrayDesc: PUBLIC PROCEDURE [f: Foo] = BEGIN OPEN DOutput; d: DI.LongDesc; sei: ArraySEIndex; [d,sei] ← DI.GetDesc[f]; Text["DESCRIPTOR["L]; LongNum[d.base, [pointer[]]]; Char[',]; MyDecimal[d.length]; Char[']]; IF d.base = NIL THEN RETURN; ArrayCommon[sei, [d.base,0], d.length]; END; Elements: PUBLIC PROCEDURE [ai: ArrayHandle, printAll: BOOLEAN ← FALSE] = BEGIN OPEN DOutput; i: CARDINAL; f: Foo; fob: DebugFormat.Fob ← [ hti: HTNull, indent: 0, xfer: FALSE, tsei: ai.type, typeOnly: FALSE, there: TRUE, addr:, words:, bits:, nesting: 0]; [fob.words, fob.bits] ← Normalize[ai.packing]; fob.addr ← CalculateAddr[ai, ai.start]; Char['(]; MyDecimal[ai.length]; Text[")["L]; FOR i IN [ai.start..ai.stop) DO IF i # ai.start THEN Text[", "L]; f ← DHeap.AllocFob[]; f↑ ← fob; IF i = 3 AND ~printAll AND ai.length > ArrayLimit THEN BEGIN f.addr ← CalculateAddr[ai, ai.stop-1]; Text["..., "L]; DebugOps.Display[f,TRUE]; EXIT; END; DebugOps.Display[f,TRUE]; NextAddr[@fob,ai.packing]; IF UserInput.userAbort THEN {ControlDel[]; RETURN}; ENDLOOP; Char[']]; END; CalculateAddr: PUBLIC PROC [ai: ArrayHandle, n: CARDINAL] RETURNS [ba: BitAddress] = BEGIN OPEN Inline, MachineDefs; words, offset: CARDINAL; ba.useStack ← ai.addr.useStack; [words, offset] ← Normalize[ai.packing]; ba.base ← ai.addr.base + LongMult[words, n]; [words, ba.offset] ← LongDivMod[LongMult[offset, n], WordLength]; ba.base ← ba.base + words; [words, ba.offset] ← Normalize[ba.offset+ai.addr.offset]; ba.base ← ba.base + words; RETURN END; NextAddr: PROCEDURE [f: Foo, packing: CARDINAL] = BEGIN words, bits: CARDINAL; [words, bits] ← Normalize[packing]; IF bits = 0 THEN BEGIN f.addr.base ← f.addr.base + words; RETURN END; IF bits + f.addr.offset = 16 THEN BEGIN f.addr.base ← f.addr.base + 1; f.addr.offset ← 0 END ELSE f.addr.offset ← f.addr.offset + bits; RETURN; END; BadDesc: PROC [cl: PrincOps.ControlLink] = { IF cl.gfi = 0 OR ~cl.tag THEN BadNum[Gf.OldLink[cl]] ELSE { DOutput.Char['[]; DOutput.Octal[Gf.OldLink[cl]]; DOutput.Char[']]}}; XferName: PUBLIC PROC [cl: PrincOps.ProcDesc, isei: ISEIndex] = {IF isei = ISENull THEN BadDesc[cl] ELSE HashVal[isei]}; XferFrame: PUBLIC PROC [cl: PrincOps.ProcDesc] = BEGIN Gf.DisplayInMsg[Gf.FrameGfi[cl.gfi], "module"L] END; Sig: PUBLIC PROC [cl: PrincOps.ProcDesc] = BEGIN IF data.signal = cl THEN Dump.PrintUCS[] ELSE {XferName[cl, Lookup.Signal[cl]]; XferFrame[cl]}; END; Xfer: PUBLIC PROCEDURE [f: Foo] = BEGIN ENABLE UNWIND => Exit[]; sei: TransferSEIndex ← CheckClass[transfer, f]; cl: PrincOps.ControlLink; Enter[]; IF seb[sei].mode # process THEN cl ← DI.GetControlLink[f]; SELECT seb[sei].mode FROM proc => Proc[cl]; port => Port[cl]; signal => {DOutput.Text["SIGNAL "L]; Sig[LOOPHOLE[cl]]}; error => {DOutput.Text["ERROR "L]; Sig[LOOPHOLE[cl]]}; process => {DI.GetValue[f]; Process[f.addr.base↑]}; program => Prog[cl]; ENDCASE => ERROR TriedToPrintWrongType[f]; Exit[]; END; Proc: PUBLIC PROC [cl: PrincOps.ControlLink] = BEGIN DOutput.Text["PROCEDURE "L]; BEGIN ENABLE Frames.Invalid => GOTO bad; cl ← DI.DerefProcDesc[cl ! DI.NotAProcedure => GOTO bad]; XferName[LOOPHOLE[cl], Pc.LinkToIsei[cl]]; XferFrame[LOOPHOLE[cl]]; EXITS bad => BadDesc[cl]; END; END; Port: PUBLIC PROC [cl: PrincOps.ControlLink] = BEGIN OPEN DOutput; Text["PORT ["L]; Octal[cl.port.in]; Text[", "L]; Octal[cl.port.out]; Char[']]; END; Process: PUBLIC PROC [psb: UNSPECIFIED] = {DOutput.Text["PROCESS ["L]; DOutput.Octal[psb]; DOutput.Char[']]}; Prog: PUBLIC PROC [gf: UNSPECIFIED] = BEGIN IF Gf.Validate[gf] THEN Gf.Display[gf,"PROGRAM"L] ELSE BadDesc[gf]; END; Opaque: PUBLIC PROCEDURE [f: Foo] = BEGIN osei: Symbols.CSEIndex ← CheckClass[opaque, f]; proc: PROCEDURE [LONG POINTER] RETURNS [UNSPECIFIED] ← IF f.there THEN DebugOps.LongREAD ELSE ReadMem; Enter[]; WITH seb[osei] SELECT FROM opaque => BEGIN IF id # Symbols.ISENull THEN HashVal[id]; IF lengthKnown AND length # 0 THEN BEGIN n: CARDINAL; size: CARDINAL = length/MachineDefs.WordLength; DOutput.Char['(]; DOutput.Octal[size]; DOutput.Text["):"L]; FOR j: CARDINAL IN [0..size) DO DOutput.Char[' ]; DOutput.Number[n ← proc[f.addr.base+j], DebugFormat.OctalFormat]; DOutput.Char[IF n ~IN[0..7] THEN 'B ELSE Ascii.SP]; IF UserInput.userAbort THEN {ControlDel[]; RETURN}; ENDLOOP; END; END; ENDCASE; Exit[]; END; ReadMem: PUBLIC PROC [p: LONG POINTER] RETURNS [UNSPECIFIED] = {RETURN[p↑]}; MyDecimal: PROCEDURE [u: UNSPECIFIED] = INLINE {DOutput.Decimal[LOOPHOLE[u,INTEGER]]}; ControlDel: PROC = {UserInput.ResetUserAbort[]; DOutput.Text[" ... aborted"L]}; ModeName: PUBLIC PROCEDURE [n: TransferMode] = BEGIN ModePrintName: ARRAY TransferMode OF STRING = ["PROCEDURE"L, "PORT"L, "SIGNAL"L, "ERROR"L, "PROCESS"L, "PROGRAM"L, "NONE"L]; DOutput.Text[ModePrintName[n]] END; END.