<<>> <> <> <> <> <> <> <> <> <> <> DIRECTORY AmpersandContext USING[StripAMNode], BreakWorldArchitecture USING [Address, BreakWorld, NewAddress, PeekContents], CCTypes USING[BreakPrintType, CCError, CCErrorCase, Conforms, CreateCompoundNameScope, GetAnyTargetType, GetNodeType, GetRopeType], CedarCode USING[GetTypeOfNode, Interpret, ShowCode, ShowNode], CedarOtherPureTypes USING[CreateIndirectToAnUnknownType, CreateRopeNode, CreateUnknownType], CedarParseSupport USING[ParseCedarExpression], CirioBackstop, CirioBreakAccess USING[BreakWorldFromBreakSet, CirioBreakSet, ClearAllBreaks, ClearBreakAtAbsAddr, ClearBreakAtIndex, ListBreaks, SetBreakAtAbsAddr], CirioMemory, CirioNub USING [Error], CirioNubAccess USING[DbgMsgNone, DbgMsgNoHandlerRequest, DbgMsgHandlerRequest, DbgMsgAbort, DbgMsgBadProceedRequest, DbgMsgBreakRequest, DbgMsgClientRequest, DbgMsgExit, DbgMsgProceed, Error, FileEntry, GetFileEntry, GetInstructionSetAndOperatingSystem, Handle, LookupMatchingSymEntryByName, LookupMatchingSymEntryByValue, LookupSymEntryByID, PCInfo, PCtoInfo, Read32BitsAsCard, RemoteAddrFault, RemoteNilFault, SymEntry], CirioSyntacticOperations USING[CompileForLHS, CompileForRHS, ParseTree, ShowParseTree], CirioTargets, CirioTypes USING[CompilerContext, Node, Type, TypedCode], Commander, CommanderOps, Convert USING[CardFromRope, Error], CParser USING [MakeCParseTree], DisassembleSPARC, FamousPath USING [DirectoryList, Get, SearchList], Frames USING[CreateIndirectGlobalFrameNode, CreateIndirectGlobalFrameType, IndirectGlobalFrameData, IndirectGlobalFrameTypeData], FS USING [Error, StreamOpen], IO, LoadStateAccess USING[BasicPCInfo, GetRopeListForLoadedFileContainingLoadedModule, GetBasicPCInfo, GetLoadedModuleInfoFromAbsPC, GetRopeForBasicPCInfo, GetRopeListForLoadedModuleInfo, LoadedModuleInfo, LoadStateHandle], MobAccess USING [MobError], MorePfsNames, NewAmpersandProcs USING[Handle, GetHandle], NewRMTW USING[CedarBreakAddress, CedarModuleSet, CedarSourcePosition, FrameNodeInfo, GetAbsAddressForBreak, GetCedarSourcePosition, GetLoadedModuleInfo, GetModuleScope, GetNodeForCedarFrame, GetRopesForCedarBreakAddress, GetRMTWInfo, LoadedModuleInfo, RawFrameInfo, RemoteMimosaTargetWorld, ShowReportByLevel], ObjectFiles USING[Module, UnreadableDotO, ModuleBody, FindVersionStamp, UnreadableObjectFile, VersionStampInfo], OneCasabaParser USING[BuildParserTableFromKipperedStream, ParserTable], PFS USING [Error, PathFromRope, RopeFromPath], PFSNames USING [Component, PATH, ShortName], PPTree USING[Link], PreDebug, RCTW USING [CBreakAddress, DescribeCBreakAddress, FrameNodeInfo, GetAbsAddressForBreak, GetFrameNodeInfo, GetSourcePosition, ProcedureFrameInfo, ProcedureFrameInfoBody], Rope, RopeParts, RopeSequence, RuntimeError USING[ArithmeticFault, BoundsFault, DivideCheck, Uncaught, ZeroDivisor], SafeStorage USING[NarrowRefFault], SourceFileOpsExtras USING [FullFormatPosition, noIndex, noPosition, noRange, Position, ShowProc], StackCirio USING[Language], StackCirioPrivate, StructuredStreams, SystemInterface USING [CirioFile, FileSet, GetCirioFile, GetFileInfo, GetNameOfFile, ShowReport, ShowSource], UnparserBufferExtras, UserProfile USING[Number], VM USING[AddressFault], WalkCedarParseTrees USING[CreatePPTreeParseTree], WalkCParseTrees USING [CreatePPTreeParseTree]; StackCirioImpl: CEDAR MONITOR LOCKS stack USING stack: Stack IMPORTS AmpersandContext, BreakWorldArchitecture, CCTypes, CedarCode, CedarOtherPureTypes, CedarParseSupport, CirioBreakAccess, CirioMemory, CirioNub, CirioNubAccess, CirioSyntacticOperations, CirioTargets, Commander, CommanderOps, Convert, CParser, DisassembleSPARC, FamousPath, Frames, FS, IO, LoadStateAccess, MobAccess, MorePfsNames, NewAmpersandProcs, NewRMTW, ObjectFiles, OneCasabaParser, PFS, PFSNames, PreDebug, RCTW, Rope, RopeParts, RopeSequence, RuntimeError, SafeStorage, SourceFileOpsExtras, StructuredStreams, SystemInterface, UnparserBufferExtras, UserProfile, VM, WalkCedarParseTrees, WalkCParseTrees EXPORTS CirioBackstop, StackCirio = BEGIN OPEN Disa:DisassembleSPARC, DOA:ObjectFiles, LSA:LoadStateAccess, MPN:MorePfsNames, RP:RopeParts, RS:RopeSequence, SS:StructuredStreams, UB:UnparserBufferExtras, StackCirioPrivate; <> DebugFlag: BOOLEAN _ FALSE; <> <<>> CedarCase: TYPE = {yes, unknown, no}; CCE: ERROR[case: CCTypes.CCErrorCase, msg: ROPE _ NIL] _ CCTypes.CCError; Stack: TYPE = REF StackBody; StackBody: PUBLIC TYPE = StackCirioPrivate.StackBody; <> <<>> famousPath: FamousPath.DirectoryList ~ FamousPath.Get["Cirio"]; cParseTable: OneCasabaParser.ParserTable _ NIL; stdMargin: INT _ 60; debugSS: BOOL _ FALSE; <> <> <<>> <<>> OpenStack: PUBLIC PROC[ampersandContext1: CirioTypes.Node, ampersandContext2: CirioTypes.Node, cc: CC, rmtw: NewRMTW.RemoteMimosaTargetWorld, cedarModules: NewRMTW.CedarModuleSet, nub: CirioNubAccess.Handle, target: CirioTargets.Target, fileSet: SystemInterface.FileSet, breaks: CirioBreakAccess.CirioBreakSet, lsh: LSA.LoadStateHandle, aph: NewAmpersandProcs.Handle, cParserTable: OneCasabaParser.ParserTable, hotFramePC: CARD, hotFrameSP: CARD, skipKFrames: CARD, ShowSource: SourceFileOpsExtras.ShowProc, reports: IO.STREAM] RETURNS[Stack] = TRUSTED BEGIN desiredHotFramePC: CARD _ hotFramePC; desiredHotFrameSP: CARD _ hotFrameSP; stack: Stack; <> loadedModule: REF LSA.LoadedModuleInfo _ NIL; initLoadedModule: PROC RETURNS[ROPE] ~ TRUSTED { loadedModule _ LSA.GetLoadedModuleInfoFromAbsPC[lsh, desiredHotFramePC]; RETURN[NIL]; }; MIPSEB: Rope.ROPE _ "MIPSEB"; IRIX: Rope.ROPE _ "IRIX"; instrSet, opSys: Rope.ROPE; [instrSet, opSys] _ CirioNubAccess.GetInstructionSetAndOperatingSystem[nub]; IF Rope.Equal[instrSet, MIPSEB] AND Rope.Equal[opSys, IRIX] THEN [] _ Protect[initLoadedModule, NIL]; BEGIN FOR n: CARD IN [0..skipKFrames) DO <> <> < GOTO beyondColdestFrame];>> desiredHotFrameSPBA: CirioMemory.BitAddr _ CirioMemory.PtrToBa[desiredHotFrameSP]; desiredHotFrameFPBA: CirioMemory.BitAddr _ target.FpFromSp[loadedModule, target, desiredHotFrameSPBA, desiredHotFramePC ! CirioNubAccess.RemoteAddrFault => GOTO beyondColdestFrame]; nextHotFramePCBA: CirioMemory.BitAddr _ target.ReadPc[loadedModule, target, desiredHotFrameSPBA, desiredHotFrameFPBA, desiredHotFramePC]; nextHotFramePC: CARD _ CirioMemory.BaToPtr[nextHotFramePCBA]; nextHotFrameSP: CARD _ CirioMemory.BaToPtr[target.NextSp[loadedModule,target, desiredHotFrameSPBA, desiredHotFrameFPBA, desiredHotFramePC]]; desiredHotFramePC _ nextHotFramePC; desiredHotFrameSP _ nextHotFrameSP; ENDLOOP; EXITS beyondColdestFrame => ERROR END; stack _ NEW[StackBody_[ tsOut: NIL, ampersandContext1: ampersandContext1, ampersandContext2: ampersandContext2, cc: cc, rmtw: rmtw, cedarModules: cedarModules, nub: nub, target: target, fileSet: fileSet, breaks: breaks, lsh: lsh, aph: aph, cParserTable: cParserTable, dummyNode: NIL, hotFramePC: desiredHotFramePC, hotFrameSP: desiredHotFrameSP, hotFrame: NIL, currentFrame: NIL, ShowSource: ShowSource, desiredLang: Cedar]]; stack.dummyNode _ BuildDummyFrameNode[stack]; RETURN[stack]; END; OpenDummyStack: PUBLIC PROC[ampersandContext1: CirioTypes.Node, ampersandContext2: CirioTypes.Node, cc: CC, rmtw: NewRMTW.RemoteMimosaTargetWorld, cedarModules: NewRMTW.CedarModuleSet, nub: CirioNubAccess.Handle, target: CirioTargets.Target, fileSet: SystemInterface.FileSet, breaks: CirioBreakAccess.CirioBreakSet, lsh: LSA.LoadStateHandle, aph: NewAmpersandProcs.Handle, cParserTable: OneCasabaParser.ParserTable, ShowSource: SourceFileOpsExtras.ShowProc, reports: IO.STREAM] RETURNS[Stack] = BEGIN stack: Stack _ NEW[StackBody_[ tsOut: NIL, ampersandContext1: ampersandContext1, ampersandContext2: ampersandContext2, cc: cc, rmtw: rmtw, cedarModules: cedarModules, nub: nub, target: target, fileSet: fileSet, breaks: breaks, lsh: lsh, aph: aph, cParserTable: cParserTable, dummyNode: NIL, hotFramePC: 0, hotFrameSP: 0, hotFrame: NIL, currentFrame: NIL, ShowSource: ShowSource, desiredLang: Cedar]]; stack.dummyNode _ BuildDummyFrameNode[stack]; RETURN[stack]; END; ShowQuickSummary: PUBLIC ENTRY PROC[stack: Stack, stopFlag: REF BOOLEAN, on: IO.STREAM, long: BOOL] = BEGIN ENABLE UNWIND => NULL; hFrame: CARD; cFrame: CARD; startFrame: BasicFrameInfo; FindHotFrame[stack, stopFlag, on, long]; hFrame _ IF stack.hotFrame # NIL THEN stack.hotFrame.frameIndex ELSE 0; cFrame _ IF stack.currentFrame # NIL THEN stack.currentFrame.basic.frameIndex ELSE 0; <> <<>> IF cFrame < hFrame THEN startFrame _ IF stack.currentFrame # NIL THEN stack.currentFrame.basic ELSE FirstFrame[stack] ELSE startFrame _ IF stack.hotFrame # NIL THEN stack.hotFrame ELSE FirstFrame[stack]; FOR frame: BasicFrameInfo _ startFrame, NextFrame[frame, stack] WHILE frame # NIL AND NOT stopFlag^ DO inner: PROC RETURNS[ROPE] = { basicPCInfo: REF LSA.BasicPCInfo _ LSA.GetBasicPCInfo[stack.lsh, frame.absPC]; rope: ROPE _ LSA.GetRopeForBasicPCInfo[basicPCInfo, frame.absPC, FALSE, long, FALSE, FALSE]; IF stack.hotFrame # NIL AND stack.hotFrame.frameIndex = frame.frameIndex THEN IO.PutRope[on, "=>"]; IF stack.currentFrame # NIL AND stack.currentFrame.basic.frameIndex = frame.frameIndex THEN IO.PutRope[on, "->"]; IO.PutF[on, "\T%g: %g\N", IO.card[frame.frameIndex], IO.rope[rope]]; RETURN[NIL]}; eMsg: ROPE _ Protect[inner, on]; IF eMsg # NIL THEN IO.PutF[on, "%g\N", [rope[eMsg]]]; ENDLOOP; IF stopFlag^ THEN IO.PutF[on, "stopped\n"]; END; FindHotFrame: PROC[stack: Stack, stopFlag: REF BOOLEAN, on: IO.STREAM, long: BOOL] = { ENABLE UNWIND => NULL; possibleHotFrame: CARD _ LAST[CARD]; MIPSEB: Rope.ROPE _ "MIPSEB"; IRIX: Rope.ROPE _ "IRIX"; instrSet, opSys: Rope.ROPE; [instrSet, opSys] _ CirioNubAccess.GetInstructionSetAndOperatingSystem[stack.nub]; IF stack.hotFrame # NIL THEN RETURN; FOR frame: BasicFrameInfo _ TopFrame[stack], NextFrame[frame, stack] WHILE frame # NIL AND stack.hotFrame = NIL AND NOT stopFlag^ DO inner: PROC RETURNS[ROPE] = { basicPCInfo: REF LSA.BasicPCInfo _ LSA.GetBasicPCInfo[stack.lsh, frame.absPC]; rope: ROPE _ LSA.GetRopeForBasicPCInfo[basicPCInfo, frame.absPC, FALSE, long, FALSE, FALSE]; IF basicPCInfo # NIL THEN { tmpRope: Rope.ROPE _ NIL; IF Rope.Equal[basicPCInfo.procedureName, stack.target.CNameToLoaderName[stack.target, "XR_CallDebugger"]] THEN { possibleHotFrame _ frame.frameIndex + 1; }; tmpRope _ stack.target.CNameToLoaderName[stack.target, "CallDebugger_"]; IF Rope.Equal[Rope.Substr[basicPCInfo.procedureName, 0, Rope.Length[tmpRope]], tmpRope] THEN { <> IF Rope.Equal[instrSet, MIPSEB] AND Rope.Equal[opSys, IRIX] THEN possibleHotFrame _ frame.frameIndex + 1 ELSE possibleHotFrame _ frame.frameIndex + 2; }; tmpRope _ stack.target.CNameToLoaderName[stack.target, "Debug_P"]; IF Rope.Equal[Rope.Substr[basicPCInfo.procedureName, 0, Rope.Length[tmpRope]], tmpRope] THEN { possibleHotFrame _ frame.frameIndex + 3; }; tmpRope _ stack.target.CNameToLoaderName[stack.target, "BreakPointPopUp_"]; IF Rope.Equal[Rope.Substr[basicPCInfo.procedureName, 0, Rope.Length[tmpRope]], tmpRope] THEN { possibleHotFrame _ frame.frameIndex + 2; }; IF Rope.Equal[basicPCInfo.procedureName, stack.target.CNameToLoaderName[stack.target, "XR_Jump5"]] THEN { possibleHotFrame _ frame.frameIndex + 1; }; IF Rope.Equal[basicPCInfo.procedureName, stack.target.CNameToLoaderName[stack.target, "XR_Jump6"]] THEN { possibleHotFrame _ frame.frameIndex + 1; }; tmpRope _ stack.target.CNameToLoaderName[stack.target, "XR_Raise"]; IF Rope.Equal[Rope.Substr[basicPCInfo.procedureName, 0, Rope.Length[tmpRope]], tmpRope] THEN { possibleHotFrame _ frame.frameIndex + 1; }; tmpRope _ stack.target.CNameToLoaderName[stack.target, "UnboundTrap"]; IF Rope.Equal[Rope.Substr[basicPCInfo.procedureName, 0, Rope.Length[tmpRope]], tmpRope] THEN { possibleHotFrame _ frame.frameIndex + 1; }; IF Rope.Equal[basicPCInfo.procedureName, stack.target.CNameToLoaderName[stack.target, "XR_Narrow"]] THEN { possibleHotFrame _ frame.frameIndex + 1; }; IF Rope.Equal[basicPCInfo.procedureName, stack.target.CNameToLoaderName[stack.target, "_sigtramp"]] THEN { possibleHotFrame _ frame.frameIndex + 1; }; }; IF possibleHotFrame = frame.frameIndex THEN { stack.hotFrame _ frame; }; RETURN[NIL]}; eMsg: ROPE _ Protect[inner, on]; IF eMsg # NIL THEN IO.PutF[on, "%g\N", [rope[eMsg]]]; ENDLOOP; }; QuickGenPossibleModuleNames: PUBLIC ENTRY PROC[stack: Stack, for: PROC[name: PATH] RETURNS[--stop-- BOOLEAN], reports: IO.STREAM] = BEGIN ENABLE UNWIND => NULL; FOR frame: BasicFrameInfo _ FirstFrame[stack], NextFrame[frame, stack] WHILE frame # NIL DO inner: PROC RETURNS[ROPE] = { basicPCInfo: REF LSA.BasicPCInfo _ LSA.GetBasicPCInfo[stack.lsh, frame.absPC]; IF ExhibitStrippedName[basicPCInfo.loadedFileName, for] THEN RETURN[NIL]; FOR names: LIST OF PATH _ basicPCInfo.possibleModuleNames, names.rest WHILE names # NIL DO IF ExhibitStrippedName[names.first, for] THEN RETURN[NIL]; ENDLOOP; RETURN[NIL]}; eMsg: ROPE _ Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; ENDLOOP; END; ExhibitStrippedName: PROC[name: PATH, for: PROC[name: PATH] RETURNS[--stop-- BOOLEAN]] RETURNS[--stop-- BOOLEAN] = BEGIN <> ropeName: ROPE _ PFS.RopeFromPath[name]; firstDot: INT _ Rope.Index[ropeName, 0, "."]; stripped: ROPE _ Rope.Substr[ropeName, firstDot]; IF Rope.Length[stripped] > 0 THEN RETURN[for[PFS.PathFromRope[stripped]]] ELSE RETURN[FALSE]; END; FirstFrame: PROC[stack: Stack] RETURNS[BasicFrameInfo] = BEGIN IF stack.hotFrame = NIL THEN stack.hotFrame _ BuildFrameInfo[stack, 0, stack.hotFramePC, stack.hotFrameSP, NIL]; RETURN[stack.hotFrame]; END; TopFrame: PROC[stack: Stack] RETURNS[BasicFrameInfo] = { RETURN[BuildFrameInfo[stack, 0, stack.hotFramePC, stack.hotFrameSP, NIL]]; }; NextFrame: PROC[current: BasicFrameInfo, stack: Stack] RETURNS[BasicFrameInfo] = TRUSTED BEGIN IF current.next = NIL THEN BEGIN <> <> <> <> <> <<>> <> <> <> <> <> <> <<>> currentSPBA: CirioMemory.BitAddr; currentFPBA: CirioMemory.BitAddr; absPCBA: CirioMemory.BitAddr; absPC: CARD; stackPointerBA: CirioMemory.BitAddr; stackPointer: CARD; loadedModule: REF LSA.LoadedModuleInfo _ NIL; initLoadedModule: PROC RETURNS[ROPE] ~ TRUSTED { loadedModule _ LSA.GetLoadedModuleInfoFromAbsPC[stack.lsh, current.absPC]; RETURN[NIL]; }; MIPSEB: Rope.ROPE _ "MIPSEB"; IRIX: Rope.ROPE _ "IRIX"; instrSet, opSys: Rope.ROPE; [instrSet, opSys] _ CirioNubAccess.GetInstructionSetAndOperatingSystem[stack.nub]; IF Rope.Equal[instrSet, MIPSEB] AND Rope.Equal[opSys, IRIX] THEN [] _ Protect[initLoadedModule, NIL]; IF loadedModule = NIL AND Rope.Equal[instrSet, MIPSEB] AND Rope.Equal[opSys, IRIX] THEN { <> <> breakWorld: BreakWorldArchitecture.BreakWorld _ CirioBreakAccess.BreakWorldFromBreakSet[stack.breaks]; address: BreakWorldArchitecture.Address _ BreakWorldArchitecture.NewAddress[breakWorld, LOOPHOLE[current.absPC+(9*4)]]; <> breakpointPC: CARD _ LOOPHOLE[BreakWorldArchitecture.PeekContents[address]]; loadedModule _ LSA.GetLoadedModuleInfoFromAbsPC[stack.lsh, breakpointPC]; IF loadedModule = NIL THEN RETURN [NIL]; current.absPC _ breakpointPC; <> <> current.stackPointer _ current.stackPointer+288; current.framePointer _ CirioMemory.BaToPtr[stack.target.FpFromSp[loadedModule, stack.target, CirioMemory.PtrToBa[current.stackPointer],current.absPC]]; }; currentSPBA _ CirioMemory.PtrToBa[current.stackPointer]; currentFPBA _ CirioMemory.PtrToBa[current.framePointer]; absPCBA _ stack.target.ReadPc[loadedModule, stack.target, currentSPBA, currentFPBA, current.absPC]; absPC _ CirioMemory.BaToPtr[absPCBA]; stackPointerBA _ stack.target.NextSp[loadedModule, stack.target, currentSPBA, currentFPBA, current.absPC]; stackPointer _ CirioMemory.BaToPtr[stackPointerBA]; current.next _ BuildFrameInfo[stack, current.frameIndex+1, absPC, stackPointer, current]; absPCBA _ stack.target.ReadPc[loadedModule, stack.target, stackPointerBA, stack.target.FpFromSp[loadedModule, stack.target, stackPointerBA, absPC], absPC]; IF absPCBA = CirioMemory.unspecdBA THEN RETURN[NIL]; END; RETURN[current.next]; END; <> <> <> <> <> BuildFrameInfo: PROC[stack: Stack, index, absPC, stackPointer: CARD, previous: BasicFrameInfo] RETURNS[BasicFrameInfo] = TRUSTED BEGIN <> IF stackPointer = 0 THEN GOTO beyondColdestFrame; -- used for dummy stack BEGIN < GOTO beyondColdestFrame]];>> <<>> info: BasicFrameInfo; stackPointerBA: CirioMemory.BitAddr; framePointerBA: CirioMemory.BitAddr; framePointer: CARD; nextStackPointerBA: CirioMemory.BitAddr; loadedModule: REF LSA.LoadedModuleInfo; initLoadedModule: PROC RETURNS[ROPE] ~ TRUSTED { loadedModule _ LSA.GetLoadedModuleInfoFromAbsPC[stack.lsh, absPC]; RETURN[NIL]; }; MIPSEB: Rope.ROPE _ "MIPSEB"; IRIX: Rope.ROPE _ "IRIX"; instrSet, opSys: Rope.ROPE; [instrSet, opSys] _ CirioNubAccess.GetInstructionSetAndOperatingSystem[stack.nub]; IF Rope.Equal[instrSet, MIPSEB] AND Rope.Equal[opSys, IRIX] THEN [] _ Protect[initLoadedModule, NIL]; IF absPC = 0 THEN GOTO beyondColdestFrame; IF loadedModule = NIL AND Rope.Equal[instrSet, MIPSEB] AND Rope.Equal[opSys, IRIX] THEN { <> << The absPC must be in the breakpoint patch area, so find the breakpoint PC. The breakpoint PC was saved in the last word of the manger. The offset from where the debugger is being called (current absPC) is 9 words. These constants should be determined somewhere and imported here.>> breakWorld: BreakWorldArchitecture.BreakWorld _ CirioBreakAccess.BreakWorldFromBreakSet[stack.breaks]; address: BreakWorldArchitecture.Address _ BreakWorldArchitecture.NewAddress[breakWorld, LOOPHOLE[absPC+(9*4)]]; <> breakpointPC: CARD _ LOOPHOLE[BreakWorldArchitecture.PeekContents[address]]; loadedModule _ LSA.GetLoadedModuleInfoFromAbsPC[stack.lsh, breakpointPC]; IF loadedModule = NIL THEN RETURN [NIL]; absPC _ breakpointPC; <> stackPointer _ stackPointer+288; }; stackPointerBA _ CirioMemory.PtrToBa[stackPointer]; <> framePointerBA _ stack.target.FpFromSp[loadedModule, stack.target, stackPointerBA, absPC ! CirioNubAccess.RemoteAddrFault => GOTO beyondColdestFrame]; framePointer _ CirioMemory.BaToPtr[framePointerBA]; nextStackPointerBA _ stack.target.NextSp[loadedModule, stack.target, stackPointerBA, framePointerBA, absPC]; IF nextStackPointerBA = CirioMemory.zeroBA THEN GOTO beyondColdestFrame; info _ NEW[BasicFrameInfoBody_[ index, absPC, framePointer, stackPointer, previous, NIL]]; IF framePointer = 0 THEN GOTO beyondColdestFrame; RETURN[info]; END; EXITS beyondColdestFrame => RETURN[NIL]; END; NoteFileCacheFlush: PUBLIC ENTRY PROC[stack: Stack] = BEGIN ENABLE UNWIND => NULL; IF FlushStackFramesFlag THEN FlushStackFrames[stack]; IF stack.currentFrame # NIL THEN { <> IF stack.target.opSys.Equal["SunOS5"] AND stack.currentFrame.basic.data # NIL THEN IF stack.currentFrame.basic.data.ledo = NIL THEN stack.currentFrame.basic.data _ NIL; stack.currentFrame _ FirstFillInFrame[stack.currentFrame.basic, stack]; }; END; FlushStackFramesFlag: BOOL _ FALSE; FlushStackFrames: PROC[stack: Stack] = { ENABLE UNWIND => NULL; startFrame: BasicFrameInfo _ NIL; IF stack.currentFrame # NIL AND stack.currentFrame.basic # NIL THEN startFrame _ stack.currentFrame.basic; IF startFrame # NIL THEN { FOR frame: BasicFrameInfo _ startFrame, frame.previous WHILE frame # NIL DO frame.data _ NIL; ENDLOOP; FOR frame: BasicFrameInfo _ startFrame.next, frame.next WHILE frame # NIL DO frame.data _ NIL; ENDLOOP; }; }; Disassemble: PUBLIC ENTRY PROC[stack: Stack, text: ROPE, reports: IO.STREAM, stop: REF BOOL _ NIL] = BEGIN ENABLE UNWIND => NULL; Inner: PROC RETURNS[ROPE] = { is: ROPE _ stack.target.instrSet; IF is.Equal["SPARC"] THEN { dn: Disa.DebugNub ~ MakeDisaDebugNub[stack.nub]; in: IO.STREAM ~ IO.RIS[text]; toke: ROPE _ in.GetTokenRope[IO.IDProc !IO.EndOfStream => GOTO Null].token; [] _ in.SkipWhitespace[]; IF NOT in.EndOf[] THEN { reports.PutRope["Only one thing at a time, please.\n"]; GOTO Null}; TRUSTED {ENABLE { Disa.Failed => { reports.PutF["%g => Error[%g]\n", [rope[toke]], [rope[errMsg]] ]; GOTO Null}; Disa.AddressFault => {a: CARD ~ LOOPHOLE[address]; reports.PutF["%g => AddressFault on addr %g=0x%08x\n", [rope[toke]], [cardinal[a]], [cardinal[a]] ]; GOTO Null}; CirioNub.Error => { reports.PutF["You're not going to like this very much. While trying to disassemble %g, CirioNub.Error[%g] was raised. This most commonly results from trying to fetch from an un-mapped address. Sadly, when this happens your connection to your remote debug nub is screwed up --- and the copy of Cirio that you're running is ususally screwed up too. Disconnect this Cirio, or, if necessary, run another debugging world, and then you should be able to reconned to your debuggee. Don't waste your time trying to disassemble this again.\n", [rope[toke]], [atom[code]] ]; GOTO Null}; }; procSE: Disa.SymEntry ~ Disa.FindSym[toke, dn, TRUE]; IF procSE#Disa.nullSymEntry THEN Disa.DisassembleProc[reports, procSE.value, Disa.EstSize[dn, procSE, TRUE], dn, NIL, stop] ELSE reports.PutF1["Unable to find a symbol for %g\n", [rope[toke]] ]; } EXITS Null => NULL} ELSE reports.PutF1["Can't show machine source for instruction set %g\n", [rope[is]] ]; RETURN [NIL]}; [] _ Protect[Inner, reports]; END; <> ResetStack: PUBLIC ENTRY PROC[stack: Stack, reports: IO.STREAM] RETURNS[newFrameIndex: CARD] = { ENABLE UNWIND => NULL; inner: PROC RETURNS[ROPE]= { frame: REF FrameData; stopFlag: REF BOOLEAN _ NEW[BOOLEAN _ FALSE]; FindHotFrame[stack, stopFlag, reports, FALSE]; frame _ FirstFillInFrame[FirstFrame[stack], stack]; stack.currentFrame _ frame; RETURN[NIL]; }; eMsg: ROPE _ Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; IF stack.currentFrame # NIL THEN RETURN[stack.currentFrame.basic.frameIndex] ELSE RETURN[0]; }; WalkStack: PUBLIC ENTRY PROC[stack: Stack, movement: INT, reports: IO.STREAM] RETURNS[actualMovement: INT, newFrameIndex: CARD] = BEGIN ENABLE UNWIND => NULL; inner: PROC RETURNS[ROPE] = BEGIN basic: BasicFrameInfo _ IF stack.currentFrame # NIL THEN stack.currentFrame.basic ELSE NIL; actualMovement _ 0; -- may be incremented or decremented IF basic # NIL AND movement < 0 THEN WHILE actualMovement > movement DO tentativeFrame: BasicFrameInfo _ basic.previous; IF tentativeFrame = NIL THEN EXIT; basic _ tentativeFrame; actualMovement _ actualMovement - 1; ENDLOOP; IF basic # NIL AND movement > 0 THEN WHILE actualMovement < movement DO tentativeFrame: BasicFrameInfo _ NextFrame[basic, stack]; IF tentativeFrame = NIL THEN EXIT; basic _ tentativeFrame; actualMovement _ actualMovement + 1; ENDLOOP; stack.currentFrame _ FirstFillInFrame[basic, stack]; newFrameIndex _ IF stack.currentFrame # NIL THEN stack.currentFrame.basic.frameIndex ELSE 0; RETURN[NIL] END; eMsg: ROPE; eMsg _ Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; WalkStackCedarFrames: PUBLIC ENTRY PROC[stack: Stack, nCedarFrames: INT, reports: IO.STREAM] RETURNS[actualNCedarFrames: INT, newFrameIndex: CARD] = BEGIN ENABLE UNWIND => NULL; inner: PROC RETURNS[ROPE] = BEGIN frame: REF FrameData _ stack.currentFrame; actualNCedarFrames _ 0; -- may be incremented or decremented IF frame # NIL AND nCedarFrames < 0 THEN WHILE actualNCedarFrames > nCedarFrames DO tentativeFrame: BasicFrameInfo _ frame.basic.previous; IF tentativeFrame = NIL THEN EXIT; frame _ FirstFillInFrame[tentativeFrame, stack]; IF frame.kind = $Cedar THEN actualNCedarFrames _ actualNCedarFrames - 1; ENDLOOP; IF frame # NIL AND nCedarFrames > 0 THEN WHILE actualNCedarFrames < nCedarFrames DO tentativeFrame: BasicFrameInfo _ NextFrame[frame.basic, stack]; IF tentativeFrame = NIL THEN EXIT; frame _ FirstFillInFrame[tentativeFrame, stack]; IF frame.kind = $Cedar THEN actualNCedarFrames _ actualNCedarFrames + 1; ENDLOOP; stack.currentFrame _ frame; newFrameIndex _ IF frame # NIL THEN frame.basic.frameIndex ELSE 0; RETURN[NIL] END; eMsg: ROPE; IF (eMsg _ Protect[inner, reports]) # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; FirstFillInFrame: PROC[basic: BasicFrameInfo, stack: Stack] RETURNS[REF FrameData] = BEGIN IF basic = NIL THEN RETURN[NIL] ELSE BEGIN IF basic.data # NIL THEN RETURN[basic.data]; basic.data _ NEW[FrameData _ [basic: basic]]; basic.data.ledo _ LSA.GetLoadedModuleInfoFromAbsPC[stack.lsh, basic.absPC, stack.cedarModules]; basic.data.basicPCInfo _ LSA.GetBasicPCInfo[stack.lsh, basic.absPC]; <> IF basic.data.ledo = NIL THEN basic.data.kind _ $C ELSE BEGIN vs: REF DOA.VersionStampInfo _ DOA.FindVersionStamp[basic.data.ledo.module]; IF vs = NIL THEN basic.data.kind _ $C ELSE basic.data.kind _ $Cedar; END; RETURN[basic.data] END; END; WalkStackToCProcedure: PUBLIC ENTRY PROC[stack: Stack, partialProcName: ROPE, moduleName: ROPE, reports: IO.STREAM] RETURNS[BOOLEAN] = BEGIN ENABLE UNWIND => NULL; foundFrame: BOOLEAN _ FALSE; inner: PROC RETURNS[ROPE] = BEGIN frame: REF FrameData _ stack.currentFrame; <> IF stack.currentFrame # NIL THEN DO tentativeFrame: BasicFrameInfo; IO.PutF[reports, " %g\N", IO.rope[frame.basicPCInfo.procedureName]]; IF Rope.Length[frame.basicPCInfo.procedureName] >= Rope.Length[partialProcName] AND Rope.Equal[partialProcName, Rope.Substr[frame.basicPCInfo.procedureName, 0, Rope.Length[partialProcName]]] THEN BEGIN IO.PutF[reports, "key procedure is %g\N", IO.rope[frame.basicPCInfo.procedureName]]; foundFrame _ TRUE; EXIT; END; tentativeFrame _ NextFrame[frame.basic, stack]; IF tentativeFrame = NIL THEN EXIT; frame _ FirstFillInFrame[tentativeFrame, stack]; <> ENDLOOP; IF foundFrame THEN stack.currentFrame _ frame; RETURN[NIL] END; eMsg: ROPE; IF (eMsg _ Protect[inner, reports]) # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; RETURN[foundFrame]; END; GetBannerForDotOofCurrentFrame: PUBLIC ENTRY PROC[stack: Stack, reports: IO.STREAM] RETURNS[ROPE] = BEGIN ENABLE UNWIND => NULL; inner: PROC RETURNS[ROPE] = BEGIN frame: REF FrameData _ stack.currentFrame; ropes: LIST OF ROPE _ LSA.GetRopeListForLoadedFileContainingLoadedModule[frame.ledo]; rope: ROPE _ NIL; FOR rps: LIST OF ROPE _ ropes, rps.rest WHILE rps # NIL DO rope _ Rope.Cat[rope, rps.first, "\N"]; ENDLOOP; RETURN[rope]; END; IF stack.currentFrame # NIL THEN RETURN[Protect[inner, reports]] ELSE RETURN["no frame"]; END; GetCurrentFrameBanner: PUBLIC ENTRY PROC[stack: Stack, reports: IO.STREAM] RETURNS[ROPE] = BEGIN ENABLE UNWIND => NULL; inner: PROC RETURNS[ROPE] = BEGIN frame: REF FrameData _ stack.currentFrame; absRope: ROPE _ IO.PutFR["absPC: %08xH, fp: %08xH, sp: %08xH", IO.card[frame.basic.absPC], IO.card[frame.basic.framePointer], IO.card[frame.basic.stackPointer]]; detail: BOOL _ frame.ledo = NIL; basicRope: ROPE _ LSA.GetRopeForBasicPCInfo[frame.basicPCInfo, frame.basic.absPC, TRUE, TRUE, detail, detail]; ropes: LIST OF ROPE _ LSA.GetRopeListForLoadedModuleInfo[frame.ledo]; rope: ROPE _ NIL; rope _ Rope.Cat[rope, absRope, "\N"]; rope _ Rope.Cat[rope, basicRope, "\N"]; FOR rps: LIST OF ROPE _ ropes, rps.rest WHILE rps # NIL DO rope _ Rope.Cat[rope, rps.first, "\N"]; ENDLOOP; IF frame.kind # $Cedar THEN rope _ rope.Concat["Can't be viewed as a Cedar frame.\n"]; RETURN[rope]; END; IF stack.currentFrame # NIL THEN RETURN[Protect[inner, reports]] ELSE RETURN["no frame"]; END; ShowCurrentFrame: PUBLIC ENTRY PROC[stack: Stack, reports: IO.STREAM] RETURNS[ROPE] = { ENABLE UNWIND => NULL; Inner: PROC RETURNS[ROPE] = { buf: IO.STREAM ~ IO.ROS[]; to: IO.STREAM ~ SS.Create[UB.NewInittedHandle[[ margin: stdMargin, output: [stream[buf]] ]]]; frame: REF FrameData _ stack.currentFrame; SS.Begin[to]; InstallFrameNode[frame, stack]; <> <<>> IO.PutF[reports, "(frame address: %g)\N", IO.card[frame.basic.framePointer]]; SELECT stack.desiredLang FROM $Cedar => IF frame.cedarFrameNode # NIL AND frame.cedarFrameNode.node # NIL THEN CedarCode.ShowNode[to, frame.cedarFrameNode.node, 3, 300, stack.cc] ELSE to.PutRope["unreadable Cedar frame, no further info"]; $C => IF frame.cFrameNode # NIL AND frame.cFrameNode.node # NIL THEN CedarCode.ShowNode[to, frame.cFrameNode.node, 3, 300, frame.cFrameNode.cc] ELSE to.PutRope["unreadable C frame, no further info"]; $Machine => ShowMachineFrame[to, stack.nub, frame]; ENDCASE => to.PutRope["unknown frame"]; SS.End[to]; RETURN[buf.RopeFromROS]}; IF stack.currentFrame # NIL THEN RETURN Protect[Inner, reports] ELSE RETURN["no frame"]; }; ShowMachineFrame: PROC [to: IO.STREAM, nub: CirioNubAccess.Handle, frame: REF FrameData] ~ { basic: BasicFrameInfo ~ frame.basic; IF basic=NIL THEN {to.PutRope["broken frame"]; RETURN}; to.PutF["pc=%08x, sp=%08x", [cardinal[basic.absPC]], [cardinal[basic.stackPointer]] ]; IF basic.stackPointer # 0 THEN { sp: CARD ~ basic.stackPointer; spPrev: INT ~ IF basic.previous#NIL THEN LOOPHOLE[basic.previous.stackPointer] ELSE 0; to.PutRope["\n%i:"]; FOR i: NAT IN [0..8) DO x: CARD ~ CirioNubAccess.Read32BitsAsCard[ [h: nub, byteAddress: sp+(i+8)*4, bitOffset: 0, nil: FALSE, valid: TRUE] ! CirioNubAccess.Error => { to.PutF[" (CirioNubAccess.Error[%g])\n", [rope[msg]] ]; GOTO Nomore}; CirioNubAccess.RemoteNilFault, CirioNubAccess.RemoteAddrFault => { to.PutRope[" (address fault)\n"]; GOTO Nomore} ]; to.PutF[" %08x", [cardinal[x]] ]; ENDLOOP; to.PutRope["\n%l:"]; FOR i: NAT IN [0..8) DO x: CARD ~ CirioNubAccess.Read32BitsAsCard[[h: nub, byteAddress: sp+(i+0)*4, bitOffset: 0, nil: FALSE, valid: TRUE] ! CirioNubAccess.Error => { to.PutF[" (CirioNubAccess.Error[%g])\n", [rope[msg]] ]; GOTO Nomore}; CirioNubAccess.RemoteNilFault, CirioNubAccess.RemoteAddrFault => { to.PutRope[" (address fault)\n"]; GOTO Nomore} ]; to.PutF[" %08x", [cardinal[x]] ]; ENDLOOP; to.PutRope["\n%o:"]; FOR i: NAT IN [0..8) DO x: CARD ~ CirioNubAccess.Read32BitsAsCard[[h: nub, byteAddress: spPrev+(i+8)*4, bitOffset: 0, nil: FALSE, valid: TRUE] ! CirioNubAccess.Error => { to.PutF[" (CirioNubAccess.Error[%g])\n", [rope[msg]] ]; GOTO Nomore}; CirioNubAccess.RemoteNilFault, CirioNubAccess.RemoteAddrFault => { to.PutRope[" (address fault)\n"]; GOTO Nomore} ]; to.PutF[" %08x", [cardinal[x]] ]; ENDLOOP; EXITS Nomore => NULL}; RETURN}; ShowSourcePosition: PUBLIC ENTRY PROC[stack: Stack, reports: IO.STREAM, stop: REF BOOL _ NIL] = BEGIN ENABLE UNWIND => NULL; pos: SourceFileOpsExtras.Position; pos _ FindSourcePosition[stack, reports]; <> IF pos # SourceFileOpsExtras.noPosition OR stack.desiredLang=$Machine THEN SELECT stack.desiredLang FROM $Cedar => { SystemInterface.ShowSource[desc: "Cedar source position", pos: pos, feedBack: reports]; }; $C => <> SystemInterface.ShowSource[desc: "C source position", pos: pos, feedBack: reports]; $Machine => { is: ROPE _ stack.target.instrSet; IF is.Equal["SPARC"] THEN TRUSTED { dn: Disa.DebugNub ~ MakeDisaDebugNub[stack.nub]; {ENABLE { Disa.Failed => { reports.PutF1["Error[%g]\n", [rope[errMsg]] ]; GOTO Null}; Disa.AddressFault => {a: CARD ~ LOOPHOLE[address]; reports.PutF["AddressFault on addr %g=0x%08x\n", [cardinal[a]], [cardinal[a]] ]; GOTO Null}; CirioNub.Error => { reports.PutF1["You're not going to like this very much. While trying to disassemble the current procedure, CirioNub.Error[%g] was raised. This most commonly results from trying to fetch from an un-mapped address. Sadly, when this happens your connection to your remote debug nub is screwed up --- and the copy of Cirio that you're running is ususally screwed up too. Disconnect this Cirio, or, if necessary, run another debugging world, and then you should be able to reconned to your debuggee. Don't waste your time trying to disassemble this procedure again.\n", [atom[code]] ]; GOTO Null}; }; procSE: Disa.SymEntry ~ dn.GetMatchingSymEntryByValue[dn, stack.currentFrame.basic.absPC, Disa.typeText, Disa.Classes[all], 0]; IF procSE#Disa.nullSymEntry THEN Disa.DisassembleProc[reports, procSE.value, Disa.EstSize[dn, procSE, TRUE], dn, NIL, stop] ELSE IO.PutF1[reports, "Couldn't find entry point for pc=0x%08x\n", [cardinal[stack.currentFrame.basic.absPC]] ]; EXITS Null => is _ is}} ELSE reports.PutF1["Can't show machine source for instruction set %g\n", [rope[is]] ]; }; ENDCASE => {} ELSE IF reports # NIL THEN IO.PutF1[reports, " couldn't ... "]; END; MakeDisaDebugNub: PROC [nub: CirioNubAccess.Handle] RETURNS [Disa.DebugNub] ~ { RETURN [NEW[Disa.DebugNubPrivate _ [ DnGetMatchingSymEntryByName, DnGetMatchingSymEntryByValue, DnGetSymEntryByID, DnGetInterfaceSlot, DnPCtoInfo, DnFetchWord, nub]]]}; DnGetMatchingSymEntryByName: PROC [nub: Disa.DebugNub, pattern: ROPE, caseSensitive: BOOLEAN, types: CARD, classes: Disa.Classes, nth: INT, from: Disa.SymID] RETURNS [Disa.SymEntry] ~ { h: CirioNubAccess.Handle ~ NARROW[nub.data]; RETURN ExportSE[CirioNubAccess.LookupMatchingSymEntryByName[h, from, pattern, caseSensitive, types, classes.ORD, nth]]}; DnGetMatchingSymEntryByValue: PROC [nub: Disa.DebugNub, val, types: CARD, classes: Disa.Classes, nth: INT, from: Disa.SymID] RETURNS [Disa.SymEntry] ~ { h: CirioNubAccess.Handle ~ NARROW[nub.data]; RETURN ExportSE[CirioNubAccess.LookupMatchingSymEntryByValue[h, from, val, types, classes.ORD, nth]]}; DnGetSymEntryByID: PROC [nub: Disa.DebugNub, id: Disa.SymID] RETURNS [Disa.SymEntry] ~ { h: CirioNubAccess.Handle ~ NARROW[nub.data]; RETURN ExportSE[CirioNubAccess.LookupSymEntryByID[h, id]]}; ExportSE: PROC [se: CirioNubAccess.SymEntry] RETURNS [Disa.SymEntry] ~ { IF se=NIL THEN RETURN [Disa.nullSymEntry]; RETURN [[ symID: se.symID, name: se.name, type: se.type, value: se.value, size: se.size, fileSeqNum: se.fileSeqNum]]}; DnGetInterfaceSlot: PROC [nub: Disa.DebugNub, ifc, item: ROPE] RETURNS [addr: CARD] ~ {RETURN [Disa.nullAddr]}; DnPCtoInfo: PROC [nub: Disa.DebugNub, pc: CARD] RETURNS [Disa.PCInfo] ~ { h: CirioNubAccess.Handle ~ NARROW[nub.data]; pci: CirioNubAccess.PCInfo ~ CirioNubAccess.PCtoInfo[h, pc]; IF pci=NIL THEN RETURN [Disa.nullPCInfo]; RETURN [[ procName: pci.procName, procSymID: pci.procSymID, fileName: PFS.RopeFromPath[pci.fileName], fileSeqNum: pci.fileSeqNum, guessedEmbeddedFileName: PFS.RopeFromPath[pci.guessedEmbeddedFileName], guessedEmbeddedFileSymID: pci.guessedEmbeddedFileSymID]]}; DnFetchWord: PROC [nub: Disa.DebugNub, addr: CARD] RETURNS [WORD] ~ { h: CirioNubAccess.Handle ~ NARROW[nub.data]; RETURN CirioNubAccess.Read32BitsAsCard[[h, addr, 0, addr=0, TRUE] !CirioNubAccess.RemoteNilFault, CirioNubAccess.RemoteAddrFault, CirioNubAccess.Error => TRUSTED {Disa.AddressFault[LOOPHOLE[addr]]} ]}; FindSourcePosition: PROC[stack: Stack, reports: IO.STREAM] RETURNS[pos: SourceFileOpsExtras.Position _ SourceFileOpsExtras.noPosition] = BEGIN ENABLE UNWIND => NULL; inner: PROC RETURNS[ROPE] = BEGIN frame: REF FrameData _ stack.currentFrame; sp: REF NewRMTW.CedarSourcePosition _ NewRMTW.GetCedarSourcePosition[stack.cedarModules, frame.ledo, frame.basic.absPC]; SELECT stack.desiredLang FROM $Cedar => { IF sp.mesa # NIL THEN { pos _ [fileName: SystemInterface.GetNameOfFile[sp.mesa], uniqueID: SystemInterface.GetFileInfo[sp.mesa].uniqueID, index: [char: [sp.mesaPosition]]]; } ELSE { pos _ SourceFileOpsExtras.noPosition; } }; $C => { IF sp.cFile # NIL THEN pos _ [fileName: SystemInterface.GetNameOfFile[sp.cFile], uniqueID: SystemInterface.GetFileInfo[sp.cFile].uniqueID, index: [line: [sp.cLineNum]]] ELSE IF frame.ledo # NIL THEN pos _ RCTW.GetSourcePosition[frame.basic.absPC, stack.cedarModules, frame.basicPCInfo, frame.ledo] ELSE pos _ SourceFileOpsExtras.noPosition; }; $Machine => pos _ SourceFileOpsExtras.noPosition; ENDCASE => RETURN["currently we can only show source position for Cedar, C, and some Machine-Language frames"]; RETURN [NIL]; END; eMsg: ROPE; IF stack.currentFrame # NIL THEN eMsg _ Protect[inner, reports] ELSE eMsg _ "no frame"; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; InterpretTextLine: PUBLIC ENTRY PROC[stack: Stack, text: ROPE, reports: IO.STREAM] RETURNS[ROPE] = { ENABLE UNWIND => {stack.tsOut _ stack.aph.out _ NIL}; CedarParse: PROC[line: ROPE, reports: IO.STREAM] RETURNS[CirioSyntacticOperations.ParseTree] = {RETURN[WalkCedarParseTrees.CreatePPTreeParseTree[CedarParseSupport.ParseCedarExpression[line, reports], stack.cc]]}; Inner: PROC RETURNS[ROPE] = { buf: IO.STREAM ~ IO.ROS[]; to: IO.STREAM ~ SS.Create[UB.Create[ publics: [ margin: stdMargin, output: [stream[buf]] ], debug: debugSS]]; debugOut: IO.STREAM _ NIL; frame: REF FrameData _ stack.currentFrame; node: CirioTypes.Node _ stack.dummyNode; -- tentative worst case cc: CC _ stack.cc; CParse: PROC[line: ROPE, reports: IO.STREAM] RETURNS[CirioSyntacticOperations.ParseTree] = { RETURN[WalkCParseTrees.CreatePPTreeParseTree[ CParser.MakeCParseTree[cParseTable, IO.RIS[line], reports], cc]]}; Doit: PROC [node: CirioTypes.Node, cc: CC, Parse: ParseProc, lang: Language] ~ { cc.nameScope _ CCTypes.CreateCompoundNameScope[stack.ampersandContext1, stack.ampersandContext2, node, cc]; -- ugh: side effects up the wazoo InterpretLine[to, text, printDepth, printWidth, cc, debugOut, TRUE, Parse, lang, reports]; RETURN}; SS.Begin[to]; IF DebugFlag THEN debugOut _ reports; IF frame#NIL AND (frame.kind=NIL OR frame.cFrameNode=NIL) THEN InstallFrameNode[frame, stack]; SELECT stack.desiredLang FROM $Cedar => { IF frame#NIL AND frame.cedarFrameNode#NIL AND frame.cedarFrameNode.node#NIL THEN node _ frame.cedarFrameNode.node; cc.moduleScope _ NewRMTW.GetModuleScope[stack.rmtw]; Doit[node, cc, CedarParse, Cedar]}; $C => { IF cParseTable=NIL THEN { tableName: ROPE ~ FamousPath.SearchList[famousPath, "c.kipperedParseTables"].fullFName; IF tableName=NIL THEN CCE[cirioError, "Couldn't find famous file c.kipperedParseTables"]; reports.PutF["Loading C parse tables from %g ...", [rope[tableName]] ]; {tableStream: IO.STREAM _ FS.StreamOpen[tableName]; cParseTable _ OneCasabaParser.BuildParserTableFromKipperedStream[tableStream]; tableStream.Close[]; tableStream _ NIL; reports.PutRope[" done reading C parse tables.\n"]}}; IF frame#NIL AND frame.cFrameNode#NIL AND frame.cFrameNode.node#NIL THEN { node _ frame.cFrameNode.node; cc _ frame.cFrameNode.cc}; Doit[node, cc, CParse, C]}; $Machine => SELECT TRUE FROM NOT mlPrefix.IsPrefix[text] => to.PutRope["Aack! You managed to delete the prompt!\n"]; ENDCASE => { dn: Disa.DebugNub ~ MakeDisaDebugNub[stack.nub]; in: IO.STREAM ~ IO.RIS[text.Substr[start: mlPrefix.Length]]; toke: ROPE; se: Disa.SymEntry; toke _ in.GetTokenRope[IO.IDProc !IO.EndOfStream => GOTO Null].token; [] _ in.SkipWhitespace[]; IF NOT in.EndOf[] THEN { to.PutRope["Only one thing at a time, please.\n"]; GOTO Null}; TRUSTED {se _ Disa.FindSym[toke, dn, FALSE ! Disa.Failed => { to.PutF["%g => Error[%g]\n", [rope[toke]], [rope[errMsg]] ]; GOTO Null}; Disa.AddressFault => {a: CARD ~ LOOPHOLE[address]; to.PutF["%g => AddressFault on addr %g=0x%08x\n", [rope[toke]], [cardinal[a]], [cardinal[a]] ]; GOTO Null}; CirioNub.Error => { to.PutF["You're not going to like this very much. While trying to interpret %g as a loader symbol, CirioNub.Error[%g] was raised. This most commonly results from trying to fetch from an un-mapped address. Sadly, when this happens your connection to your remote debug nub is screwed up --- and the copy of Cirio that you're running is ususally screwed up too. Disconnect this Cirio, or, if necessary, run another debugging world, and then you should be able to reconned to your debuggee.\n", [rope[toke]], [atom[code]] ]; GOTO Null}] }; IF se=Disa.nullSymEntry THEN to.PutF1["Unable to find a symbol for %g\n", [rope[toke]] ] ELSE {fe: CirioNubAccess.FileEntry; to.PutFL["%g => %g type=%g val=%g=0x%08x size=%g file=%g", LIST[ [rope[toke]], [rope[se.name]], [cardinal[se.type]], [cardinal[se.value]], [cardinal[se.value]], [cardinal[se.size]], [cardinal[se.fileSeqNum]] ]]; fe _ CirioNubAccess.GetFileEntry[stack.nub, se.fileSeqNum]; to.PutF1[" %g\n", [rope[PFS.RopeFromPath[fe.fileName]]] ]}; EXITS Null => cc _ stack.cc}; ENDCASE => CCE[cirioError, "InterpretTextLine[unrecognized language]"]; SS.End[to]; RETURN[buf.RopeFromROS]}; result: ROPE; stack.tsOut _ stack.aph.out _ reports; -- transient result _ Protect[Inner, reports ! NewAmpersandProcs.GetHandle => RESUME[stack.aph]]; stack.tsOut _ stack.aph.out _ NIL; -- clear out the transient RETURN[result]}; <<>> SetDesiredLanguage: PUBLIC PROC [stack: Stack, lang: Language, reports: IO.STREAM] ~ { stack.desiredLang _ lang; RETURN}; ReportDesiredLanguage: PUBLIC PROC [stack: Stack, reports: IO.STREAM _ NIL] RETURNS [Language] ~ { IF reports#NIL THEN reports.PutF["Current desired language is %g.\n", [rope[SELECT stack.desiredLang FROM $C => "C", $Cedar => "Cedar", $Machine => "Machine", ENDCASE => "Unrecognized!"]] ]; RETURN [stack.desiredLang]}; FormatPrompt: PUBLIC PROC [stack: Stack, counter: INT] RETURNS [ROPE] ~ { frame: REF FrameData _ stack.currentFrame; SELECT stack.desiredLang FROM $C => RETURN IO.PutFR["/* %g */ ", [integer[counter]] ]; $Cedar => RETURN IO.PutFR["&%g _ ", [integer[counter]] ]; $Machine => RETURN [mlPrefix]; ENDCASE => CCE[cirioError, "FormatPrompt[unrecognized language]"]}; mlPrefix: ROPE ~ ". "; <> InstallFrameNode: PROC[frame: REF FrameData, stack: Stack] = BEGIN IF frame.rawFrameInfo = NIL THEN frame.rawFrameInfo _ NEW[NewRMTW.RawFrameInfo_[ frame.basic.absPC, frame.basic.framePointer, frame.basic.stackPointer]]; IF frame.ledo#NIL THEN { frameInfo: RCTW.ProcedureFrameInfo ~ NEW [RCTW.ProcedureFrameInfoBody _ [ dotOLongName: PFS.RopeFromPath[frame.basicPCInfo.loadedFileName], mTime: frame.ledo.mtimeOfLoadedFile, size: frame.ledo.sizeOfLoadedFile, codeBase: frame.ledo.lsi[text].base, dataBase: frame.ledo.lsi[data].base, bssBase: frame.ledo.lsi[bss].base, relativePC: frame.basic.absPC - frame.ledo.lsi[text].base, framePointer: frame.basic.framePointer, stackPointer: frame.basic.stackPointer]]; frame.cFrameNode _ RCTW.GetFrameNodeInfo[ NewRMTW.GetRMTWInfo[stack.rmtw].serverName, frameInfo, stack.nub, stack.lsh, frame.ledo.module]}; IF frame.kind = $Cedar THEN { frame.loadedCedarModule _ NewRMTW.GetLoadedModuleInfo[stack.cedarModules, frame.ledo]; <> IF frame.loadedCedarModule # NIL THEN frame.cedarFrameNode _ NewRMTW.GetNodeForCedarFrame[stack.rmtw, frame.loadedCedarModule, frame.rawFrameInfo]; }; END; BuildDummyFrameNode: PROC[stack: Stack] RETURNS[CirioTypes.Node] = BEGIN gftd: REF Frames.IndirectGlobalFrameTypeData _ BuildDummyGFTD[stack]; dummyFrameType: CirioTypes.Type _ Frames.CreateIndirectGlobalFrameType[gftd, stack.cc]; igfd: REF Frames.IndirectGlobalFrameData _ BuildDummyIGFD[stack]; dummyNode: CirioTypes.Node _ Frames.CreateIndirectGlobalFrameNode[igfd, dummyFrameType, stack.cc]; RETURN[dummyNode]; END; BuildDummyGFTD: PROC[stack: Stack] RETURNS[REF Frames.IndirectGlobalFrameTypeData] = BEGIN cc: CC _ stack.cc; ut: CirioTypes.Type _ CedarOtherPureTypes.CreateUnknownType[cc, "unknown type involved in dummy frame node type"]; gftd: REF Frames.IndirectGlobalFrameTypeData _ NEW[Frames.IndirectGlobalFrameTypeData]; gftd.globalVars _ ut; RETURN[gftd] END; BuildDummyIGFD: PROC[stack: Stack] RETURNS[REF Frames.IndirectGlobalFrameData] = BEGIN cc: CC _ stack.cc; igfd: REF Frames.IndirectGlobalFrameData _ NEW[Frames.IndirectGlobalFrameData]; ut: CirioTypes.Type _ CedarOtherPureTypes.CreateUnknownType[cc, "unknown type involved in dummy frame node"]; utn: CirioTypes.Node _ CedarOtherPureTypes.CreateIndirectToAnUnknownType[ut, "unknown type node involved in dummy frame node", cc]; IF CCTypes.GetRopeType[cc]=NIL THEN igfd.descriptor _ utn ELSE igfd.descriptor _ CedarOtherPureTypes.CreateRopeNode["dummy (global) frame node", cc]; igfd.globalVars _ utn; RETURN[igfd]; END; ClearBreakPoint: PUBLIC ENTRY PROC [stack: Stack, reports: IO.STREAM] = BEGIN ENABLE UNWIND => NULL; eMsg: ROPE; inner: PROC RETURNS[ROPE] = BEGIN frame: REF FrameData _ stack.currentFrame; absAddr: CARD _ frame.basic.absPC; CirioBreakAccess.ClearBreakAtAbsAddr[stack.breaks, absAddr]; RETURN[NIL]; END; IF stack = NIL THEN eMsg _ "no stack" ELSE IF stack.currentFrame # NIL THEN eMsg _ Protect[inner, reports] ELSE eMsg _ "no frame"; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; ClearIthBreakPoint: PUBLIC ENTRY PROC [stack: Stack, i: INT, reports: IO.STREAM] = BEGIN ENABLE UNWIND => NULL; eMsg: ROPE; inner: PROC RETURNS[ROPE] = BEGIN CirioBreakAccess.ClearBreakAtIndex[stack.breaks, CARD[i]]; RETURN[NIL]; END; eMsg _ Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; ClearAllBreakPoints: PUBLIC PROC [stack: Stack, reports: IO.STREAM] = <> BEGIN inner: PROC RETURNS[ROPE] = BEGIN CirioBreakAccess.ClearAllBreaks[stack.breaks]; RETURN [" done"]; END; eMsg: ROPE; eMsg _ Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; ClearBreakPointAtPosition: PUBLIC PROC[stack: Stack, pos: SourceFileOpsExtras.Position, reports: IO.STREAM] = { inner: PROC RETURNS[ROPE] = { actual: SourceFileOpsExtras.Position; absPC: CARD; [actual, absPC] _ GetBreakAddrFromPosition[stack, pos, reports]; IF absPC # 0 THEN CirioBreakAccess.ClearBreakAtAbsAddr[stack.breaks, absPC]; RETURN [NIL]; }; eMsg: ROPE; eMsg _ Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; }; ClearBreakPointAtAddress: PUBLIC PROC[stack: Stack, addr: CARD, reports: IO.STREAM] = { inner: PROC RETURNS[ROPE] = { CirioBreakAccess.ClearBreakAtAbsAddr[stack.breaks, addr]; RETURN [NIL]; }; eMsg: ROPE; eMsg _ Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; }; GetAbsPC: PUBLIC ENTRY PROC [stack: Stack] RETURNS[CARD] = BEGIN ENABLE UNWIND => NULL; frame: REF FrameData _ stack.currentFrame; RETURN[frame.basic.absPC]; END; FrameDiagnosticInfo: PUBLIC ENTRY PROC[stack: Stack, reports: IO.STREAM] = BEGIN ENABLE UNWIND => NULL; frame: REF FrameData _ stack.currentFrame; ropes: LIST OF ROPE _ SELECT frame.kind FROM $Cedar => IF frame.cedarFrameNode # NIL THEN frame.cedarFrameNode.getDiagnosticInfo[frame.cedarFrameNode] ELSE LIST["unreadable Cedar frame"], $C => IF frame.cFrameNode # NIL THEN frame.cFrameNode.getDiagnosticInfo[frame.cFrameNode] ELSE LIST["unreadable C frame"], $none => LIST["unknown frame"], ENDCASE => LIST["unknown frame"]; FOR rps: LIST OF ROPE _ ropes, rps.rest WHILE rps # NIL DO IO.PutF[reports, "\t%g\N", IO.rope[rps.first]]; ENDLOOP; END; <> <<>> ListBreakPoints: PUBLIC PROC[stack: Stack, reports: IO.STREAM] = BEGIN inner: PROC RETURNS[ROPE] = BEGIN CirioBreakAccess.ListBreaks[stack.breaks]; RETURN [NIL]; END; eMsg: ROPE _ Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; SetBreakPointAtPosition: PUBLIC PROC[stack: Stack, pos: SourceFileOpsExtras.Position, reports: IO.STREAM, stopAll: BOOLEAN] RETURNS [whereSet: SourceFileOpsExtras.Position _ SourceFileOpsExtras.noPosition] = BEGIN inner: PROC RETURNS[ROPE] = { absPC: CARD; [whereSet, absPC] _ GetBreakAddrFromPosition[stack, pos, reports]; IF absPC # 0 THEN BEGIN <> CirioBreakAccess.SetBreakAtAbsAddr[stack.breaks, absPC, whereSet, stopAll]; END; RETURN [NIL]; }; eMsg: ROPE; eMsg _ Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; SetBreakPointAtAddress: PUBLIC PROC[stack: Stack, addr: CARD, reports: IO.STREAM, stopAll: BOOLEAN] = BEGIN inner: PROC RETURNS[ROPE] = { CirioBreakAccess.SetBreakAtAbsAddr[stack.breaks, addr, SourceFileOpsExtras.noPosition, stopAll]; RETURN [NIL]; }; eMsg: ROPE; eMsg _ Protect[inner, reports]; IF eMsg # NIL THEN IO.PutF[reports, "%g\N", [rope[eMsg]]]; END; GetBreakAddrFromPosition: PROC [stack: Stack, pos: SourceFileOpsExtras.Position, reports: IO.STREAM] RETURNS [actual: SourceFileOpsExtras.Position _ SourceFileOpsExtras.noPosition, absPC: CARD _ 0] = { srcFileName: PATH ~ pos.fileName; srcFile: SystemInterface.CirioFile; breakAddr: REF NewRMTW.CedarBreakAddress; ropes: LIST OF ROPE; shortName: PFSNames.Component; ext: RS.RopePart; parsedShort: RS.RopeSeq; IO.PutF[reports, "\Tselection is at %g.\n", [rope[SourceFileOpsExtras.FullFormatPosition[pos]]] ]; IF srcFileName = NIL THEN { IO.PutRope[reports, "Selection not in a source file; aborting.\N"]; RETURN}; srcFile _ SystemInterface.GetCirioFile[stack.fileSet, srcFileName, pos.uniqueID]; IF srcFile=NIL THEN { reports.PutRope["Couldn't access source file!\n"]; RETURN}; shortName _ srcFileName.ShortName[]; parsedShort _ RS.ParsePartToSeq[MPN.ComponentName[shortName], '.]; ext _ parsedShort.Fetch[parsedShort.Length[]-1]; SELECT TRUE FROM ext.Equal[RP.Make["mesa"], FALSE], ext.Equal[RP.Make["cedar"], FALSE] => { mesaSourcePos: INT ~ pos.index[char].first; breakAddr: REF NewRMTW.CedarBreakAddress _ NewRMTW.GetAbsAddressForBreak[stack.cedarModules, srcFile, stack.lsh, mesaSourcePos]; ropes _ NewRMTW.GetRopesForCedarBreakAddress[breakAddr]; IF breakAddr#NIL THEN { actual _ [pos.fileName, pos.uniqueID, [ [breakAddr.correspondingMesaPosition, SourceFileOpsExtras.noIndex], SourceFileOpsExtras.noRange]]; absPC _ breakAddr.absPC} ELSE absPC _ 0}; ext.Equal[RP.Make["c"], FALSE] => { breakAddr: REF RCTW.CBreakAddress ~ RCTW.GetAbsAddressForBreak[stack.fileSet, srcFile, stack.lsh, pos.index[line].first]; ropes _ RCTW.DescribeCBreakAddress[breakAddr]; IF breakAddr#NIL THEN { actual _ [pos.fileName, pos.uniqueID, [ SourceFileOpsExtras.noRange, [breakAddr.stmtLineNumber, SourceFileOpsExtras.noIndex] ]]; absPC _ breakAddr.absPC} ELSE absPC _ 0}; ENDCASE => { reports.PutRope["Source is not in a recognized language (Mesa or C); aborting.\n"]; RETURN}; FOR rps: LIST OF ROPE _ ropes, rps.rest WHILE rps # NIL DO SystemInterface.ShowReport[rps.first, $normal]; ENDLOOP; RETURN}; <> <<>> RopeForDbgMsg: PROC[msg: INT] RETURNS[ROPE] = BEGIN RETURN[SELECT msg FROM CirioNubAccess.DbgMsgNone => "None", CirioNubAccess.DbgMsgNoHandlerRequest => "NoHandlerRequest", CirioNubAccess.DbgMsgHandlerRequest => "HandlerRequest", CirioNubAccess.DbgMsgBadProceedRequest => "BadProceedRequest", CirioNubAccess.DbgMsgBreakRequest => "BreakRequest", CirioNubAccess.DbgMsgClientRequest => "ClientRequest", CirioNubAccess.DbgMsgProceed => "Proceed", CirioNubAccess.DbgMsgExit => "Kill", CirioNubAccess.DbgMsgAbort => "Abort", ENDCASE => "??"]; END; RopeForCCError: PROC[case: CCTypes.CCErrorCase, msg: ROPE] RETURNS[ROPE] = BEGIN msg1: ROPE _ SELECT case FROM none => "internal Cirio error", syntax => "syntax error", operation => "illegal operation", typeConformity => "incompatible types", unimplemented => "unimplemented feature", cirioError => "internal Cirio error", ENDCASE => "internal Cirio error"; msg2: ROPE _ IF Rope.Length[msg] = 0 THEN "" ELSE ": "; RETURN[Rope.Cat["failure due to ", msg1, msg2, msg]]; END; <> <<>> <> <<>> <> <> <> <<>> <> ParseProc: TYPE ~ PROC[line: ROPE, reports: IO.STREAM] RETURNS[CirioSyntacticOperations.ParseTree]; InterpretLine: PROC[to: IO.STREAM, line: ROPE, depth, width: INT, cc: CC, debugOut: IO.STREAM, stripNodes: BOOLEAN, parser: ParseProc, case: Language, reports: IO.STREAM] = BEGIN <> showTypeFlag: BOOLEAN _ FALSE; showCode: BOOL _ FALSE; evalit: BOOL _ TRUE; lineLength: INT; ptree: CirioSyntacticOperations.ParseTree; tc: CirioTypes.TypedCode; nd: CirioTypes.Node; amNdType: CirioTypes.Type; showNode: CirioTypes.Node; WHILE (lineLength _ Rope.Length[line]) # 0 DO SELECT TRUE FROM Rope.Fetch[line, lineLength-1] = '\n => <> line _ Rope.Replace[line, lineLength-1, 1]; Rope.Fetch[line, lineLength-1] = '? => <> BEGIN IF showTypeFlag THEN evalit _ FALSE; line _ Rope.Replace[line, lineLength-1, 1]; showTypeFlag _ TRUE; END; Rope.Fetch[line, lineLength-1] = '! => <> BEGIN line _ Rope.Replace[line, lineLength-1, 1]; depth _ depth + 1; width _ width + 10; END; Rope.Fetch[line, lineLength-1] = '$ => <> BEGIN line _ Rope.Replace[line, lineLength-1, 1]; showCode _ TRUE; debugOut _ reports; END; ENDCASE => EXIT; ENDLOOP; <> IF lineLength = 0 THEN RETURN; <> ptree _ parser[line, reports]; IF debugOut # NIL THEN IO.PutF[debugOut, "Parse Tree: %g\n", IO.rope[CirioSyntacticOperations.ShowParseTree[ptree, cc]]]; <> IF showTypeFlag THEN { <> ENABLE CCTypes.CCError => { GO TO lhsError; }; <> IF case = C THEN GOTO lhsError; <> tc _ CirioSyntacticOperations.CompileForLHS[ptree, cc]; IF showCode THEN IO.PutF[debugOut, "Code: %g\n", [rope[CedarCode.ShowCode[tc.code]]]]; <> to.PutRope["(type)"]; CCTypes.BreakPrintType[to, tc.type, depth, width, cc, " "]; RETURN; EXITS <> lhsError => NULL; }; tc _ CirioSyntacticOperations.CompileForRHS[ptree, CCTypes.GetAnyTargetType[cc], cc]; IF showCode THEN IO.PutF[debugOut, "Code: %g\n", [rope[CedarCode.ShowCode[tc.code]]]]; <> IF NOT evalit THEN { to.PutRope["(type)"]; CCTypes.BreakPrintType[to, tc.type, depth, width, cc, " "]; RETURN}; <> nd _ CedarCode.Interpret[tc.code, cc, debugOut]; <> amNdType _ CCTypes.GetNodeType[cc]; showNode _ IF (stripNodes AND CCTypes.Conforms[CedarCode.GetTypeOfNode[nd], amNdType, cc]) THEN AmpersandContext.StripAMNode[nd] ELSE nd; <> IF showTypeFlag THEN { <> showType: CirioTypes.Type _ CedarCode.GetTypeOfNode[showNode]; to.PutRope["(type)"]; CCTypes.BreakPrintType[to, showType, depth, width, cc, " "]; RETURN} ELSE { <> CedarCode.ShowNode[to, showNode, depth, width, cc]; RETURN}; END; <<>> <> <<>> treatment: {catch, reject, oz} _ catch; <> <> <> <> Protect: PUBLIC PROC[inner: PROC RETURNS[ROPE], reports: IO.STREAM] RETURNS[ROPE] = { eCase: CCTypes.CCErrorCase _ none; eMsg: ROPE _ NIL; ToGo: PROC RETURNS [BOOL] ~ { SELECT treatment FROM catch => RETURN [TRUE]; reject => RETURN [FALSE]; oz => {CallDebugger[]; RETURN[TRUE]}; ENDCASE => ERROR}; <> { ENABLE { SystemInterface.ShowReport => IF reports#NIL THEN { NewRMTW.ShowReportByLevel[reports, msgText, priority]; <> RESUME}; CCTypes.CCError => { eCase _ case; eMsg _ msg; IF ToGo[] THEN GOTO error ELSE REJECT}; MobAccess.MobError => { eCase _ cirioError; eMsg _ IO.PutFR["MobAccess.MobError[%g] (should be handled lower in Cirio)", [rope[msg]] ]; IF ToGo[] THEN GOTO error ELSE REJECT}; CirioMemory.Error => { eCase _ cirioError; eMsg _ msg; IF ToGo[] THEN GOTO error ELSE REJECT}; CirioTargets.Error => { eCase _ cirioError; eMsg _ msg; IF ToGo[] THEN GOTO error ELSE REJECT}; CirioNub.Error => { eCase _ cirioError; eMsg _ IO.PutFR["CirioNub.Error[%g] - you're probably pretty dead", [atom[code]] ]; IF ToGo[] THEN GOTO error ELSE REJECT}; CirioNubAccess.RemoteNilFault => { eCase _ operation; eMsg _ "debuggee NIL fault"; IF ToGo[] THEN GOTO error ELSE REJECT}; CirioNubAccess.RemoteAddrFault => { eCase _ cirioError; eMsg _ "debuggee Address fault"; IF ToGo[] THEN GOTO error ELSE REJECT}; CirioNubAccess.Error => { eCase _ cirioError; eMsg _ msg; IF ToGo[] THEN GOTO error ELSE REJECT}; ObjectFiles.UnreadableDotO => { eCase _ cirioError; eMsg _ IO.PutFR["ObjectFiles.UnreadableDotO[%g] (should be handled lower in Cirio)", [rope[msg]] ]; IF ToGo[] THEN GOTO error ELSE REJECT}; ObjectFiles.UnreadableObjectFile => { eCase _ cirioError; eMsg _ IO.PutFR["ObjectFiles.UnreadableObjectFile[%g] (should be handled lower in Cirio)", [rope[msg]] ]; IF ToGo[] THEN GOTO error ELSE REJECT}; FS.Error => { eCase _ cirioError; eMsg _ IO.PutFR["FS.Error[%g, %g]", [atom[error.code]], [rope[error.explanation]] ]; IF ToGo[] THEN GOTO error ELSE REJECT}; PFS.Error => { eCase _ cirioError; eMsg _ IO.PutFR["PFS.Error[%g, %g]", [atom[error.code]], [rope[error.explanation]] ]; IF ToGo[] THEN GOTO error ELSE REJECT}; VM.AddressFault => { eCase _ cirioError; eMsg _ "local debugger Address fault"; IF ToGo[] THEN GOTO error ELSE REJECT}; SafeStorage.NarrowRefFault => { eCase _ cirioError; eMsg _ "local debugger NarrowRefFault"; IF ToGo[] THEN GOTO error ELSE REJECT}; RuntimeError.ArithmeticFault => { eCase _ cirioError; eMsg _ "local debugger ArithmeticFault"; IF ToGo[] THEN GOTO error ELSE REJECT}; RuntimeError.BoundsFault => { eCase _ cirioError; eMsg _ "local debugger BoundsFault"; IF ToGo[] THEN GOTO error ELSE REJECT}; RuntimeError.DivideCheck => { eCase _ cirioError; eMsg _ "local debugger DivideCheck"; IF ToGo[] THEN GOTO error ELSE REJECT}; RuntimeError.ZeroDivisor => { eCase _ cirioError; eMsg _ "local debugger ZeroDivisor"; IF ToGo[] THEN GOTO error ELSE REJECT}; RuntimeError.Uncaught => { eCase _ cirioError; TRUSTED {eMsg _ PreDebug.Explain[signal, LOOPHOLE[parameters]]}; IF ToGo[] THEN GOTO error ELSE REJECT}; ABORTED => { eCase _ cirioError; eMsg _ "aborted"; IF ToGo[] THEN GOTO error ELSE REJECT}; }; RETURN[inner[]]; EXITS error => RETURN[RopeForCCError[eCase, eMsg]]; }; }; <<>> CallDebugger: PROC [] RETURNS [] ~ TRUSTED MACHINE CODE { "XR_CallDebugger" }; TreatmentCmd: PROC [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- ~ { argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd]; SELECT argv.argc FROM 2 => SELECT TRUE FROM argv[1].Equal["catch"] => treatment _ catch; argv[1].Equal["reject"] => treatment _ reject; argv[1].Equal["oz"] => treatment _ oz; ENDCASE => RETURN[$Failure, "Usage: CirioBugTreatment [catch|reject|oz]"]; 1 => NULL; ENDCASE => RETURN[$Failure, "Usage: CirioBugTreatment [catch|reject|oz]"]; cmd.out.PutF["Cirio's bug treatment now = %g.\n", [rope[SELECT treatment FROM catch => "catch", reject => "reject", oz => "oz", ENDCASE => ERROR]] ]; RETURN}; printDepth: CARD _ ABS[UserProfile.Number[key: "Cirio.PrintDepth", default: 3]]; printWidth: CARD _ ABS[UserProfile.Number[key: "Cirio.PrintWidth", default: 30]]; ChangePrintDepthAndWidth: Commander.CommandProc ~ { ENABLE Convert.Error => GOTO usage; numArgs:CARD _ CommanderOps.NumArgs[cmd]; IF numArgs = 3 THEN { depth: CARD _ Convert.CardFromRope[CommanderOps.NextArgument[cmd]]; width: CARD _ Convert.CardFromRope[CommanderOps.NextArgument[cmd]]; IO.PutF[cmd.out, "Print depth changed from %g to %g.\nPrint width changed from %g to %g.\n", IO.card[printDepth], IO.card[depth], IO.card[printWidth], IO.card[width]]; printDepth _ depth; printWidth _ width; } ELSE { IF numArgs # 1 THEN GOTO usage; IO.PutF[cmd.out, "Current depth: %g width: %g\n", IO.int[printDepth], IO.int[printWidth]]; }; EXITS usage => IO.PutF[cmd.out, "Usage: ChangeCirioPrintDepthAndWidth [depth width\n"]; }; Commander.Register["CirioBugTreatment", TreatmentCmd, "[catch|reject|oz] -- set or query Cirio's bug treatment"]; Commander.Register["ChangeCirioPrintDepthAndWidth", ChangePrintDepthAndWidth, "Set or query Cirio's print depth and width."]; END..