-- Conditionals.Mesa
-- Edited by:
-- Barbara on February 9, 1979 4:40 PM
-- Sandman on July 18, 1980 11:18 AM
-- Bruce on September 26, 1980 10:42 PM
DIRECTORY
BP USING [
AbortWithError, BBHandle, BytePC, Error, Fail, FindBBNum, WriteError],
DebugFormat USING [BBHandle, Foo],
DebugOps USING [
Foo, InvalidNumber, Interpret, ShortCopyREAD, ShortCopyWRITE, ShortREAD, ShortWRITE,
StringExpToDecimal],
DI USING [dereferenced],
Inline USING [LowHalf],
MachineDefs USING [BBHandle, BYTE, ByteToRealPC, GFHandle, RealPC, RealToBytePC, WordLength, UBBPointer, UserBreakBlock],
SDDefs USING [sBreakBlock, sBreakBlockSize, SD],
State USING [ContextType, Get, GetGS, GSHandle, Handle],
Storage USING [CopyString, FreeStringNil],
Tree USING [NodeName];
Conditionals: PROGRAM
IMPORTS BP, DebugOps, DI, Inline, MachineDefs, State, Storage
EXPORTS BP =
BEGIN OPEN BP;
UBBPointer: TYPE = MachineDefs.UBBPointer;
GFHandle: TYPE = MachineDefs.GFHandle;
data: State.GSHandle ← State.GetGS[];
ubb: UBBPointer;
AttachCondition: PUBLIC PROCEDURE [bbNum, cond: STRING] =
BEGIN Conditionalize[GetBreak[bbNum],cond] END;
ClearCondition: PUBLIC PROCEDURE [bbNum: STRING] = {AttachCondition[bbNum,NIL]};
Conditionalize: PUBLIC PROC [bb: DebugFormat.BBHandle, cond: STRING] =
BEGIN
userBB: MachineDefs.UserBreakBlock;
IF bb = NIL THEN AbortWithWrittenError[notFound];
IF cond = NIL THEN {
IF bb.condition # NIL THEN bb.condition ← Storage.FreeStringNil[bb.condition];
FreeUserBB[bb.gf,bb.pc];
RETURN};
IF data.worryBreaks THEN WriteError[worryOn];
userBB ← [
frame: bb.gf, pc: MachineDefs.ByteToRealPC[bb.pc], ptrL: NIL, ptrR: NIL,
posnL: 0, posnR: 0, sizeL: 16, sizeR: 16, inst:bb.inst, relation:,
immediateR: FALSE, counterL: FALSE, localL: FALSE, localR: FALSE,
stackRelative: FALSE];
ubb ← @userBB;
ParseConditional[cond, @userBB, bb];
bb.condition ← Storage.CopyString[cond];
WriteUserBB[@userBB];
END;
GetBreak: PROC [num: STRING] RETURNS [bb: DebugFormat.BBHandle] =
BEGIN
i: INTEGER ← 0;
i ← DebugOps.StringExpToDecimal[num ! DebugOps.InvalidNumber => CONTINUE];
IF i = 0 THEN RETURN[NIL];
RETURN [BP.FindBBNum[LOOPHOLE[i,CARDINAL]]];
END;
ParseConditional: PROCEDURE [c: STRING, p: UBBPointer, bb: DebugFormat.BBHandle] =
BEGIN
h: State.Handle = State.Get[];
howSet: State.ContextType = h.howSet;
context: POINTER = h.interpretContext;
IF Counter[c,p] THEN RETURN;
h.interpretContext ← bb;
h.howSet ← break;
DebugOps.Interpret[c ! UNWIND => {h.interpretContext ← context; h.howSet ← howSet}];
h.interpretContext ← context;
h.howSet ← howSet;
RETURN
END;
Counter: PROC [c: STRING, p: UBBPointer] RETURNS [BOOLEAN] =
BEGIN
FOR i: CARDINAL IN [0..c.length) DO
IF c[i] ~IN['0..'9] THEN RETURN[FALSE];
ENDLOOP;
p.counterL ← TRUE;
p.relation ← eq;
p.ptrL ← LOOPHOLE[0];
p.ptrR ← LOOPHOLE[DebugOps.StringExpToDecimal[c]];
RETURN[TRUE];
END;
Condition: PUBLIC PROC [
left: DebugFormat.Foo, rel: Tree.NodeName, right: DebugFormat.Foo] =
BEGIN
bitsL: CARDINAL = left.words*MachineDefs.WordLength + left.bits;
bitsR: CARDINAL = right.words*MachineDefs.WordLength + right.bits;
IF DI.dereferenced THEN AbortWithWrittenError[spare1];
SELECT TRUE FROM
bitsL > MachineDefs.WordLength => AbortWithWrittenError[size];
bitsR > MachineDefs.WordLength => AbortWithWrittenError[size];
ENDCASE;
SELECT rel FROM
relE => ubb.relation ← eq;
relN => ubb.relation ← ne;
relL => ubb.relation ← lt;
relLE => ubb.relation ← le;
relG => ubb.relation ← gt;
relGE => ubb.relation ← ge;
ENDCASE => AbortWithWrittenError[invalidRelation];
ubb.ptrL ← Inline.LowHalf[left.addr.base];
ubb.posnL ← left.addr.offset;
ubb.localL ← left.addr.local;
ubb.stackRelative ← left.addr.useStack;
ubb.sizeL ← bitsL;
IF right.there THEN {
IF right.addr.useStack THEN AbortWithWrittenError[stack];
ubb.ptrR ← Inline.LowHalf[right.addr.base];
ubb.posnR ← right.addr.offset;
ubb.localR ← right.addr.local;
ubb.sizeR ← bitsR}
ELSE {
ubb.immediateR ← TRUE;
ubb.ptrR ← right.addr.base↑;
ubb.posnR ← 0;
ubb.sizeR ← 16};
END;
WriteUserBB: PUBLIC PROC [ubb: MachineDefs.UBBPointer] =
BEGIN
i: CARDINAL;
bbHandle: MachineDefs.BBHandle ← DebugOps.ShortREAD[@SDDefs.SD[SDDefs.sBreakBlock]];
i ← GetUserBB[ubb.frame, MachineDefs.RealToBytePC[ubb.pc] !
BP.Fail => {AbortWithWrittenError[type]; CONTINUE}];
DebugOps.ShortCopyWRITE[from: ubb, to: @bbHandle.blocks[i],
nwords: SIZE[MachineDefs.UserBreakBlock]];
RETURN
END;
GetUserBB: PUBLIC PROC [gf: GFHandle, pc: BytePC] RETURNS [i: CARDINAL] =
BEGIN OPEN SDDefs;
bbHandle: MachineDefs.BBHandle;
n: CARDINAL;
i ← FindUserBB[gf,pc];
IF i # LAST[CARDINAL] THEN RETURN;
bbHandle ← DebugOps.ShortREAD[@SD[sBreakBlock]];
n ← DebugOps.ShortREAD[@bbHandle.length];
IF n >= LOOPHOLE[DebugOps.ShortREAD[@SD[sBreakBlockSize]],CARDINAL] /
SIZE[MachineDefs.UserBreakBlock] THEN SIGNAL BP.Fail[tooManyConditions];
DebugOps.ShortWRITE[@bbHandle.length,n+1];
RETURN[n]
END;
FindUserBB: PUBLIC PROC [gf: GFHandle, pc: BytePC] RETURNS [i: CARDINAL] =
BEGIN OPEN SDDefs;
bbHandle: MachineDefs.BBHandle = DebugOps.ShortREAD[@SD[sBreakBlock]];
n: CARDINAL = DebugOps.ShortREAD[@bbHandle.length];
wpc: MachineDefs.RealPC = MachineDefs.ByteToRealPC[pc];
FOR i IN [0..n) DO
IF DebugOps.ShortREAD[@bbHandle.blocks[i].frame] = gf
AND DebugOps.ShortREAD[@bbHandle.blocks[i].pc] = wpc
THEN RETURN[i];
ENDLOOP;
RETURN[LAST[CARDINAL]]
END;
FreeUserBB: PUBLIC PROCEDURE [gf: GFHandle, pc: BytePC] =
BEGIN OPEN SDDefs;
i: CARDINAL = FindUserBB[gf,pc];
bbHandle: MachineDefs.BBHandle;
n: CARDINAL;
local: MachineDefs.UserBreakBlock;
IF i = LAST[CARDINAL] THEN AbortWithWrittenError[conditionNotFound];
bbHandle ← DebugOps.ShortREAD[@SD[sBreakBlock]];
n ← DebugOps.ShortREAD[@bbHandle.length];
FOR j: CARDINAL IN [i+1..n) DO
DebugOps.ShortCopyREAD[from: @bbHandle.blocks[j], to: @local,
nwords: SIZE[MachineDefs.UserBreakBlock]];
DebugOps.ShortCopyWRITE[from: @local, to: @bbHandle.blocks[j-1],
nwords: SIZE[MachineDefs.UserBreakBlock]];
ENDLOOP;
DebugOps.ShortWRITE[@bbHandle.length,n-1];
RETURN
END;
AbortWithWrittenError: PUBLIC PROC [err: Error] = {WriteError[err]; AbortWithError[err]};
END.