PopUpDriver2.mesa
Copyright Ó 1992 by Xerox Corporation. All rights reserved.
Sturgis, March 30, 1990 2:02 pm PST
Linda Howe January 8, 1990 3:14:40 pm PST
Spreitze, July 24, 1992 6:26 pm PDT
Coolidge, June 29, 1990 12:27 pm PDT
Chauser, August 27, 1990 10:34 am PDT
Laurie Horton, May 22, 1991 5:17 pm PDT
Udagawa, February 13, 1991 7:38 pm PST
Willie-s, July 27, 1992 5:59 pm PDT
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;
Viewer related code
Stolen from RemoteDriver2.mesa
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;
lets be sure Cirio is registered as the local debugger
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;
PopUp will be called by Carl (and friends) when the debuggee wants to contact the debugger, i.e. when a breakpoint is reached.
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
I belive the following test will eventually go away, when Carl arranges to turn ABORTED into a proper UNWIND. But for the moment, we have to blow the thread away when we are called for ABORTED. This logic is adapted from /pcedar2.0/Debugger/Debugger.mesa.
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];
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;
END;
BlowAwayThread:
PROC ~
TRUSTED
MACHINE
CODE {
"XR𡤎xit"
};
The address of this procedure is supplied to the breakpoint mechanism. Same world break points will call this procedure. The type of this procedure should match the type of CirioThingsImpl.CallDebugger. The behavior should mimick that of CirioThingsImpl.CallDebugger.
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;
Interpret
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]};
We do not pass a stack to CreateViewer, because the remote tool will be changing stacks from time to time. So we use a call back for interpret line.
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;
Rules
InstallRules:
PROC[d: MyViewerData] =
BEGIN
ruleButtonSet: CirioButtons.ButtonSet ¬ CirioButtons.CreateButtonSet[d.vc.self, d.vc, 0, d.ruleY, 0, d.lineH, 0];
because we throw this away, no one will do a KillButtonSet, hence it is alright to use d.vc.self as the container.
CirioButtons.MoveToY[ruleButtonSet, d.ruleY];
CirioButtons.InstallRule[ruleButtonSet];
END;
General Buttons
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[
bs: bs,
name: "ClearDir",
clientData1: d,
proc2: ClearDirAction];
[] ¬ 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
just a no op to keep CirioButtons happy.
END;
RemoveGeneralButtons:
PROC[d: MyViewerData] =
BEGIN
d.genButtonsButtonSet ¬ CirioButtons.KillButtonSet[d.genButtonsButtonSet, FALSE];
END;
Stack debug buttons
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;
Registration as uncaught signal handler and breakpoint handler
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;
Main code
Commander.Register["Interpreter", InterpDriver, "<search directory>* --- create a local debugger tool"];
Commander.Register["RegistrationlessInterpreter", InterpDriver, "<search directory list>* --- doesn't include RegisterCirio", $Registrationless];
Commander.Register["RegisterCirio", RegisterCirio, " --- to catch uncaught errors"];
Commander.Register["CirioLocal", RegisterCirio, "= RegisterCirio"];
Commander.Register["DeRegisterCirio", DeRegisterCirio];
END..