<<>> <> <> <> <> <> <> <> <> <> <> DIRECTORY CCTypes USING[CCError, CCErrorCase], CirioButtons USING[ButtonSet, CreateButtonSet, CreateViewer, GetButtonSize, InstallLabelButton, InstallRule, InstallShowFrameButton, InstallSourceLanguageButton, InstallSourcePositionButton, KillButtonSet, MainActionProc, MoveToY, ViewerControl, InstallCommandButton, InstallWalkStackButton], CirioBackstop USING[Protect], CirioTypes USING[CompilerContext], Commander USING[CommandProc, Register], CommanderOps USING[ParseToList], Containers USING[ChildXBound, Create], Convert USING[Error, RopeFromCard], DisassembleSPARC, IO USING[PutF, PutF1, PutRope, rope, STREAM], LocalCirio USING[AddSearchDirectory, Connection, DoUnderMonitorLock, FlushUnknownFileCache, GetConnection, GetDummyStack, GetStackForSelf, ReleaseConnection, ListSearchDirectory, ClearSearchDirectory], PFS USING[AbsoluteName, PathFromRope, RopeFromPath], Process USING[Detach], Rope USING[Cat, ROPE], RuntimeError USING[Aborted, RegisterUncaughtSignalHandler, UCSProc], SourceFileOps, StackCirio USING[ClearAllBreakPoints, ClearBreakPoint, FormatPrompt, GetBannerForDotOofCurrentFrame, InterpretTextLine, ListBreakPoints, ResetStack, SetBreakPointAtAddress, SetBreakPointAtPosition, ShowQuickSummary, Stack], WindowSystemInterface USING[GetSelectionContents], ViewerClasses USING[Viewer]; PopUpDriver2: CEDAR MONITOR LOCKS d USING d: MyViewerData IMPORTS CCTypes, CirioButtons, CirioBackstop, Commander, CommanderOps, Convert, Containers, DisassembleSPARC, LocalCirio, IO, PFS, Process, Rope, RuntimeError, SourceFileOps, StackCirio, WindowSystemInterface = BEGIN ROPE: TYPE = Rope.ROPE; CC: TYPE = CirioTypes.CompilerContext; CCE: ERROR[case: CCTypes.CCErrorCase, msg: ROPE ¬ NIL] ¬ CCTypes.CCError; <> <> MyViewerData: TYPE = REF MyViewerDataBody; MyViewerDataBody: TYPE = MONITORED RECORD[ vc: CirioButtons.ViewerControl ¬ NIL, abortFlag: BOOLEAN ¬ TRUE, lineH: CARD, genButtonsY: INTEGER ¬ 0, genButtonsAreaH: INTEGER ¬ 0, genButtonsButtonSet: CirioButtons.ButtonSet, stack: StackCirio.Stack ¬ NIL, frameLabel: ViewerClasses.Viewer, stackButtonsY: INTEGER ¬ 0, stackButtonsAreaH: INTEGER ¬ 0, stackButtonSet: CirioButtons.ButtonSet, ruleY: INTEGER ¬ 0, scriptY: INTEGER ¬ 0, connection: LocalCirio.Connection, stopFlag: REF BOOLEAN ¬ NIL ]; InterpDriver: Commander.CommandProc = { dirs: LIST OF ROPE ¬ CommanderOps.ParseToList[cmd].list; absDirs: LIST OF ROPE ¬ NIL; FOR dirs ¬ dirs, dirs.rest WHILE dirs#NIL DO absDirs ¬ CONS[ PFS.RopeFromPath[ PFS.AbsoluteName[ PFS.PathFromRope[dirs.first]]], absDirs]; ENDLOOP; <> IF cmd.procData.clientData # $Registrationless THEN BEGIN result: REF ANY; msg: ROPE; [result, msg] ¬ RegisterCirio[cmd]; IF result = $Failure THEN RETURN[result, msg]; END; Process.Detach[FORK ForkedInterp[absDirs]]; }; ForkedInterp: PROC [searchDirs: LIST OF ROPE] = BEGIN d: MyViewerData ¬ BasicBuildViewer[]; Protected: PROC RETURNS [ROPE] ~ { d.connection ¬ LocalCirio.GetConnection[["PopUpDriver2", "BreakPointPopUp"], d.vc.out, searchDirs]; << open a block to so that unwind catches can close the connection>> BEGIN ENABLE UNWIND => {LocalCirio.ReleaseConnection[d.connection, d.vc.out]}; localStack: StackCirio.Stack ¬ LocalCirio.GetStackForSelf[d.connection, d.vc.out]; d.stack ¬ LocalCirio.GetDummyStack[d.connection, d.vc.out]; IO.PutF1[d.vc.out, "Cirio Of %g\N", IO.rope[StackCirio.GetBannerForDotOofCurrentFrame[localStack, d.vc.out]]]; CirioButtons.MainActionProc[d.vc]; END; LocalCirio.ReleaseConnection[d.connection, d.vc.out]; RETURN [NIL]}; err: ROPE ¬ CirioBackstop.Protect[Protected, d.vc.out]; IF err#NIL THEN d.vc.out.PutF1["%g\n", [rope[err]] ]; END; <> UncaughtSignalPopUp: RuntimeError.UCSProc = <<[msg: WORD, signal: SIGNAL ANY RETURNS ANY, frame: POINTER]>> <<(except that at January 9, 1990 11:19:53 am PST the implementation calls with frame = NIL)>> BEGIN <> <<>> IF signal = LOOPHOLE[RuntimeError.Aborted] THEN BlowAwayThread[] ELSE BEGIN d: MyViewerData ¬ BasicBuildViewer[]; Protected: PROC RETURNS [ROPE] ~ { d.connection ¬ LocalCirio.GetConnection[["PopUpDriver2", "BreakPointPopUp"], d.vc.out]; <> BEGIN ENABLE UNWIND => {LocalCirio.ReleaseConnection[d.connection, d.vc.out]}; d.stack ¬ LocalCirio.GetStackForSelf[d.connection, d.vc.out]; InstallStackDebugButtons[d]; IO.PutF1[d.vc.out, "Cirio Of %g\N", IO.rope[StackCirio.GetBannerForDotOofCurrentFrame[d.stack, d.vc.out]]]; CirioButtons.MainActionProc[d.vc]; END; LocalCirio.ReleaseConnection[d.connection, d.vc.out]; RETURN [NIL]}; err: ROPE ¬ CirioBackstop.Protect[Protected, d.vc.out]; IF err#NIL THEN d.vc.out.PutF1["%g\n", [rope[err]] ]; IF d.abortFlag THEN ERROR ABORTED; END; END; BlowAwayThread: PROC ~ TRUSTED MACHINE CODE { "XR_Exit" }; <> BreakPointPopUp: PROCEDURE [key: CARD32] = BEGIN d: MyViewerData ¬ BasicBuildViewer[]; Protected: PROC RETURNS [ROPE] ~ { d.connection ¬ LocalCirio.GetConnection[["PopUpDriver2", "BreakPointPopUp"], d.vc.out]; << open a block to so that unwind catches can close the connection>> BEGIN ENABLE UNWIND => {LocalCirio.ReleaseConnection[d.connection, d.vc.out]}; d.stack ¬ LocalCirio.GetStackForSelf[d.connection, d.vc.out]; InstallStackDebugButtons[d]; IO.PutF1[d.vc.out, "Cirio Of %g\N", IO.rope[StackCirio.GetBannerForDotOofCurrentFrame[d.stack, d.vc.out]]]; CirioButtons.MainActionProc[d.vc]; END; LocalCirio.ReleaseConnection[d.connection, d.vc.out]; RETURN [NIL]}; err: ROPE ¬ CirioBackstop.Protect[Protected, d.vc.out]; IF err#NIL THEN d.vc.out.PutF1["%g\n", [rope[err]] ]; IF d.abortFlag THEN ERROR ABORTED; END; BasicBuildViewer: PROC RETURNS[MyViewerData] = BEGIN d: MyViewerData ¬ NEW[MyViewerDataBody]; d.lineH ¬ CirioButtons.GetButtonSize["Sample"].h+1; d.genButtonsY ¬ 1; d.genButtonsAreaH ¬ d.lineH+1; d.stackButtonsY ¬ d.genButtonsY+d.genButtonsAreaH+1; d.stackButtonsAreaH ¬ d.lineH; d.ruleY ¬ d.stackButtonsY+d.stackButtonsAreaH+1; d.scriptY ¬ d.ruleY+1; d.vc ¬ CirioButtons.CreateViewer["Cirio", d.scriptY, FormatPrompt, InterpretTextLine, ShutDown, d]; d.stopFlag ¬ NEW[BOOLEAN¬FALSE]; InstallRules[d]; InstallGeneralButtons[d]; RETURN[d] END; <<>> <> <<>> FormatPrompt: PROC [counter: INT, clientData: REF ANY] RETURNS [ROPE] ~ { d: MyViewerData ¬ NARROW[clientData]; IF d.stack=NIL THEN RETURN ["can't set the language without a stack"]; RETURN StackCirio.FormatPrompt[d.stack, counter]}; <<>> <> InterpretTextLine: PROC[line: ROPE, reports: IO.STREAM, clientData: REF ANY] RETURNS[ROPE] = BEGIN d: MyViewerData ¬ NARROW[clientData]; result: ROPE; interpret: PROC = {result ¬ StackCirio.InterpretTextLine[d.stack, line, reports]}; IF d.stack = NIL THEN BEGIN IO.PutRope[reports, "can't interpret without a stack"]; RETURN[NIL] END ELSE {LocalCirio.DoUnderMonitorLock[d.connection, interpret]; RETURN[result]}; END; <<>> <> <<>> InstallRules: PROC[d: MyViewerData] = BEGIN ruleButtonSet: CirioButtons.ButtonSet ¬ CirioButtons.CreateButtonSet[d.vc.self, d.vc, 0, d.ruleY, 0, d.lineH, 0]; <> CirioButtons.MoveToY[ruleButtonSet, d.ruleY]; CirioButtons.InstallRule[ruleButtonSet]; END; <> InstallGeneralButtons: PROC[d: MyViewerData] = BEGIN genButtonsViewer: ViewerClasses.Viewer ¬ Containers.Create[ info: [parent: d.vc.self, border: FALSE, scrollable: FALSE, wx: 0, wy: d.genButtonsY, ww: d.vc.self.cw, wh: d.genButtonsAreaH] ]; bs: CirioButtons.ButtonSet ¬ d.genButtonsButtonSet ¬ CirioButtons.CreateButtonSet[genButtonsViewer, d.vc, 0, 0, 0, d.lineH, 0]; Containers.ChildXBound[d.vc.self, genButtonsViewer]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "SetBreak", clientData1: d, choices: LIST[[$SetBreakAtPosition, "set breakpoint at selected source position"], [$SetBreakAtAddr, "set breakpoint at selected address"]], proc1: SetBreakAction1, proc2: SetBreakAction2]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "ListBreaks", clientData1: d, proc2: ListBreaksAction]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "ClearBreak(s)", clientData1: d, choices: LIST[[$ThisOne, "clear the active break"], [$All, "clear all breaks"], [$All, "clear all breaks"]], proc2: ClearBreakAction]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "AddDir", clientData1: d, proc1: AddDirAction1, proc2: AddDirAction2]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "ListDir", clientData1: d, proc2: ListDirAction]; <<[] _ CirioButtons.InstallCommandButton[>> <> <> <> <> [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "FlushCache", clientData1: d, proc2: FlushCacheAction]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "Stop", clientData1: d, proc1: StopAction1, proc2: StopAction2]; END; SetBreakAction1: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1: REF ANY] RETURNS [clientData2: REF ANY] ~ { SELECT key FROM $SetBreakAtPosition => { pos: SourceFileOps.Position ~ SourceFileOps.GetSelection[].pos; RETURN [NEW[SourceFileOps.Position ¬ pos]]}; $SetBreakAtAddr => { addrope: ROPE ~ WindowSystemInterface.GetSelectionContents[]; RETURN[addrope]}; ENDCASE => ERROR}; SetBreakAction2: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ~ NARROW[clientData1]; SELECT key FROM $SetBreakAtPosition => { pos: REF SourceFileOps.Position ~ NARROW[clientData2]; corresp: SourceFileOps.Position ¬ pos­; set: PROC = { corresp ¬ StackCirio.SetBreakPointAtPosition[d.stack, pos­, d.vc.out, FALSE] }; IO.PutRope[d.vc.out, "Setting break ... "]; LocalCirio.DoUnderMonitorLock[d.connection, set]; IF corresp # SourceFileOps.noPosition THEN SourceFileOps.OpenSource["break set", corresp, d.vc.out]; }; $SetBreakAtAddr => { addrope: ROPE ~ NARROW[clientData2]; addr: CARD; set: PROC = { StackCirio.SetBreakPointAtAddress[d.stack, addr, d.vc.out, FALSE]; }; TRUSTED {addr ¬ DisassembleSPARC.CardFromRope[addrope !Convert.Error => { d.vc.out.PutF["Syntax error (VAL[%g]) at %g --- selection should be an unsigned number in C or Mesa syntax", [integer[reason.ORD]], [integer[index]] ]; GOTO Bail}]}; d.vc.out.PutF1["Setting break at 0x%08x ...", [cardinal[addr]] ]; LocalCirio.DoUnderMonitorLock[d.connection, set]; EXITS Bail => NULL}; ENDCASE => ERROR; IO.PutRope[d.vc.out, " done.\n"]; END; ListBreaksAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; list: PROC = {StackCirio.ListBreakPoints[d.stack, d.vc.out]}; IO.PutRope[d.vc.out, "Listing breaks ... "]; LocalCirio.DoUnderMonitorLock[d.connection, list]; IO.PutRope[d.vc.out, " done.\n"]; END; ClearBreakAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; clearAll: BOOLEAN ¬ key = $All; IF clearAll THEN BEGIN clear: PROC = {StackCirio.ClearAllBreakPoints[d.stack, d.vc.out]}; IO.PutRope[d.vc.out, "Clearing all breaks ... "]; LocalCirio.DoUnderMonitorLock[d.connection, clear]; END ELSE BEGIN clear: PROC = {StackCirio.ClearBreakPoint[d.stack, d.vc.out]}; IO.PutRope[d.vc.out, "Clearing break ... "]; LocalCirio.DoUnderMonitorLock[d.connection, clear]; END; IO.PutRope[d.vc.out, " done.\n"]; END; AddDirAction1: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1: REF ANY] RETURNS[clientData2: REF ANY] = BEGIN rope: ROPE ¬ WindowSystemInterface.GetSelectionContents[]; IF rope = NIL THEN RETURN[NIL] ELSE RETURN[NEW[RopeHolder ¬ rope]]; END; RopeHolder: TYPE = ROPE; AddDirAction2: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; ropeHolder: REF RopeHolder ¬ NARROW[clientData2]; dirPath: ROPE ¬ IF ropeHolder = NIL THEN NIL ELSE ropeHolder­; IO.PutRope[d.vc.out, "Adding search directory ... "]; LocalCirio.AddSearchDirectory[d.connection, dirPath, d.vc.out]; IO.PutRope[d.vc.out, "Added.\n"]; END; ListDirAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; IO.PutRope[d.vc.out, "Listing directories ... "]; LocalCirio.ListSearchDirectory[d.connection, d.vc.out]; IO.PutRope[d.vc.out, " done.\n"]; END; ClearDirAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; LocalCirio.ClearSearchDirectory[d.connection, d.vc.out]; END; FlushCacheAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; IO.PutRope[d.vc.out, "Flushing unknown file cache ..."]; LocalCirio.FlushUnknownFileCache[d.connection, d.vc.out]; IO.PutRope[d.vc.out, " done flushing.\n"]; END; StopAction1: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1: REF ANY] RETURNS[clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; d.stopFlag­ ¬ TRUE; RETURN[NIL] END; StopAction2: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN <> END; RemoveGeneralButtons: PROC[d: MyViewerData] = BEGIN d.genButtonsButtonSet ¬ CirioButtons.KillButtonSet[d.genButtonsButtonSet, FALSE]; END; <<>> <<>> <> InstallStackDebugButtons: PROC[d: MyViewerData] = BEGIN subViewer: ViewerClasses.Viewer ¬ Containers.Create[ info: [parent: d.vc.self, border: FALSE, scrollable: FALSE, wx: 0, wy: d.stackButtonsY, ww: d.vc.self.cw, wh: d.stackButtonsAreaH] ]; subBs: CirioButtons.ButtonSet ¬ CirioButtons.CreateButtonSet[subViewer, d.vc, 0, 0, 0, d.lineH, 0]; Containers.ChildXBound[d.vc.self, subViewer]; d.frameLabel ¬ CirioButtons.InstallLabelButton[subBs, Rope.Cat["frame: ", Convert.RopeFromCard[StackCirio.ResetStack[d.stack, d.vc.out]], " "]]; [] ¬ CirioButtons.InstallCommandButton[ bs: subBs, name: "Summary", clientData1: d, choices: LIST[[$FullSummary, "full summary"], [$ShortSummary, "short summary"]], proc2: SummaryAction]; CirioButtons.InstallWalkStackButton[subBs, d.stack, NIL, d.frameLabel]; CirioButtons.InstallShowFrameButton[subBs, d.stack]; CirioButtons.InstallSourcePositionButton[subBs, d.stack]; [] ¬ CirioButtons.InstallCommandButton[ bs: subBs, name: "Proceed", clientData1: d, proc2: ProceedAction]; [] ¬ CirioButtons.InstallCommandButton[ bs: subBs, name: "Abort", clientData1: d, proc2: AbortAction]; CirioButtons.InstallSourceLanguageButton[subBs, d.stack]; d.stackButtonSet ¬ subBs; END; SummaryAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; show: PROC = {StackCirio.ShowQuickSummary[d.stack, d.stopFlag, d.vc.out, key=$FullSummary]}; d.stopFlag­ ¬ FALSE; LocalCirio.DoUnderMonitorLock[d.connection, show]; END; ProceedAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; d.stopFlag­ ¬ FALSE; vc.destroyStarted ¬ vc.okToDestroy ¬ TRUE; -- ugh: there should be documentation in the interface that this will indeed initiate the shutdown mechanism IO.PutRope[vc.out, "proceed\N"]; d.abortFlag ¬ FALSE; END; AbortAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; d.stopFlag­ ¬ FALSE; vc.destroyStarted ¬ vc.okToDestroy ¬ TRUE; -- ugh: there should be documentation in the interface that this will indeed initiate the shutdown mechanism IO.PutRope[vc.out, "abort\N"]; d.abortFlag ¬ TRUE; -- actually, this flag should already be true END; RemoveStackDebugButtons: PROC[d: MyViewerData] = BEGIN d.stackButtonSet ¬ CirioButtons.KillButtonSet[d.stackButtonSet, FALSE]; d.frameLabel ¬ NIL; END; <> <<>> ShutDown: PROC[clientData: REF ANY, reports: IO.STREAM] = BEGIN d: MyViewerData ¬ NARROW[clientData]; RemoveGeneralButtons[d]; RemoveStackDebugButtons[d]; END; <<>> <> forLockingOriginalUCS: MyViewerData ¬ NEW[MyViewerDataBody]; originalUCS: RuntimeError.UCSProc ¬ NIL; RegisterCirio: Commander.CommandProc = BEGIN Inner: PROC[d: MyViewerData] = BEGIN IF originalUCS = NIL THEN originalUCS ¬ RuntimeError.RegisterUncaughtSignalHandler[UncaughtSignalPopUp]; END; Inner[forLockingOriginalUCS]; END; DeRegisterCirio: Commander.CommandProc = BEGIN Inner: PROC[d: MyViewerData] = BEGIN IF originalUCS # NIL THEN BEGIN [] ¬ RuntimeError.RegisterUncaughtSignalHandler[originalUCS]; originalUCS ¬ NIL; END; END; Inner[forLockingOriginalUCS]; END; <<>> <
> Commander.Register["Interpreter", InterpDriver, "* --- create a local debugger tool"]; Commander.Register["RegistrationlessInterpreter", InterpDriver, "* --- doesn't include RegisterCirio", $Registrationless]; Commander.Register["RegisterCirio", RegisterCirio, " --- to catch uncaught errors"]; Commander.Register["CirioLocal", RegisterCirio, "= RegisterCirio"]; Commander.Register["DeRegisterCirio", DeRegisterCirio]; <<>> END..