-- 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.