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