RemoteDriver3.mesa
Copyright Ó 1990, 1991, 1992, 1993 by Xerox Corporation. All rights reserved.
Sturgis, April 3, 1990 11:50 am PDT
Linda Howe, January 8, 1990 1:19:50 pm PST
Last tweaked by Mike Spreitzer on July 24, 1992 5:15 pm PDT
Laurie Horton, September 17, 1992 8:54 am PDT
Udagawa, February 14, 1991 4:23 pm PST
Philip James, March 6, 1992 10:25 am PST
Willie-s, August 26, 1992 12:15 pm PDT
Katsuyuki Komatsu January 23, 1993 4:36 pm PST
DIRECTORY
Buttons USING [Button, ButtonProc, Create],
CCTypes USING[CCError, CCErrorCase],
CirioButtons USING[ButtonSet, ButtonSize, ChoiceList, CreateButtonSet, CreateViewer, GetButtonSize, InstallCommandButton, InstallLabelButton, InstallSourceLanguageButton, InstallRule, InstallShowFrameButton, InstallSourcePositionButton, InstallWalkStackButton, KillButtonSet, MainActionProc, MoveToX, MoveToY, NewLine, SkipX, ViewerControl],
CirioTypes USING[CompilerContext],
Commander USING[CommandProc, Register],
CommanderOps USING[ParseToList],
Containers USING[ChildXBound, Create],
Convert USING[CardFromRope, Error, RopeFromAtom, RopeFromCard],
DisassembleSPARC,
FileNames USING[CurrentWorkingDirectory],
IO USING[PutF, PutF1, PutRope, rope, STREAM],
Labels USING [Set],
NetworkName USING[AddressFromName, Error],
Process USING[Detach],
RemoteCirio USING[AbortThread, AddSearchDirectory, CloseConnection, Connection, DbxExamineThread, DestroyRemoteWorld, FindThreadsWithProperty, FlushUnknownFileCache, FocusOnThread, FreezeThread, GetDummyStack, GetStackForCurrentThread, GetThreadTitleText, InstallBreakCheckDaemon, KillThread, ListSearchDirectory, OpenConnection, ProceedThread, ResumeRemoteWorld, ResumeRemoteWorldWithOnlyVP0, ShowQuickSummary, StopBreakCheckDaemon, StopRemoteWorld, ThreadIDFromIndex],
Rope USING[Cat, Concat, Equal, Find, Length, ROPE],
SourceFileOpsExtras USING [FullFormatPosition, FullGetSelection, FullOpenSource, noPosition, Position],
SystemNames USING[MachineName],
StackCirio USING[ClearAllBreakPoints, ClearBreakPoint, Disassemble, FormatPrompt, InterpretTextLine, ListBreakPoints, ResetStack, SetBreakPointAtAddress, SetBreakPointAtPosition, Stack],
Termination USING[CallBeforeQuitWorld],
TiogaOps USING[FindText, FindWord, SearchDir],
WindowSystemInterface USING[GetSelectionContents],
ViewerClasses USING[MouseButton, Viewer],
ViewerOps USING[BlinkViewer, PaintViewer];
RemoteDriver3: CEDAR MONITOR
LOCKS d USING d: MyViewerData
IMPORTS Buttons, CCTypes, CirioButtons, Commander, CommanderOps, Containers, Convert, DisassembleSPARC, FileNames, IO, Labels, NetworkName, Process, RemoteCirio, Rope, SourceFileOpsExtras, StackCirio, SystemNames, Termination, TiogaOps, WindowSystemInterface, ViewerOps
= BEGIN
ROPE: TYPE ~ Rope.ROPE;
CC: TYPE = CirioTypes.CompilerContext;
CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE ¬ NIL] ¬ CCTypes.CCError;
Viewer related code
Stolen from RemoteDriver2.mesa
MyViewerData: TYPE = REF MyViewerDataBody;
MyViewerDataBody: TYPE = MONITORED RECORD[
vc: CirioButtons.ViewerControl ¬ NIL,
connection: RemoteCirio.Connection,
dummyStack: StackCirio.Stack,
serverName: ROPE,
portNum: CARD,
threadsInfo: REF ThreadsInfo,
remoteWorldGone: BOOLEAN ¬ FALSE,
runningFlag: BOOLEAN ¬ TRUE,
runningLabel: ViewerClasses.Viewer,
stopAllFlag: BOOLEAN ¬ FALSE,
stopAllLabel: ViewerClasses.Viewer,
dbxFlag: BOOLEAN ¬ FALSE,
lineH: CARD ¬ 0,
worldControlY: INTEGER ¬ 0,
worldControlH: INTEGER ¬ 0,
worldControlButtonSet: CirioButtons.ButtonSet,
threadControlY: INTEGER ¬ 0,
threadControlH: INTEGER ¬ 0,
threadControlButtonSet: CirioButtons.ButtonSet,
threadListControlButtonsInstalled: BOOL ¬ FALSE,
rule1Y: INTEGER ¬ 0,
threadButtonsY: INTEGER ¬ 0,
threadButtonsH: INTEGER ¬ 0,
threadButtonsButtonSet: CirioButtons.ButtonSet,
activeThread: REF ThreadButtonInfo ¬ NIL,
activeThreadRemoteIndex: CARD,
currentStack: StackCirio.Stack,
rule2Y: INTEGER ¬ 0,
stopFlag: REF BOOLEAN ¬ NIL,
generalButtonsY: INTEGER ¬ 0,
generalButtonsH: INTEGER ¬ 0,
generalButtonsButtonSet: CirioButtons.ButtonSet,
stackButtonsY: INTEGER ¬ 0,
stackButtonsH: INTEGER ¬ 0,
stackButtonsButtonSet: CirioButtons.ButtonSet,
frameLabel: ViewerClasses.Viewer,
rule3Y: INTEGER ¬ 0,
findButtonsY: INTEGER ¬ 0,
findButtonsH: INTEGER ¬ 0,
findButton: ViewerClasses.Viewer,
wordButton: ViewerClasses.Viewer,
findButtonsButtonSet: CirioButtons.ButtonSet,
rule4Y: INTEGER ¬ 0,
scriptY: INTEGER ¬ 0
];
ThreadsInfo: TYPE = RECORD[SEQUENCE nThreads: CARDINAL OF REF ThreadButtonInfo];
ThreadButtonInfo: TYPE = RECORD[d: MyViewerData, index: CARD, visible: BOOLEAN, label: ViewerClasses.Viewer];
toolIDInfo: TYPE ~ RECORD [
valid: BOOL ¬ FALSE,
localPort: CARD ¬ 0,
localName: Rope.ROPE ¬ NIL,
localHostIP: Rope.ROPE ¬ NIL
];
thisTool: toolIDInfo ¬ [];
GetPortNum: PROC RETURNS[CARD] = TRUSTED MACHINE CODE
{"CirioNubLocalGetPort"};
Driver: Commander.CommandProc = {
d: MyViewerData ¬ NEW[MyViewerDataBody];
args: LIST OF ROPE;
numArgs: NAT;
serverName: ROPE;
serverNameIP: ROPE;
portNum: CARDINAL;
wDirs: LIST OF ROPE ¬ NIL;
lastWDir: LIST OF ROPE ¬ NIL;
cDir: LIST OF ROPE ¬ LIST[FileNames.CurrentWorkingDirectory[]];
[args, numArgs] ¬ CommanderOps.ParseToList[cmd];
{ ENABLE {
Convert.Error => {GOTO usage};
NetworkName.Error => {
errRope: Rope.ROPE ¬ NIL;
IO.PutF[cmd.out, "\nProblem(s) occured while looking up host %g (%g", [rope[serverName]], [rope[msg]]];
FOR problems: LIST OF ATOM ¬ codes, problems.rest WHILE problems # NIL DO
errRope ¬ Convert.RopeFromAtom[problems.first, FALSE];
IO.PutF1[cmd.out, ", %g", [rope[errRope]]];
ENDLOOP;
IO.PutRope[cmd.out, ")\nPlease verify the correct <MachineName> and <PortNumber> and try again.\n\n"];
GOTO done;
};
};
IF numArgs<1 THEN GOTO usage;
serverName ¬ args.first;
serverNameIP ¬ NetworkName.AddressFromName[family: $ARPA, name: serverName, portHint: NIL, components: host].addr;
portNum ¬ IF numArgs < 2 THEN 4815 ELSE CARDINAL[Convert.CardFromRope[args.rest.first]];
EXITS
usage => RETURN [$Failure, "Usage: CirioRemote <hostname> [<portnumber> [<listOfWorkingDirectories>]]"];
done => RETURN;
};
Get user supplied and default working directories
wDirs ¬ IF numArgs < 3 THEN NIL ELSE args.rest.rest;
IF wDirs # NIL THEN {
FOR thisDir: LIST OF ROPE ¬ wDirs, thisDir.rest WHILE thisDir # NIL DO
lastWDir ¬ thisDir;
ENDLOOP;
lastWDir.rest ¬ cDir;
}
ELSE {
wDirs ¬ cDir;
};
Try to prevent connecting to ourselves.
{
localhost: Rope.ROPE ¬ "localhost";
Rope returned by SystemNames.MachineName if yp isn't running.
anonMachine: Rope.ROPE ¬ "AnonymousMachine";
IF NOT thisTool.valid THEN {
thisTool.localPort ¬ GetPortNum[];
thisTool.localName ¬ SystemNames.MachineName[];
IF (Rope.Equal[thisTool.localName, anonMachine]) THEN {
thisTool.localName ¬ localhost;
IO.PutRope[cmd.out, "\nSystemNames.MachineName reports AnonymousMachine. Using localhost instead.\n\n"];
};
thisTool.localHostIP ¬ NetworkName.AddressFromName[family: $ARPA, name: thisTool.localName, portHint: NIL, components: host].addr;
thisTool.valid ¬ TRUE;
};
IF (portNum = thisTool.localPort AND (Rope.Equal[thisTool.localHostIP, serverNameIP] OR Rope.Equal[localhost, serverName])) THEN {
IO.PutF[cmd.out, "\nYou are attempting to connect Cirio to itself.\nPlease verify the correct <hostname> and <portnumber> and try again.\n\n"];
RETURN;
};
};
d.lineH ¬ CirioButtons.GetButtonSize["Sample"].h+1;
d.worldControlY ¬ 1;
d.worldControlH ¬ d.lineH;
d.threadControlY ¬ d.worldControlY+d.worldControlH;
d.threadControlH ¬ 2*d.lineH;
d.rule1Y ¬ d.threadControlY+d.threadControlH;
d.threadButtonsY ¬ d.rule1Y+2;
d.threadButtonsH ¬ 6*d.lineH;
d.rule2Y ¬ d.threadButtonsY+d.threadButtonsH+1;
d.generalButtonsY ¬ d.rule2Y+1;
d.generalButtonsH ¬ d.lineH;
d.stackButtonsY ¬ d.generalButtonsY+d.generalButtonsH+1;
d.stackButtonsH ¬ d.lineH;
d.rule3Y ¬ d.stackButtonsY+d.stackButtonsH+1;
d.findButtonsY ¬ d.stackButtonsY + d.generalButtonsH + 1;
d.findButtonsH ¬ d.lineH;
d.rule4Y ¬ d.findButtonsY+d.findButtonsH+1;
d.scriptY ¬ d.rule4Y+1;
d.vc ¬ CirioButtons.CreateViewer[Rope.Cat["Cirio remote ", serverName, " (", Convert.RopeFromCard[portNum], ")"], d.scriptY, FormatPrompt, InterpretTextLine, ShutDown, d];
d.connection ¬ RemoteCirio.OpenConnection[serverName, portNum, wDirs, d.vc.out];
IF d.connection=NIL THEN {
TRUSTED{Process.Detach[FORK CirioButtons.MainActionProc[d.vc]]}; --so delete works
RETURN [$Failure, "Debugging session abandoned because couldn't open connection"]};
open a block to so that unwind catches can close the connection
BEGIN
ENABLE UNWIND => {CleanupConnection[d]};
Termination.CallBeforeQuitWorld[CleanupConnection, d];
RemoteCirio.InstallBreakCheckDaemon[d.connection, d.vc.out];
d.dummyStack ¬ RemoteCirio.GetDummyStack[d.connection, d.vc.out];
d.serverName ¬ serverName;
d.portNum ¬ portNum;
d.stopFlag ¬ NEW[BOOLEAN¬FALSE];
InstallRules[d];
InstallWorldControlButtons[d];
InstallFindButtons[d];
TRUSTED{Process.Detach[FORK CirioButtons.MainActionProc[d.vc]]};
SetThreadControlToRunning[d];
END;
RETURN};
Cleanup before exiting
CleanupConnection: PROC [x: REF] = {
d: MyViewerData ¬ NARROW[x];
IF d # NIL AND d.vc.self # NIL THEN RemoteCirio.CloseConnection[d.connection, d.vc.out];
};
Interpret
FormatPrompt: PROC [counter: INT, clientData: REF ANY] RETURNS [ROPE] ~ {
d: MyViewerData ¬ NARROW[clientData];
stack: StackCirio.Stack ¬ IF d.currentStack # NIL THEN d.currentStack ELSE d.dummyStack;
IF d.connection=NIL THEN RETURN["broken!"];
RETURN StackCirio.FormatPrompt[stack, counter]};
InterpretTextLine: PROC[line: ROPE, reports: IO.STREAM, clientData: REF ANY] RETURNS[ROPE] = {
d: MyViewerData ¬ NARROW[clientData];
stack: StackCirio.Stack ¬ IF d.currentStack # NIL THEN d.currentStack ELSE d.dummyStack;
IF d.connection=NIL THEN RETURN["I'm broken, you fool"];
RETURN[StackCirio.InterpretTextLine[stack, line, reports]];
};
Find
InstallFindButtons: PROC[d: MyViewerData] =
BEGIN
d.findButton ¬ Buttons.Create[info: [wx: 0, wy: d.findButtonsY + 1, ww: 50, wh: d.findButtonsH, name: "Find", parent: d.vc.self, border: FALSE], proc: FindAction, clientData: d.vc.script];
d.wordButton ¬ Buttons.Create[info: [wx: 50, wy: d.findButtonsY + 1, ww: 50, wh: d.findButtonsH, name: "Word", parent: d.vc.self, border: FALSE], proc: WordAction, clientData: d.vc.script];
END;
InstallFindButtons: PROC[d: MyViewerData] =
BEGIN
findButtonSet: CirioButtons.ButtonSet ← d.findButtonsButtonSet ← CirioButtons.CreateButtonSet[d.vc.self, d.vc, 0, d.findButtonsH, 0, d.lineH, 0];
[] ← CirioButtons.InstallCommandButton[bs: findButtonSet, name: "Find", clientData1: d.vc, choices: LIST[[$Forward], [$Anywhere], [$Backward]], proc2: FindAction];
[] ← CirioButtons.InstallCommandButton[bs: findButtonSet, name: "Word", clientData1: d.vc, choices: LIST[[$Forward], [$Anywhere], [$Backward]], proc2: FindAction];
END;
FindAction: Buttons.ButtonProc ~ {
script: ViewerClasses.Viewer ¬ NARROW[clientData];
IF ~TiogaOps.FindText[viewer: script, rope: NIL, whichDir: DirFromClick[mouseButton], which: primary, case: ~shift] THEN
ViewerOps.BlinkViewer[script, 300];
};
WordAction: Buttons.ButtonProc ~ {
script: ViewerClasses.Viewer ¬ NARROW[clientData];
IF ~TiogaOps.FindWord[viewer: script, rope: NIL, whichDir: DirFromClick[mouseButton], which: primary, case: ~shift] THEN
ViewerOps.BlinkViewer[script, 300];
};
FindAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] RETURNS[] ~ {
v: ViewerClasses.Viewer ← NARROW[clientData1];
dirAtom: ATOMNARROW[key];
IF ~TiogaOps.FindText[viewer: v, rope: NIL, whichDir: DirFromAtom[dirAtom], which: primary, case: TRUE] THEN
do something?
v ← NIL;
};
WordAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] ~ {
v: ViewerClasses.Viewer ← NARROW[clientData1];
dirAtom: ATOMNARROW[key];
IF ~TiogaOps.FindWord[viewer: v, rope: NIL, whichDir: DirFromAtom[dirAtom], which: primary, case: TRUE] THEN
do something?
v ← NIL;
};
DirFromAtom: PROC[a: ATOM] RETURNS [dir: TiogaOps.SearchDir ← forwards] ~ {
SELECT a FROM
$Forward => dir ← forwards;
$Backward => dir ← backwards;
$Anywhere => dir ← anywhere;
ENDCASE => ERROR;
};
DirFromClick: PROC[b: ViewerClasses.MouseButton] RETURNS [dir: TiogaOps.SearchDir ¬ forwards] ~ {
SELECT b FROM
red => dir ¬ forwards;
blue => dir ¬ backwards;
yellow => dir ¬ anywhere;
ENDCASE => ERROR;
};
Rules
InstallRules: PROC[d: MyViewerData] =
BEGIN
ruleButtonSet: CirioButtons.ButtonSet ¬ CirioButtons.CreateButtonSet[d.vc.self, d.vc, 0, 0, 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.rule1Y];
CirioButtons.InstallRule[ruleButtonSet];
CirioButtons.MoveToY[ruleButtonSet, d.rule2Y];
CirioButtons.InstallRule[ruleButtonSet];
CirioButtons.MoveToY[ruleButtonSet, d.rule3Y];
CirioButtons.InstallRule[ruleButtonSet];
CirioButtons.MoveToY[ruleButtonSet, d.rule4Y];
CirioButtons.InstallRule[ruleButtonSet];
END;
world control
InstallWorldControlButtons: PROC [d: MyViewerData] =
BEGIN
worldControlViewer: ViewerClasses.Viewer ¬ Containers.Create[
info: [parent: d.vc.self, border: FALSE, scrollable: FALSE, wx: 0, wy: d.worldControlY, ww: d.vc.self.cw, wh: d.worldControlH] ];
bs: CirioButtons.ButtonSet ¬ d.worldControlButtonSet ¬ CirioButtons.CreateButtonSet[worldControlViewer, d.vc, 0, 0, 0, d.lineH, 0];
Containers.ChildXBound[d.vc.self, worldControlViewer];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "Flush unknownFileCache", border: TRUE,
clientData1: d,
proc2: FlushAction];
CirioButtons.SkipX[bs, 5];
d.runningLabel ¬ CirioButtons.InstallLabelButton[bs, "Remote World Running"];
CirioButtons.SkipX[bs, 2];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "KillRemoteWorld", border: TRUE, guarded: TRUE,
clientData1: d,
proc2: KillRemoteWorld];
[] ← CirioButtons.InstallCommandButton[
bs: bs,
name: "ForkWSDaemon", border: TRUE, guarded: FALSE,
clientData1: d,
proc2: BreakCheckDaemonInitialize];
END;
BreakCheckDaemonInitialize: PROC [button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] =
BEGIN
p: PROCESS;
d: MyViewerData ¬ NARROW[clientData1];
RemoteCirio.InstallBreakCheckDaemon[connection: d.connection, reports: d.vc.out];
END;
FlushAction: 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 ..."];
RemoteCirio.FlushUnknownFileCache[d.connection, d.vc.out];
IO.PutRope[d.vc.out, " done flushing.\n"];
END;
KillRemoteWorld: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] =
BEGIN
d: MyViewerData ¬ NARROW[clientData1];
RemoteCirio.StopBreakCheckDaemon[connection: d.connection, reports: d.vc.out];
IO.PutRope[d.vc.out, "Killing remote world ..."];
CloseThreadInner[d];
RemoveThreadButtons[d];
RemoteCirio.DestroyRemoteWorld[d.connection];
d.connection ¬ NIL;
Labels.Set[d.runningLabel, " Remote World Gone"];
d.runningFlag ¬ FALSE;
d.remoteWorldGone ¬ TRUE;
ViewerOps.PaintViewer[d.vc.self, client];
IO.PutRope[d.vc.out, " killed.\n"];
END;
ThreadControl
SetThreadControlToRunning: PROC[d: MyViewerData] =
BEGIN
empty: CirioButtons.ButtonSet ¬ d.threadControlButtonSet ¬ CirioButtons.KillButtonSet[d.threadControlButtonSet, FALSE];
threadControlViewer: ViewerClasses.Viewer ¬ Containers.Create[
info: [parent: d.vc.self, border: FALSE, scrollable: FALSE, wx: 0, wy: d.threadControlY, ww: d.vc.self.cw, wh: d.threadControlH] ];
bs: CirioButtons.ButtonSet ¬ d.threadControlButtonSet ¬ CirioButtons.CreateButtonSet[threadControlViewer, d.vc, 0, 0, 0, d.lineH, 0];
Containers.ChildXBound[d.vc.self, threadControlViewer];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "StopRemoteWorld", border: TRUE,
clientData1: d,
proc2: StopRemoteWorld];
END;
StopRemoteWorld: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] =
BEGIN
d: MyViewerData ¬ NARROW[clientData1];
{
ENABLE CCTypes.CCError => {
IO.PutF1[d.vc.out, " CCTypes.CCError: %g (try again)\n", [rope[msg]]];
GOTO dead;
};
IO.PutRope[d.vc.out, "Stopping remote world execution ..."];
BEGIN
nThreads: CARD ¬ RemoteCirio.StopRemoteWorld[d.connection, d.vc.out];
d.threadsInfo ¬ NEW[ThreadsInfo[nThreads]];
FOR x: CARDINAL IN [0..d.threadsInfo.nThreads) DO
d.threadsInfo[x] ¬ NEW[ThreadButtonInfo¬[d, x, FALSE, NIL]];
ENDLOOP;
Labels.Set[d.runningLabel, "Remote World Stopped"];
d.runningFlag ¬ FALSE;
SetThreadControlToStopped[d];
InstallGeneralButtons[d];
IO.PutRope[d.vc.out, " stopped.\n"];
END;
EXITS dead => {};
};
END;
SetThreadControlToRunningDbx: PROC[d: MyViewerData] =
BEGIN
empty: CirioButtons.ButtonSet ¬ d.threadControlButtonSet ¬ CirioButtons.KillButtonSet[d.threadControlButtonSet, FALSE];
threadControlViewer: ViewerClasses.Viewer ¬ Containers.Create[
info: [parent: d.vc.self, border: FALSE, scrollable: FALSE, wx: 0, wy: d.threadControlY, ww: d.vc.self.cw, wh: d.threadControlH] ];
bs: CirioButtons.ButtonSet ¬ d.threadControlButtonSet ¬ CirioButtons.CreateButtonSet[threadControlViewer, d.vc, 0, 0, 0, d.lineH, 0];
Containers.ChildXBound[d.vc.self, threadControlViewer];
END;
SetThreadControlToStopped: PROC[d: MyViewerData] =
BEGIN
empty: CirioButtons.ButtonSet ¬ d.threadControlButtonSet ¬ CirioButtons.KillButtonSet[d.threadControlButtonSet, FALSE];
threadControlViewer: ViewerClasses.Viewer ¬ Containers.Create[
info: [parent: d.vc.self, border: FALSE, scrollable: FALSE, wx: 0, wy: d.threadControlY, ww: d.vc.self.cw, wh: d.threadControlH] ];
bs: CirioButtons.ButtonSet ¬ d.threadControlButtonSet ¬ CirioButtons.CreateButtonSet[threadControlViewer, d.vc, 0, 0, 0, d.lineH, 0];
Containers.ChildXBound[d.vc.self, threadControlViewer];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "ResumeRemoteWorld", border: TRUE,
clientData1: d,
proc2: ResumeRemoteWorld];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "VP0", border: TRUE,
clientData1: d,
proc2: OneVP];
CirioButtons.NewLine[bs];
[] ¬ CirioButtons.InstallLabelButton[bs, "Add threads: "];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "CallingDebugger", border: TRUE,
clientData1: d,
proc2: AddCallingDebuggerThreads];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "Ready", border: TRUE,
clientData1: d,
proc2: AddReadyThreads];
[] ← CirioButtons.InstallCommandButton[
bs: bs,
name: "for context", border: TRUE,
clientData1: d,
proc1: AddThreadsForContext1,
proc2: AddThreadsForContext2];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "All", border: TRUE,
clientData1: d,
proc2: AddAllThreads];
END;
InstallThreadListButtons: PROC[d: MyViewerData] = {
bs: CirioButtons.ButtonSet ¬ d.threadControlButtonSet;
IF d.threadsInfo = NIL THEN RETURN;
[] ¬ CirioButtons.InstallLabelButton[bs, " Listed threads: "];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "*", border: TRUE,
clientData1: d,
choices: LIST[[$FullSummary], [$ShortSummary], [$FreezeThread], [$ProceedThread], [$AbortThread], [$KillThread]],
proc2: ThreadListButtonProc];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "Sum'ry", border: TRUE,
clientData1: d,
choices: LIST[[$FullSummary], [$ShortSummary]],
proc2: ThreadListButtonProc];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "Frz", border: TRUE,
clientData1: d,
choices: LIST[[$FreezeThread]],
proc2: ThreadListButtonProc];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "Prcd", border: TRUE,
clientData1: d,
choices: LIST[[$ProceedThread]],
proc2: ThreadListButtonProc];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "Abrt", border: TRUE,
clientData1: d,
choices: LIST[[$AbortThread]],
proc2: ThreadListButtonProc];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "Kill", border: TRUE,
clientData1: d,
choices: LIST[[$KillThread]],
proc2: ThreadListButtonProc];
d.threadListControlButtonsInstalled ¬ TRUE;
};
ResumeRemoteWorld: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = {
d: MyViewerData ¬ NARROW[clientData1];
{
ENABLE CCTypes.CCError => {
IO.PutF1[d.vc.out, " CCTypes.CCError: %g (probably worked)\n", [rope[msg]]];
GOTO dead;
};
IF NOT d.runningFlag THEN {
IO.PutRope[d.vc.out, "Resuming remote world execution ..."];
CloseThreadInner[d];
RemoveGeneralButtons[d];
RemoveThreadButtons[d];
SetThreadControlToRunning[d];
RemoteCirio.ResumeRemoteWorld[d.connection];
d.threadsInfo ¬ NIL;
Labels.Set[d.runningLabel, "Remote World Running"];
d.runningFlag ¬ TRUE;
ViewerOps.PaintViewer[d.vc.self, client];
IO.PutRope[d.vc.out, " resumed.\n"];
};
EXITS dead => {};
};
};
OneVP: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = {
d: MyViewerData ¬ NARROW[clientData1];
{
ENABLE CCTypes.CCError => {
IO.PutF1[d.vc.out, " CCTypes.CCError: %g (probably worked)\n", [rope[msg]]];
GOTO dead;
};
IF NOT d.runningFlag THEN {
IO.PutRope[d.vc.out, "Resuming remote world execution with only VP0 ..."];
CloseThreadInner[d];
RemoveGeneralButtons[d];
RemoveThreadButtons[d];
SetThreadControlToRunning[d];
RemoteCirio.ResumeRemoteWorldWithOnlyVP0[d.connection];
d.threadsInfo ¬ NIL;
Labels.Set[d.runningLabel, "Remote World Running (VP0)"];
d.runningFlag ¬ TRUE;
ViewerOps.PaintViewer[d.vc.self, client];
IO.PutRope[d.vc.out, " resumed with only VP0.\n"];
};
EXITS dead => {};
};
};
AddCallingDebuggerThreads: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] =
BEGIN
d: MyViewerData ¬ NARROW[clientData1];
IF NOT d.runningFlag THEN
BEGIN
IO.PutRope[d.vc.out, "Adding threads calling debugger ..."];
BEGIN
someThreads: LIST OF CARD ¬ RemoteCirio.FindThreadsWithProperty[d.connection, [callingDebugger[]], d.vc.out];
RedoThreadButtons[d, someThreads];
IO.PutRope[d.vc.out, " added.\n"];
InstallThreadListButtons[d];
END;
END;
END;
AddReadyThreads: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] =
BEGIN
d: MyViewerData ¬ NARROW[clientData1];
IF NOT d.runningFlag THEN
BEGIN
IO.PutRope[d.vc.out, "Adding ready threads (including running) ..."];
BEGIN
someThreads: LIST OF CARD ¬ RemoteCirio.FindThreadsWithProperty[d.connection, [ready[]], d.vc.out];
RedoThreadButtons[d, someThreads];
IO.PutRope[d.vc.out, " added.\n"];
InstallThreadListButtons[d];
END;
END;
END;
AddThreadsForContext1: 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;
AddThreadsForContext2: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] =
BEGIN
d: MyViewerData ¬ NARROW[clientData1];
IF NOT d.runningFlag THEN
BEGIN
ropeHolder: REF RopeHolder ¬ NARROW[clientData2];
contextName: ROPE ¬ IF ropeHolder = NIL THEN NIL ELSE ropeHolder­;
IF Rope.Length[contextName] = 0 OR Rope.Find[contextName, "."] >= 0 OR Rope.Find[contextName, "/"] >= 0 THEN
IO.PutF1[d.vc.out, "sorry, selection \"%g\" is not a valid context name\N", IO.rope[contextName]]
ELSE
BEGIN
IO.PutF1[d.vc.out, "Adding threads for context %g ...", IO.rope[contextName]];
BEGIN
someThreads: LIST OF CARD ¬ RemoteCirio.FindThreadsWithProperty[d.connection, [context[contextName]], d.vc.out];
RedoThreadButtons[d, someThreads];
IO.PutRope[d.vc.out, " added.\n"];
END;
END;
END;
END;
AddAllThreads: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] =
BEGIN
d: MyViewerData ¬ NARROW[clientData1];
IF NOT d.runningFlag THEN {
IO.PutRope[d.vc.out, "Adding all threads ..."];
{someThreads: LIST OF CARD ¬ RemoteCirio.FindThreadsWithProperty[d.connection, [any[]], d.vc.out];
RedoThreadButtons[d, someThreads];
};
IO.PutRope[d.vc.out, " added.\n"];
InstallThreadListButtons[d];
};
END;
Thread Buttons
RemoveThreadButtons: PROC[d: MyViewerData] =
BEGIN
d.threadButtonsButtonSet ¬ CirioButtons.KillButtonSet[d.threadButtonsButtonSet, FALSE];
END;
RedoThreadButtons: PROC[d: MyViewerData, someThreads: LIST OF CARD] =
BEGIN
nNewButtons: CARD ¬ 0;
empty: CirioButtons.ButtonSet ¬ d.threadButtonsButtonSet ¬ CirioButtons.KillButtonSet[d.threadButtonsButtonSet, FALSE];
threadButtonsViewer: ViewerClasses.Viewer ¬ Containers.Create[
info: [parent: d.vc.self, border: FALSE, scrollable: TRUE, wx: 0, wy: d.threadButtonsY, ww: d.vc.self.cw, wh: d.threadButtonsH] ];
sample1: CirioButtons.ButtonSize ¬ CirioButtons.GetButtonSize["9999: (10) (Handlee) (frozen) (BadProceedRequest)"];
bs: CirioButtons.ButtonSet ¬ d.threadButtonsButtonSet ¬ CirioButtons.CreateButtonSet[threadButtonsViewer, d.vc, 0, 0, 0, d.lineH-2, 0];
Containers.ChildXBound[d.vc.self, threadButtonsViewer];
FOR st: LIST OF CARD ¬ someThreads, st.rest WHILE st # NIL DO
IF NOT d.threadsInfo[st.first].visible THEN nNewButtons ¬ nNewButtons + 1;
d.threadsInfo[st.first].visible ¬ TRUE;
ENDLOOP;
FOR x: CARDINAL IN [0..d.threadsInfo.nThreads) DO
IF d.threadsInfo[x].visible THEN
BEGIN
title: ROPE ¬ RemoteCirio.GetThreadTitleText[d.connection, x];
tbi: REF ThreadButtonInfo ¬ d.threadsInfo[x];
Button: PROC[name: ROPE, proc: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY], choices: CirioButtons.ChoiceList] =
BEGIN
[] ¬ CirioButtons.InstallCommandButton[bs: bs, name: name, border: TRUE, clientData1: tbi, choices: choices, proc2: proc]
END;
tbi.label ¬ CirioButtons.InstallLabelButton[bs, title];
CirioButtons.MoveToX[bs, sample1.w];
Button["*", ThreadButtProc, LIST[[$FullSummary], [$ShortSummary], [$ThreadDetails], [$FreezeThread], [$ProceedThread], [$AbortThread], [$KillThread], [$CallDbx]] ];
Button["Sum'ry", ThreadButtProc, LIST[[$FullSummary], [$ShortSummary]] ];
Button["Detailed", ThreadButtProc, LIST[[$ThreadDetails]] ];
Button["Frz", ThreadButtProc, LIST[[$FreezeThread]] ];
Button["Prcd", ThreadButtProc, LIST[[$ProceedThread]] ];
Button["Abrt", ThreadButtProc, LIST[[$AbortThread]] ];
Button["Kill", ThreadButtProc, LIST[[$KillThread]] ];
Button["Dbx", ThreadButtProc, LIST[[$CallDbx]] ];
Containers.ChildXBound[threadButtonsViewer, tbi.label];
CirioButtons.NewLine[bs];
END;
ENDLOOP;
END;
ThreadButtProc: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] =
BEGIN
tbi: REF ThreadButtonInfo ¬ NARROW[clientData1];
d: MyViewerData ¬ tbi.d;
SELECT key FROM
$FullSummary, $ShortSummary => {
tbi.d.stopFlag­ ¬ FALSE;
RemoteCirio.ShowQuickSummary[tbi.d.connection, tbi.index, tbi.d.stopFlag, tbi.d.vc.out, key=$FullSummary];
};
$ThreadDetails => {
IF NOT d.remoteWorldGone THEN SwitchToThread[d, tbi];
};
$FreezeThread => {
newTitleText: ROPE;
IO.PutF1[tbi.d.vc.out, "Freeze %g.\n", [cardinal[RemoteCirio.ThreadIDFromIndex[tbi.index, tbi.d.connection]]]];
newTitleText ¬ RemoteCirio.FreezeThread[tbi.d.connection, tbi.index, tbi.d.vc.out];
Labels.Set[tbi.label, newTitleText];
};
$ProceedThread => {
newTitleText: ROPE;
IO.PutF1[tbi.d.vc.out, "Proceed %g.\n", [cardinal[RemoteCirio.ThreadIDFromIndex[tbi.index, tbi.d.connection]]]];
newTitleText ¬ RemoteCirio.ProceedThread[tbi.d.connection, tbi.index, tbi.d.vc.out];
Labels.Set[tbi.label, newTitleText];
};
$AbortThread => {
newTitleText: ROPE;
IO.PutF1[tbi.d.vc.out, "Abort %g.\n", [cardinal[RemoteCirio.ThreadIDFromIndex[tbi.index, tbi.d.connection]]]];
newTitleText ¬ RemoteCirio.AbortThread[tbi.d.connection, tbi.index, tbi.d.vc.out];
Labels.Set[tbi.label, newTitleText];
};
$KillThread => {
newTitleText: ROPE;
IO.PutF1[tbi.d.vc.out, "Kill %g.\n", [cardinal[RemoteCirio.ThreadIDFromIndex[tbi.index, tbi.d.connection]]]];
newTitleText ¬ RemoteCirio.KillThread[tbi.d.connection, tbi.index, tbi.d.vc.out];
Labels.Set[tbi.label, newTitleText];
};
$CallDbx => IF NOT d.remoteWorldGone AND NOT d.runningFlag THEN
BEGIN
newNThreads: CARD;
first we have to do more or less what we would do if we were restarting the remote world
IO.PutRope[d.vc.out, "Calling DBX.\n"];
CloseThreadInner[d];
RemoveThreadButtons[d];
SetThreadControlToRunningDbx[d]; -- this is different
d.threadsInfo ¬ NIL;
Labels.Set[d.runningLabel, " Remote World in Dbx"];
d.dbxFlag ¬ TRUE;
IO.PutRope[d.vc.out, " (remote world under Dbx)\n"];
now we do it
newNThreads ¬ RemoteCirio.DbxExamineThread[tbi.d.connection, tbi.index, tbi.d.vc.out];
now we put the world back. Unfortunately, we don't reconstruct the thread info (we shall code that later).
d.threadsInfo ¬ NEW[ThreadsInfo[newNThreads]];
FOR x: CARDINAL IN [0..d.threadsInfo.nThreads) DO
d.threadsInfo[x] ¬ NEW[ThreadButtonInfo¬[d, x, FALSE, NIL]];
ENDLOOP;
Labels.Set[d.runningLabel, " Remote World Stopped"];
d.runningFlag ¬ FALSE;
SetThreadControlToStopped[d];
RedoThreadButtons[d, NIL];
IO.PutRope[d.vc.out, " (Dbx activity stopped)\n"]
END;
ENDCASE => IO.PutRope[d.vc.out, "\n!Unrecognized action (this can't happen)!\n"];
END;
ThreadListButtonProc: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = {
d: MyViewerData ¬ NARROW[clientData1];
IF d.threadsInfo #NIL THEN
FOR threadIndex: CARDINAL IN [0..d.threadsInfo.nThreads) DO
IF d.threadsInfo[threadIndex].visible THEN
ThreadButtProc[button, vc, key, d.threadsInfo[threadIndex], clientData2];
ENDLOOP;
};
GeneralButtons
InstallGeneralButtons: PROC[d: MyViewerData] =
BEGIN
generalButtonsViewer: ViewerClasses.Viewer ¬ Containers.Create[
info: [parent: d.vc.self, border: FALSE, scrollable: FALSE, wx: 0, wy: d.generalButtonsY, ww: d.vc.self.cw, wh: d.generalButtonsH] ];
bs: CirioButtons.ButtonSet ¬ d.generalButtonsButtonSet ¬ CirioButtons.CreateButtonSet[generalButtonsViewer, d.vc, 0, 0, 0, d.lineH, 0];
Containers.ChildXBound[d.vc.self, generalButtonsViewer];
[] ¬ 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: ListDirAction2];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "Stop",
clientData1: d,
proc1: StopAction1,
proc2: StopAction2];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "Disassemble",
clientData1: d,
proc1: DisassembleAction1,
proc2: DisassembleAction2];
[] ¬ CirioButtons.InstallCommandButton[
bs: bs,
name: "BreakMode", border: TRUE,
clientData1: d,
proc2: BreakModeAction];
d.stopAllLabel ¬ CirioButtons.InstallLabelButton[bs, "StopAThread "];
END;
SetBreakAction1: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1: REF ANY] RETURNS [clientData2: REF ANY] ~ {
SELECT key FROM
$SetBreakAtPosition => {
pos: SourceFileOpsExtras.Position ~ SourceFileOpsExtras.FullGetSelection[].pos;
RETURN [NEW[SourceFileOpsExtras.Position ¬ pos]]};
$SetBreakAtAddr => {
addrope: ROPE ~ WindowSystemInterface.GetSelectionContents[];
RETURN[addrope]};
ENDCASE => ERROR};
SetBreakAction2: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = {
d: MyViewerData ~ NARROW[clientData1];
SELECT key FROM
$SetBreakAtPosition => {
pos: REF SourceFileOpsExtras.Position ~ NARROW[clientData2];
corresp: SourceFileOpsExtras.Position ¬ pos­;
IO.PutF1[d.vc.out, "Setting break at %g ... ", [rope[SourceFileOpsExtras.FullFormatPosition[pos­]]] ];
corresp ¬ StackCirio.SetBreakPointAtPosition[d.dummyStack, pos­, d.vc.out, d.stopAllFlag];
IF corresp#SourceFileOpsExtras.noPosition THEN
SourceFileOpsExtras.FullOpenSource["Break set at ", corresp, d.vc.out];
};
$SetBreakAtAddr => {
addrope: ROPE ~ NARROW[clientData2];
addr: CARD;
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]] ];
StackCirio.SetBreakPointAtAddress[d.dummyStack, addr, d.vc.out, d.stopAllFlag];
EXITS Bail => NULL};
ENDCASE => ERROR;
IO.PutRope[d.vc.out, " done.\n"];
};
ListBreaksAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] =
BEGIN
d: MyViewerData ¬ NARROW[clientData1];
IO.PutRope[d.vc.out, "Listing breaks ... "];
StackCirio.ListBreakPoints[d.dummyStack, d.vc.out];
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
IO.PutRope[d.vc.out, "Clearing all breaks ... "];
StackCirio.ClearAllBreakPoints[d.dummyStack, d.vc.out];
END
ELSE IF d.currentStack # NIL THEN
BEGIN
IO.PutRope[d.vc.out, "Clearing break ... "];
StackCirio.ClearBreakPoint[d.currentStack, d.vc.out];
END
ELSE IO.PutRope[d.vc.out, "can not clear break without a current frame ... "];
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;
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 ... "];
RemoteCirio.AddSearchDirectory[d.connection, dirPath, d.vc.out];
IO.PutRope[d.vc.out, "Added.\n"];
END;
ListDirAction2: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] =
BEGIN
d: MyViewerData ¬ NARROW[clientData1];
IO.PutRope[d.vc.out, "Listing search directory(s) ... "];
RemoteCirio.ListSearchDirectory[d.connection, d.vc.out];
IO.PutRope[d.vc.out, "Done.\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;
DisassembleAction1: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1: REF ANY] RETURNS[clientData2: REF ANY] = {
addrope: ROPE ~ WindowSystemInterface.GetSelectionContents[];
RETURN[addrope];
};
DisassembleAction2: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = {
d: MyViewerData ~ NARROW[clientData1];
addrRope: ROPE ~ NARROW[clientData2];
IO.PutRope[d.vc.out, "Disassemble ... "];
d.stopFlag­ ¬ FALSE;
StackCirio.Disassemble[d.dummyStack, addrRope, d.vc.out, d.stopFlag];
IO.PutRope[d.vc.out, "done.\n"];
};
BreakModeAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] =
BEGIN
d: MyViewerData ~ NARROW[clientData1];
d.stopAllFlag ¬ ~ d.stopAllFlag;
IF d.stopAllFlag THEN
{Labels.Set[d.stopAllLabel, "StopAllThreads"];}
ELSE
{Labels.Set[d.stopAllLabel, "StopAThread "];};
END;
RemoveGeneralButtons: PROC[d: MyViewerData] =
BEGIN
d.generalButtonsButtonSet ¬ CirioButtons.KillButtonSet[d.generalButtonsButtonSet, FALSE];
END;
Stack debug buttons
SwitchToThread: PROC[d: MyViewerData, tbi: REF ThreadButtonInfo] =
BEGIN
IO.PutRope[d.vc.out, "switching threads ... "];
RemoveStackDebugButtons[d];
d.activeThread ¬ tbi;
d.activeThreadRemoteIndex ¬ RemoteCirio.FocusOnThread[tbi.d.connection, tbi.index, tbi.d.vc.out];
d.currentStack ¬ RemoteCirio.GetStackForCurrentThread[tbi.d.connection, tbi.d.vc.out];
InstallStackDebugButtons[d];
IO.PutRope[d.vc.out, "switched\N"];
END;
InstallStackDebugButtons: PROC[d: MyViewerData] =
BEGIN
stackDebugButtonsViewer: 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.stackButtonsH] ];
bs: CirioButtons.ButtonSet ¬ d.stackButtonsButtonSet ¬ CirioButtons.CreateButtonSet[stackDebugButtonsViewer, d.vc, 0, 0, 0, d.lineH, 0];
tbi: REF ThreadButtonInfo ¬ d.activeThread;
frameIndex: CARD ¬ StackCirio.ResetStack[d.currentStack, tbi.d.vc.out];
threadText: ROPE ¬ Rope.Concat[Convert.RopeFromCard[d.activeThreadRemoteIndex], "."];
Containers.ChildXBound[d.vc.self, stackDebugButtonsViewer];
d.frameLabel ¬ CirioButtons.InstallLabelButton[bs, Rope.Cat["frame: ", threadText, Convert.RopeFromCard[frameIndex], " "]];
CirioButtons.InstallWalkStackButton[bs, d.currentStack, threadText, d.frameLabel];
CirioButtons.InstallShowFrameButton[bs, d.currentStack];
CirioButtons.InstallSourcePositionButton[bs, d.currentStack];
CirioButtons.InstallSourceLanguageButton[bs, d.currentStack];
END;
RemoveStackDebugButtons: PROC[d: MyViewerData] =
BEGIN
d.stackButtonsButtonSet ¬ CirioButtons.KillButtonSet[d.stackButtonsButtonSet, FALSE];
d.frameLabel ¬ NIL;
END;
CloseThreadInner: PROC[d: MyViewerData] =
{RemoveStackDebugButtons[d]; d.currentStack ¬ NIL};
misc
ShutDown: PROC[clientData: REF ANY, reports: IO.STREAM] =
BEGIN
d: MyViewerData ¬ NARROW[clientData];
IF d.connection # NIL THEN RemoteCirio.CloseConnection[d.connection, reports];
d.connection ¬ NIL;
END;
Main code
Commander.Register["CirioRemote", Driver, "Connect to a world.\n Usage: CirioRemote <hostname> [<portnumber> [<listOfWorkingDirectories>]]"];
END..