-- XXDebugGlobals.mesa -- Edited by Bruce, October 13, 1980 6:26 PM -- Edited by Sweet, September 4, 1980 2:37 PM DIRECTORY BcdDefs: FROM "bcddefs", BcdOps: FROM "bcdops", ControlDefs: FROM "controldefs" USING [GlobalFrameHandle], DebugUsefulDefs: FROM "debugusefuldefs" USING [ Enumerate, Name, ShortCopyREAD, ShortREAD, window], Event: FROM "event", FrameDefs: FROM "framedefs", FormSW: FROM "formsw", Inline USING [COPY], Process USING [Detach, Yield], RESOut: FROM "resout", SegmentDefs: FROM "segmentdefs", State: FROM "state", STDebugDefs: FROM "stdebugdefs", StreamDefs: FROM "streamdefs", StringDefs: FROM "stringdefs" USING [ AppendString, CompareStrings, InvalidNumber, StringToNumber], SymbolSegment: FROM "symbolsegment" USING [bodyType, ctxType, extType, htType, ltType, mdType, seType, ssType, STHeader, stType, treeType], SymbolTable: FROM "symboltable" USING [Base], Table: FROM "table" USING [Base, chunkType, Selector], UserInput USING [ CancelPeriodicNotify, CreatePeriodicNotify, PeriodicNotifyHandle, PeriodicProcType], XXDebugDefs: FROM "xxdebugdefs", XXDebugGlobalDefs; XXDebugGlobals: PROGRAM IMPORTS DebugUsefulDefs, Event, FormSW, FrameDefs, Inline, Process, RESOut, SegmentDefs, STDebugDefs, StreamDefs, StringDefs, UserInput EXPORTS STDebugDefs, XXDebugDefs = BEGIN OPEN DebugUsefulDefs, RESOut, XXDebugGlobalDefs, XXDebugDefs; al: POINTER _ NIL; stateCold: POINTER _ NIL; pcPack: POINTER _ NIL; symbolCopier: POINTER _ NIL; stSource: PUBLIC STSource _ allocator; stFile: PUBLIC STRING _ NIL; stHandle: SegmentDefs.FileSegmentHandle _ NIL; stAddr: POINTER TO SymbolSegment.STHeader; -- to actual symbol table bits STMissing: SIGNAL = CODE; TopCtx: PUBLIC PROCEDURE RETURNS [State.Handle] = BEGIN IF stateCold = NIL THEN BEGIN RESOut.Complain["Base of StateCold unknown"L]; ERROR cancelAction; END; RETURN [ShortREAD[stateCold+XXDebugGlobalDefs.StateColdTopOffset]]; END; GS: PUBLIC PROCEDURE RETURNS [State.GSHandle] = BEGIN IF stateCold = NIL THEN BEGIN RESOut.Complain["Base of StateCold unknown"L]; ERROR cancelAction; END; RETURN [ShortREAD[stateCold+XXDebugGlobalDefs.StateColdGsOffset]]; END; PCCache: PUBLIC PROCEDURE RETURNS [POINTER] = BEGIN IF pcPack = NIL THEN BEGIN RESOut.Complain["Base of PCPack unknown"L]; ERROR cancelAction; END; RETURN [ShortREAD[pcPack+XXDebugGlobalDefs.PCPackCacheOffset]]; END; PCHead: PUBLIC PROCEDURE RETURNS [UNSPECIFIED] = BEGIN IF pcPack = NIL THEN BEGIN RESOut.Complain["Base of PCPack unknown"L]; ERROR cancelAction; END; RETURN [ShortREAD[pcPack+XXDebugGlobalDefs.PCPackHeadOffset]]; END; ClearFileSource: PUBLIC PROCEDURE = BEGIN IF stSource # file THEN RETURN; IF stHandle # NIL THEN { SegmentDefs.DeleteFileSegment[stHandle]; stHandle _ NIL}; stSource _ allocator; END; SourceChanged: PUBLIC FormSW.EnumeratedNotifyProcType = BEGIN lookupString: STRING _ [40]; RESOut.Complain[""L]; StreamDefs.ResetControlDEL[]; IF stHandle # NIL THEN BEGIN SegmentDefs.DeleteFileSegment[stHandle]; stHandle _ NIL; END; SELECT stSource FROM file => BEGIN OPEN SegmentDefs; IF stFile = NIL OR stFile.length > 36 THEN GO TO nope; StringDefs.AppendString[lookupString, stFile]; stHandle _ STTableForString[lookupString ! STMissing => GO TO nope]; SwapIn[stHandle]; stAddr _ FileSegmentAddress[stHandle]; PCr[]; PCr[]; PString["From file: "L]; PString[lookupString]; PChar[' ]; STDebugDefs.PutVersion[@stAddr.version]; Unlock[stHandle]; stHandle.inuse _ TRUE; RETURN; EXITS nope => BEGIN RESOut.Complain["Invalid file"L]; stSource _ none; FormSW.DisplayItem[sw, index]; END; END; allocator => BEGIN PCr[]; PCr[]; PString["From allocator symbol table"L]; END; alFrame => BEGIN PCr[]; PCr[]; PString["From Allocator per frame pointer"L]; END; spFrame => BEGIN PCr[]; PCr[]; PString["From SymbolPack per frame pointer"L]; END; copier => BEGIN IF symbolCopier = NIL THEN GO TO noCopier; PCr[]; PCr[]; PString["From SymbolCopier"L]; EXITS noCopier => BEGIN RESOut.Complain["base of SymbolCopier unknown"L]; stSource _ none; FormSW.DisplayItem[sw, index]; END; END; ENDCASE; END; LockSymbols: PUBLIC PROCEDURE = BEGIN IF stSource # file THEN RETURN; SegmentDefs.SwapIn[stHandle]; stAddr _ SegmentDefs.FileSegmentAddress[stHandle]; END; UnlockSymbols: PUBLIC PROCEDURE = BEGIN IF stHandle = NIL THEN RETURN; WHILE stHandle.lock # 0 DO SegmentDefs.Unlock[stHandle]; ENDLOOP; stHandle.inuse _ TRUE; END; TableBase: PUBLIC PROCEDURE [table: Table.Selector _ Table.chunkType] RETURNS [Table.Base] = BEGIN base: DESCRIPTOR FOR ARRAY Table.Selector OF Table.Base; SELECT stSource FROM none => BEGIN RESOut.Complain["Select source"L]; ERROR cancelAction; END; copier => BEGIN copierSymbols: SymbolTable.Base = ShortREAD[symbolCopier + XXDebugGlobalDefs.SymbolCopierIBaseOffset]; IF copierSymbols = NIL THEN GO TO noSymbols; stAddr _ ShortREAD[@copierSymbols.stHandle]; IF stAddr = NIL THEN GO TO noSymbols; RETURN[FileTableBase[table]]; EXITS noSymbols => BEGIN RESOut.Complain["SymbolCopier has no current table"L]; ERROR cancelAction; END; END; file => RETURN[FileTableBase[table]]; spFrame => BEGIN spBase: SymbolTable.Base = LOOPHOLE[StringDefs.StringToNumber[stFile, 10 ! StringDefs.InvalidNumber => GO TO noSymbols]]; IF spBase = NIL THEN GO TO noSymbols; stAddr _ ShortREAD[@spBase.stHandle]; IF stAddr = NIL THEN GO TO noSymbols; RETURN[FileTableBase[table]]; EXITS noSymbols => BEGIN RESOut.Complain["SymbolPack has no current symbols"L]; ERROR cancelAction; END; END; alFrame => BEGIN alf: POINTER = LOOPHOLE[StringDefs.StringToNumber[stFile, 10 ! StringDefs.InvalidNumber => GO TO noAl]]; ShortCopyREAD[to: @base, from: alf+AllocatorbaseOffset, nwords: SIZE[DESCRIPTOR FOR ARRAY Table.Selector OF Table.Base]]; RETURN[ShortREAD[@base[table]]]; EXITS noAl => BEGIN RESOut.Complain["addr of Allocator invalid"L]; ERROR cancelAction; END; END; ENDCASE; IF al = NIL THEN BEGIN RESOut.Complain["Base of Allocator unknown"L]; ERROR cancelAction; END; ShortCopyREAD[to: @base, from: al+AllocatorbaseOffset, nwords: SIZE[DESCRIPTOR FOR ARRAY Table.Selector OF Table.Base]]; RETURN [ShortREAD[@base[table]]]; END; FileTableBase: PROCEDURE [table: Table.Selector] RETURNS [Table.Base] = BEGIN OPEN SymbolSegment; delta: CARDINAL; SELECT table FROM treeType => delta _ STRead[@stAddr.treeBlock.offset]; seType => delta _ STRead[@stAddr.seBlock.offset]; htType => delta _ STRead[@stAddr.htBlock.offset]; ssType => delta _ STRead[@stAddr.ssBlock.offset]; ctxType => delta _ STRead[@stAddr.ctxBlock.offset]; mdType => delta _ STRead[@stAddr.mdBlock.offset]; bodyType => delta _ STRead[@stAddr.bodyBlock.offset]; ltType => delta _ STRead[@stAddr.litBlock.offset]; stType => delta _ STRead[@stAddr.sLitBlock.offset]; extType => delta _ STRead[@stAddr.extBlock.offset]; ENDCASE => ERROR; RETURN [LOOPHOLE[stAddr+delta]]; END; TableSize: PUBLIC PROCEDURE [table: Table.Selector _ Table.chunkType] RETURNS [CARDINAL] = BEGIN top: DESCRIPTOR FOR ARRAY Table.Selector OF CARDINAL; SELECT stSource FROM none => BEGIN RESOut.Complain["Select source"L]; ERROR cancelAction; END; copier => BEGIN copierSymbols: SymbolTable.Base = ShortREAD[symbolCopier + XXDebugGlobalDefs.SymbolCopierIBaseOffset]; IF copierSymbols = NIL THEN GO TO noSymbols; stAddr _ ShortREAD[@copierSymbols.stHandle]; IF stAddr = NIL THEN GO TO noSymbols; RETURN[FileTableSize[table]]; EXITS noSymbols => BEGIN RESOut.Complain["SymbolCopier has no current table"L]; ERROR cancelAction; END; END; file => RETURN [FileTableSize[table]]; ENDCASE; IF al = NIL THEN BEGIN RESOut.Complain["Base of Allocator unknown"L]; ERROR cancelAction; END; DebugUsefulDefs.ShortCopyREAD[to: @top, from: al+AllocatortopOffset, nwords: SIZE[DESCRIPTOR FOR ARRAY Table.Selector OF CARDINAL]]; RETURN [ShortREAD[@top[table]]]; END; FileTableSize: PROCEDURE [table: Table.Selector] RETURNS [size: CARDINAL] = BEGIN OPEN SymbolSegment; SELECT table FROM treeType => size _ STRead[@stAddr.treeBlock.size]; seType => size _ STRead[@stAddr.seBlock.size]; htType => size _ STRead[@stAddr.htBlock.size]; ssType => size _ STRead[@stAddr.ssBlock.size]; ctxType => size _ STRead[@stAddr.ctxBlock.size]; mdType => size _ STRead[@stAddr.mdBlock.size]; bodyType => size _ STRead[@stAddr.bodyBlock.size]; ltType => size _ STRead[@stAddr.litBlock.size]; stType => size _ STRead[@stAddr.sLitBlock.size]; extType => size _ STRead[@stAddr.extBlock.size]; ENDCASE => ERROR; RETURN; END; STRead: PUBLIC PROCEDURE [p: UNSPECIFIED] RETURNS [UNSPECIFIED] = BEGIN IF stSource = file THEN RETURN [LOOPHOLE[p, POINTER]^] ELSE RETURN[ShortREAD[p]]; END; STCopyRead: PUBLIC PROCEDURE [from: POINTER, nwords: CARDINAL, to: POINTER] = BEGIN IF stSource = file THEN Inline.COPY[from: from, nwords: nwords, to: to] ELSE DebugUsefulDefs.ShortCopyREAD[from: from, nwords: nwords, to: to]; END; STTableForString: PUBLIC PROCEDURE [name: STRING] RETURNS [SegmentDefs.FileSegmentHandle] = BEGIN OPEN SegmentDefs; file: FileHandle; base: PageNumber; pages: PageCount; symseg: FileSegmentHandle; CheckForExtension[name, ".bcd"L]; [file, base, pages] _ STFindSymbolTable[name]; symseg _ NewFileSegment[file, base, pages, Read]; RETURN[symseg] END; STFindSymbolTable: PUBLIC PROCEDURE [name: STRING] RETURNS [file: SegmentDefs.FileHandle, base: SegmentDefs.PageNumber, pages: SegmentDefs.PageCount] = BEGIN OPEN SegmentDefs, BcdDefs; headerseg: FileSegmentHandle; bcd: POINTER TO BCD; mth: BcdOps.MTHandle; sgh: BcdOps.SGHandle; file _ NewFile[name, Read, OldFileOnly ! FileNameError => ERROR STMissing]; headerseg _ NewFileSegment[file,1,1,Read]; SwapIn[headerseg]; bcd _ FileSegmentAddress[headerseg]; BEGIN OPEN bcd; ENABLE UNWIND => BEGIN Unlock[headerseg]; DeleteFileSegment[headerseg]; END; IF versionIdent # BcdDefs.VersionID OR nModules # 1 THEN ERROR STMissing; IF (pages_nPages) # 1 THEN BEGIN Unlock[headerseg]; MoveFileSegment[headerseg,1,pages]; SwapIn[headerseg]; bcd _ FileSegmentAddress[headerseg]; END; mth _ @LOOPHOLE[bcd+bcd.mtOffset, Base][FIRST[MTIndex]]; sgh _ @LOOPHOLE[bcd+bcd.sgOffset, Base][mth.sseg]; base _ sgh.base; pages _ sgh.pages+sgh.extraPages; END; Unlock[headerseg]; LockFile[file]; DeleteFileSegment[headerseg]; UnlockFile[file]; RETURN END; CheckForExtension: PROCEDURE [name, ext: STRING] = BEGIN i: CARDINAL; FOR i IN [0..name.length) DO IF name[i] = '. THEN RETURN; ENDLOOP; StringDefs.AppendString[name, ext]; RETURN END; nMods: CARDINAL = 4; LookForFrames: PROCEDURE = BEGIN moduleName: ARRAY [0..nMods) OF STRING _ [ "Allocator"L, "PcHot"L, "StateCold"L, "SymbolCopier"L]; basePtr: ARRAY [0..nMods) OF POINTER _ [ @al, @pcPack, @stateCold, @symbolCopier]; keyString: STRING = [40]; firstOut: BOOLEAN _ TRUE; i, nFound: CARDINAL; CheckOneFrame: PROCEDURE [han: ControlDefs.GlobalFrameHandle] RETURNS [BOOLEAN] = BEGIN l, u, i: CARDINAL; name: POINTER TO ARRAY [0..nMods) OF STRING = @moduleName; base: POINTER TO ARRAY [0..nMods) OF POINTER = @basePtr; key: STRING = keyString; key.length _ 0; DebugUsefulDefs.Name[name: key, gf: han]; l _ 0; u _ nMods-1; WHILE l <= u DO i _ (l+u)/2; SELECT StringDefs.CompareStrings[key, name[i], FALSE] FROM < 0 => u _ i-1; > 0 => l _ i+1; ENDCASE => BEGIN IF base[i]^ = NIL THEN BEGIN base[i]^ _ han; nFound _ nFound + 1 END ELSE BEGIN IF firstOut THEN BEGIN firstOut _ FALSE; RESOut.Complain["Duplicate: "L]; END ELSE RESOut.Complain[", "L, FALSE]; RESOut.Complain[key, FALSE]; END; EXIT END; ENDLOOP; Process.Yield[]; RETURN[nFound = nMods]; END; FOR i IN [0..nMods) DO basePtr[i]^ _ NIL; ENDLOOP; nFound _ 0; IF FrameDefs.IsBound[DebugUsefulDefs.Enumerate] THEN [] _ DebugUsefulDefs.Enumerate[CheckOneFrame]; IF nFound # nMods THEN BEGIN IF ~firstOut THEN RESOut.Complain[", "L, FALSE]; RESOut.Complain["Missing: "L, ~firstOut]; firstOut _ TRUE; FOR i IN [0..nMods) DO IF basePtr[i]^ = NIL THEN BEGIN IF firstOut THEN firstOut _ FALSE ELSE RESOut.Complain[", "L, FALSE]; RESOut.Complain[moduleName[i], FALSE]; END; ENDLOOP; END; END; LookupTheFrames: UserInput.PeriodicProcType = BEGIN periodic _ UserInput.CancelPeriodicNotify[periodic]; Process.Detach[FORK LookForFrames[]]; END; FindFrames: PUBLIC PROCEDURE = BEGIN END; Notify: Event.Notifier = BEGIN SELECT why FROM newSession => IF periodic = NIL THEN periodic _ UserInput.CreatePeriodicNotify[LookupTheFrames, DebugUsefulDefs.window, 1]; abortSession => ClearFileSource[]; ENDCASE; END; notifierItem: Event.Item _ [ eventMask: Event.Masks[newSession] + Event.Masks[abortSession], eventProc: Notify]; periodic: UserInput.PeriodicNotifyHandle _ UserInput.CreatePeriodicNotify[LookupTheFrames, DebugUsefulDefs.window, 1]; Event.AddNotifier[@notifierItem]; END.