CommandLineCirioImpl.mesa
Copyright Ó 1989, 1990, 1991, 1992, 1993 by Xerox Corporation. All rights reserved.
Philip James, March 16, 1992 1:21 pm PST
Spreitze, December 12, 1991 3:41 pm PST
Laurie Horton, September 21, 1992 5:09 pm PDT
Udagawa, February 13, 1991 7:58 pm PST
Willie-s, March 2, 1993 4:03 pm PST
Katsuyuki Komatsu January 23, 1993 4:30 pm PST
DIRECTORY
CCTypes USING [CCError],
Commander USING [CommandProc, Handle, Register],
CommanderBackdoor USING [CommandToolData, GetCommandToolData],
CommanderOps USING [DoCommand, NextArgument, NumArgs],
CommandLineCirio,
Convert USING [CardFromRope, IntFromRope, Error, RopeFromAtom, RopeFromCard],
DisassembleSPARC,
IO USING [card, GetLineRope, int, PutF, PutF1, PutFLR, PutFR, PutFR1, PutRope, rope, STREAM],
LocalCirio USING [AddSearchDirectory, ClearSearchDirectory, Connection, DoUnderMonitorLock, FlushUnknownFileCache, GetConnection, GetDummyStack, GetStackForSelf, ListSearchDirectory, ReleaseConnection, RemoveSearchDirectory],
NetworkName USING [AddressFromName, Error],
PFS USING [Error, FileInfo, GetWDir, PATH, PathFromRope, RopeFromPath],
RemoteCirio USING [AbortThread, AddSearchDirectory, ClearSearchDirectory, CloseConnection, Connection, DbxExamineThread, DestroyRemoteWorld, FindThreadsWithProperty, FlushUnknownFileCache, FocusOnThread, FreezeThread, GetDummyStack, GetStackForCurrentThread, GetThreadTitleText, InstallBreakCheckDaemon, KillThread, ListSearchDirectory, OpenConnection, ProceedThread, RemoveSearchDirectory, ResumeRemoteWorld, ResumeRemoteWorldWithOnlyVP0, ShowQuickSummary, StopBreakCheckDaemon, StopRemoteWorld, ThreadIDFromIndex, ThreadIndexFromID, ThreadProperty],
Rope USING [Cat, Concat, Equal, Fetch, IsEmpty, Length, ROPE, Substr],
SourceFileOps USING [noPosition, nullUniqueID, Position, UniqueID],
StackCirio USING [ClearAllBreakPoints, ClearBreakPoint, ClearIthBreakPoint, ClearBreakPointAtPosition, Disassemble, FormatPrompt, GetCurrentFrameBanner, InterpretTextLine, Language, ListBreakPoints, ReportDesiredLanguage, ResetStack, SetBreakPointAtAddress, SetBreakPointAtPosition, SetDesiredLanguage, ShowCurrentFrame, ShowSourcePosition, Stack, WalkStack, WalkStackCedarFrames],
SystemNames USING[MachineName],
Termination USING[CallBeforeQuitWorld];
CommandLineCirioImpl: CEDAR MONITOR
IMPORTS CCTypes, Commander, CommanderBackdoor, CommanderOps, Convert, DisassembleSPARC, IO, LocalCirio, NetworkName, PFS, RemoteCirio, Rope, StackCirio, SystemNames, Termination
EXPORTS CommandLineCirio ~ {
oldPrompt: PROC[cmd: Commander.Handle] ¬ NIL;
connectionType: {Local, Remote, Nil} ¬ Nil;
ch: PUBLIC Commander.Handle ¬ NIL;
currentConnection: RemoteCirio.Connection ¬ NIL;
remoteWorldRunning: BOOL ¬ FALSE;
remoteHost: Rope.ROPE ¬ NIL;
globalPrompt: Rope.ROPE ¬ "CommandLineCirio% ";
currentThread, oldCurrentThread: INTEGER ¬ -1;
commandNum: INT ¬ 1;
vpZeroFlag: BOOL ¬ FALSE;
currentThreads: LIST OF CARD;
inCommLineCirio: BOOL ¬ FALSE;
currentStack: StackCirio.Stack ¬ NIL;
currentDummyStack: StackCirio.Stack ¬ NIL;
currentFrame: CARD ¬ 0;
focused: BOOL ¬ FALSE;
currentLanguage: StackCirio.Language ¬ Cedar;
lastDetailed: CARD ¬ 0;
stopAllFlag: BOOLEAN ¬ FALSE;
currentLevel: CARD ¬ 0;
currentLocalConnection: LocalCirio.Connection;
localhost: Rope.ROPE ¬ "localhost";
Rope returned by SystemNames.MachineName if yp isn't running.
anonMachine: Rope.ROPE ¬ "AnonymousMachine";
toolIDInfo: TYPE ~ RECORD [
valid: BOOL ¬ FALSE,
localPort: CARD ¬ 0,
localName: Rope.ROPE ¬ NIL,
localHostIP: Rope.ROPE ¬ NIL,
safetyNetPort: CARD ¬ 0,
safetyNetStarted: BOOL ¬ FALSE
];
thisTool: toolIDInfo ¬ [];
CLCStarted: CARD ~ 0;
CLCConnected: CARD ~ 1;
CLCStopped: CARD ~ 2;
CLCThreadsAdded: CARD ~ 3;
CLCDetailed: CARD ~ 4;
ConnectionLevel: TYPE ~ [CLCStarted..CLCDetailed];
addThreadsDoc: Rope.ROPE = "AddThreads ThreadOption\n where ThreadOption is one of:\n CallingDebugger\n Ready\n All\n";
Connected: PROC [cmd: Commander.Handle] RETURNS [connected: BOOL] ~ {
IF currentConnection # NIL THEN
RETURN[TRUE]
ELSE {
IO.PutRope[cmd.out, "Not connected to remote world.\n"];
RETURN[FALSE];
}
};
Stopped: PROC [cmd: Commander.Handle] RETURNS [stopped: BOOL] ~ {
IF NOT remoteWorldRunning THEN
RETURN[TRUE]
ELSE {
IO.PutRope[cmd.out, "Remote world must be stopped to perform that operation.\n"];
RETURN[FALSE];
}
};
CommandLinePrompt: PROC [cmd: Commander.Handle] ~ {
IO.PutRope[cmd.err, globalPrompt];
};
SetPromptToName: PROC ~ {
running: Rope.ROPE ¬ NIL;
threadRope, frameRope: Rope.ROPE ¬ NIL;
threadFrameLang: Rope.ROPE ¬ NIL;
IF currentConnection # NIL THEN {
IF remoteWorldRunning THEN
IF vpZeroFlag THEN
running ¬ "running VP0"
ELSE
running ¬ "running"
ELSE
running ¬ "stopped";
IF focused = TRUE THEN {
threadRope ¬ Convert.RopeFromCard[lastDetailed];
frameRope ¬ Convert.RopeFromCard[currentFrame];
threadFrameLang ¬ threadFrameLang.Concat["("].Concat[threadRope].Concat["."].Concat[frameRope].Concat[") ("];
SELECT currentLanguage FROM
C => threadFrameLang ¬ threadFrameLang.Concat["C"];
Cedar => threadFrameLang ¬ threadFrameLang.Concat["Cedar"];
ENDCASE => threadFrameLang ¬ threadFrameLang.Concat["Unknown Language"];
threadFrameLang ¬ threadFrameLang.Concat[") "];
};
globalPrompt := Rope.Concat[
Rope.Concat[
Rope.Concat[remoteHost, " ("],
Rope.Concat[running, ") "]],
Rope.Concat[threadFrameLang, "% "]];
}
ELSE IF currentLocalConnection # NIL THEN
globalPrompt ¬ "LocalWorld% "
ELSE
globalPrompt ¬ "CommandLineCirio% ";
};
CheckLevel: PROCEDURE [validLevels: LIST OF ConnectionLevel, reports: IO.STREAM ¬ NIL] RETURNS [BOOLEAN ¬ FALSE] ~ {
current: ConnectionLevel ¬ currentLevel;
badLevel: BOOL ¬ TRUE;
lowestValid: CARD ¬ LAST[CARD];
highestValid: CARD ¬ 0;
FOR vl: LIST OF ConnectionLevel ¬ validLevels, vl.rest WHILE vl # NIL DO
highestValid ¬ MAX[highestValid, vl.first];
lowestValid ¬ MIN[lowestValid, vl.first];
IF currentLevel = vl.first THEN
badLevel ¬ FALSE;
ENDLOOP;
IF badLevel THEN {
IF reports # NIL THEN
IF current < lowestValid THEN
WHILE current < lowestValid DO
current ¬ current + 1;
SELECT current FROM
1 => IO.PutRope[reports, "You must CirioConnect to a world.\n"];
2 => IO.PutRope[reports, "You must StopRemoteWorld.\n"];
3 => IO.PutRope[reports, "You must AddThreads.\n"];
4 => IO.PutRope[reports, "You must Detail a thread.\n"];
ENDCASE => {};
ENDLOOP
ELSE
SELECT highestValid FROM
0 => IO.PutRope[reports, "You must not be connected to a world to do this.\n"];
1 => IO.PutRope[reports, "You must not have a running remote world to do this.\n"];
2 => IO.PutRope[reports, "You must not have and threads added to do this.\n"];
3 => IO.PutRope[reports, "You must not be detailed to do this.\n"];
ENDCASE => {};
RETURN[TRUE]
};
};
StartComLineProc: Commander.CommandProc ~ {
cmdData: CommanderBackdoor.CommandToolData ¬ NIL;
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.safetyNetPort ¬ thisTool.localPort + 10000;
thisTool.safetyNetStarted ¬ FALSE;
thisTool.valid ¬ TRUE;
SafetyNetHelpRope ¬ IO.PutFLR["\n\tA NetCommander was started on port %g (unless errors occurred).\n\tIt may be used to establish another user interface connection to\n\tthis Cirio tool. This is handy if you lose this shell accidently.\n\tTo reconnect, type the following command in another shell:\n\n\t\ttelnet %g %g\n\tOR\ttelnet %g %g\n\n", LIST[IO.card[thisTool.safetyNetPort], IO.rope[thisTool.localName], IO.card[thisTool.safetyNetPort], IO.rope[thisTool.localHostIP], IO.card[thisTool.safetyNetPort]] ];
SafetyNetHelpRope2 ¬ IO.PutFR1["\n\t The NetCommander on port %g is now unavailable.\n\n", IO.card[thisTool.safetyNetPort]];
};
[] ¬ SafetyNet[cmd, "On"];
IF inCommLineCirio # TRUE THEN {
cmdData ¬ CommanderBackdoor.GetCommandToolData[cmd];
ch ¬ cmd;
oldPrompt ¬ cmdData.Prompt;
cmdData.Prompt ¬ CommandLinePrompt;
inCommLineCirio ¬ TRUE;
IO.PutRope[cmd.out, "CirioHelp [ all | safetynet ] for command list.\n"];
currentLevel ¬ CLCStarted;
Commander.Register["StartCommandLineCirio", NIL];
Commander.Register["CirioHelp", CirioHelpProc, "List all CommandLineCirio commands.\n"];
Commander.Register["WatchFiles", WatchFilesProc, "Add file patterns to the default VersionMap."];
Commander.Register["QuitCommandLineCirio", QuitComLineProc, "Exit the command line cirio package."];
Commander.Register["Quit", QuitDummyProc, "keeps 'q' from triggering QuitCommandLineCirio."];
Commander.Register["CirioConnectToWorld", WorldConnectProc, "Connect to a world.\n Usage: CirioConnectToWorld MachineName [PortNumber [ListOfWorkingDirectories]]"];
Commander.Register["CirioDisconnectFromWorld", WorldDisconnectProc, "Disconnect from the world currently connected to."];
Commander.Register["FlushUnknownFileCache", FlushUFCProc, "Flush the unknown file cache for the world connected to."];
Commander.Register["StopRemoteWorld", StopRemoteWorldProc, "Stop remote world execution."];
Commander.Register["KillRemoteWorld", KillWorldProc, "Kill the remote world."];
Commander.Register["ResumeRemoteWorld", ResumeRemoteWorldProc, "Resume remote world execution."];
Commander.Register["ResumeVP0", ResumeRemoteWorldVP0Proc, "Resume remote world execution with one virtual processor."];
Commander.Register["AddThreads", AddThreadsProc, addThreadsDoc, "Add threads of the remote world to the working set.\n Usage: AddThreads [All | Ready | CallingDebugger]"];
Commander.Register["SetCurrentThread", SetCurrentThreadProc, "Set the current working thread."];
Commander.Register["PrintCurrentThread", PrintCurrentThreadProc, "Print the current working thread."];
Commander.Register["AddDir", AddDirProc, "Add a search directory for the remote world.\n Usage: AddDir DirectoryName"];
Commander.Register["ListDir", ListDirProc, "List the search directories for the remote world."];
Commander.Register["RemoveDir", RemoveDirProc, "Remove the search directory for the remote world."];
Commander.Register["ClearDirs", ClearDirsProc, "Remove all search directories for the remote world."];
Commander.Register["SetBreak", SetBreakProc, "Set a break in the remote world.\n Usage: SetBreak FullPathOfSourceFile CharacterPositionInFile"];
Commander.Register["BreakAtAddress", SetBreakAtAddressProc, "Set a break at address in the remote world.\n Usage: BreakAtAddress Address"];
Commander.Register["ListBreaks", ListBreakProc, "List breaks set in remote world."];
Commander.Register["ClearBreak", ClearBreakProc, "Clear break(s) set in remote world.\n Usage: ClearBreak [# | All | FullPathOfSourceFile CharacterPositionInSourceFile]"];
Commander.Register["ToggleBreakStopAll", ToggleBreakStopAllProc, "Toggle stopAll mode for breaks in remote world.\n Usage: ToggleBreakStopAll"];
Commander.Register["CirioDo", CirioDoProc, "Enter Cirio interpreter (Exit or Quit to exit it)"];
Commander.Register["RemoteDisassemble", RemoteDisassembleProc, "Disassemble from memory in remote world\n Usage: RemoteDisassemble [CProcName | PC]"];
Commander.Register["Summary", SummaryProc, "Give a quick summary for a thread.\n Usage: Summary [ThreadID | listed]"];
Commander.Register["ListAvailableThreads", ListThreadsProc, "List available threads."];
Commander.Register["Freeze", FreezeThreadProc, "Freeze [ThreadID | listed]"];
Commander.Register["Abort", AbortThreadProc, "Abort [ThreadID | listed]"];
Commander.Register["Kill", KillThreadProc, "Kill [ThreadID | listed]"];
Commander.Register["Proceed", ProceedThreadProc, "Proceed [ThreadID | listed]"];
Commander.Register["DbxExamine", DbxExamineThreadProc, "DbxExamine [ThreadID]"];
Commander.Register["Detailed", DetailedProc, "Detailed [ThreadID]"];
Commander.Register["ShowSourcePosition", ShowSourceProc, "Reports the current source position."];
Commander.Register["ShowFrame", ShowFrameProc, "Shows the current frame in the world."];
Commander.Register["WalkStack", WalkStackProc, "Walks through the stack of the world.\n Usage: WalkStack [[Cooler | Warmer [NumberOfFrames]] | AbsoluteFrameNumber][C | Cedar]"];
Commander.Register["Language", LanguageProc, "Change or Query the current debugging language.\n Usage: Language [Cedar | Machine | C]"];
};
};
WatchFilesProc: Commander.CommandProc ~ {
numArgs: CARD ¬ CommanderOps.NumArgs[cmd];
cmdLine: Rope.ROPE ¬ NIL;
watchCmd: Rope.ROPE ¬ "WatchPatternVersions \"\"";
listWatchCmd: Rope.ROPE ¬ "ListPatternVersionsWatches \"\"";
IF numArgs = 1 THEN
cmdLine ¬ listWatchCmd
ELSE {
cmdLine ¬ watchCmd;
FOR i: CARD IN [2..numArgs] DO
cmdLine ¬ Rope.Cat[cmdLine, " ", CommanderOps.NextArgument[cmd]];
ENDLOOP
};
[] ¬ CommanderOps.DoCommand[cmdLine, cmd];
};
SafetyNetHelp: Rope.ROPE ¬ NIL;
SafetyNetHelpRope: Rope.ROPE ¬ NIL;
SafetyNetHelpRope2: Rope.ROPE ¬ NIL;
SafetyNet: PROC[cmd: Commander.Handle, action: Rope.ROPE ¬ NIL] ~ {
netCmd: Rope.ROPE ¬ "NetCommanderListeners";
SELECT TRUE FROM
Rope.Equal[action, "on", FALSE] => {
IF thisTool.safetyNetStarted THEN {
IO.PutRope[cmd.out, "NetCommander already started.\n"];
}
ELSE {
netCmd ¬ IO.PutFR1["NetCommanderListeners; NetCommanderOn %g", IO.card[thisTool.safetyNetPort]];
[] ¬ CommanderOps.DoCommand[netCmd, cmd];
thisTool.safetyNetStarted ¬ TRUE;
SafetyNetHelp ¬ SafetyNetHelpRope;
};
};
Rope.Equal[action, "off", FALSE] => {
IF NOT thisTool.safetyNetStarted THEN {
IO.PutRope[cmd.out, "NetCommander already off.\n"];
}
ELSE {
netCmd ¬ "NetCommanderOff";
[] ¬ CommanderOps.DoCommand[netCmd, cmd];
thisTool.safetyNetStarted ¬ FALSE;
SafetyNetHelp ¬ SafetyNetHelpRope2;
};
};
ENDCASE => {
[] ¬ CommanderOps.DoCommand[netCmd, cmd];
};
IO.PutRope[cmd.out, SafetyNetHelp];
};
CirioHelpProc: Commander.CommandProc ~ {
numArgs: CARD ¬ CommanderOps.NumArgs[cmd];
arg: Rope.ROPE;
IF numArgs = 1 THEN
DisplayHelp[cmd.out, RemoteHelpMessages[currentLevel], 0]
ELSE
arg ¬ CommanderOps.NextArgument[cmd];
IF Rope.Equal[arg, "SafetyNet", FALSE] THEN {
[] ¬ SafetyNet[cmd, ""];
}
ELSE
IF Rope.Equal[arg, "all", FALSE] THEN {
[] ¬ SafetyNet[cmd, ""];
FOR i: ConnectionLevel IN ConnectionLevel DO
DisplayHelp[cmd.out, RemoteHelpMessages[i], i];
ENDLOOP
}
ELSE
IO.PutRope[cmd.out, "Usage: CirioHelp [all | safetynet]\n"];
};
DisplayHelp: PROC [where: IO.STREAM, messages: HelpRopes, indentLevel: CARD ¬ 0] ~ {
spaces: Rope.ROPE ¬ NIL;
FOR i: CARD IN [1..3*indentLevel] DO
spaces ¬ spaces.Concat[" "];
ENDLOOP;
IO.PutF[where, "%g%g\n", [rope[spaces]], [rope[messages[0]]]];
FOR i: CARD IN [1..messages.length) DO
IO.PutF[where, "%g %g\n", [rope[spaces]], [rope[messages[i]]]];
ENDLOOP;
};
QuitComLineProc: Commander.CommandProc ~ {
cmdData: CommanderBackdoor.CommandToolData ¬ NIL;
IF (currentConnection # NIL) OR (currentLocalConnection # NIL) THEN {
[ , ] ¬ WorldDisconnectProc[cmd];
};
cmdData ¬ CommanderBackdoor.GetCommandToolData[cmd];
cmdData.Prompt ¬ oldPrompt;
inCommLineCirio ¬ FALSE;
LevelFourToLevelThree[];
LevelThreeToLevelTwo[];
LevelTwoToLevelOne[];
LevelOneToLevelZero[];
Commander.Register["QuitCommandLineCirio", NIL ];
Commander.Register["CirioConnectToWorld", NIL ];
Commander.Register["CirioHelp", NIL];
Commander.Register["Quit", NIL];
Commander.Register["CirioDisconnectFromWorld", NIL];
Commander.Register["FlushUnknownFileCache", NIL];
Commander.Register["StopRemoteWorld", NIL];
Commander.Register["KillRemoteWorld", NIL];
Commander.Register["ResumeRemoteWorld", NIL];
Commander.Register["ResumeVP0", NIL];
Commander.Register["AddThreads", NIL];
Commander.Register["SetCurrentThread", NIL];
Commander.Register["PrintCurrentThread", NIL];
Commander.Register["AddDir", NIL];
Commander.Register["ListDir", NIL];
Commander.Register["RemoveDir", NIL];
Commander.Register["ClearDirs", NIL];
Commander.Register["SetBreak", NIL];
Commander.Register["BreakAtAddress", NIL];
Commander.Register["ListBreaks", NIL];
Commander.Register["ClearBreak", NIL];
Commander.Register["ToggleBreakStopAll", NIL];
Commander.Register["CirioDo", NIL];
Commander.Register["RemoteDisassemble", NIL];
Commander.Register["Summary", NIL];
Commander.Register["ListAvailableThreads", NIL];
Commander.Register["Freeze", NIL];
Commander.Register["Abort", NIL];
Commander.Register["Kill", NIL];
Commander.Register["Proceed", NIL];
Commander.Register["DbxExamine", NIL];
Commander.Register["Detailed", NIL];
Commander.Register["ShowSourcePosition", NIL];
Commander.Register["ShowFrame", NIL];
Commander.Register["WalkStack", NIL];
Commander.Register["Language", NIL];
Commander.Register["StartCommandLineCirio", StartComLineProc, "Start the command line cirio package."];
[] ¬ SafetyNet[cmd, "Off"];
};
QuitDummyProc: Commander.CommandProc ~ {
IO.PutRope[cmd.out, "Type at least the first five letters of a command beginning with 'quit'.\n"];
};
GetPortNum: PROC RETURNS[CARD] = TRUSTED MACHINE CODE
{"CirioNubLocalGetPort"};
WorldConnectProc: Commander.CommandProc ~ {
localhost: Rope.ROPE ¬ "localhost";
localworld: Rope.ROPE ¬ "LocalWorld";
remoteName: Rope.ROPE ¬ NIL;
remoteNameIP: Rope.ROPE ¬ NIL;
portNum: CARD ¬ 4815;
numArgs: INT ¬ CommanderOps.NumArgs[cmd];
wDirs: LIST OF Rope.ROPE ¬ NIL;
lastWDir: LIST OF Rope.ROPE ¬ NIL;
cDir: LIST OF Rope.ROPE ¬ LIST[PFS.RopeFromPath[PFS.GetWDir[]]];
{
ENABLE {
Convert.Error => {GOTO punt};
NetworkName.Error => {
errRope: Rope.ROPE ¬ NIL;
IO.PutF[cmd.out, "\nProblem(s) occured while looking up host %g (%g", [rope[remoteName]], [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 CheckLevel[LIST[CLCStarted], cmd.out] THEN
RETURN;
IF numArgs <= 1 THEN {
IO.PutRope[cmd.out, "You must specify a machine to connect to.\n"];
RETURN[];
};
IF numArgs >= 2 THEN {
remoteName ¬ CommanderOps.NextArgument[cmd];
IF (NOT Rope.Equal[localworld, remoteName, FALSE]) THEN {
remoteNameIP ¬ NetworkName.AddressFromName[family: $ARPA, name: remoteName, portHint: NIL, components: host].addr;
};
};
IF numArgs >= 3 THEN
portNum ¬ Convert.CardFromRope[CommanderOps.NextArgument[cmd]];
Get user supplied and default working directories
IF numArgs >= 4 THEN {
FOR i: INT IN [4..numArgs] DO
IF wDirs = NIL THEN {
wDirs ¬ LIST [CommanderOps.NextArgument[cmd]];
lastWDir ¬ wDirs;
}
ELSE {
lastWDir.rest ¬ LIST [CommanderOps.NextArgument[cmd]];
lastWDir ¬ lastWDir.rest;
};
ENDLOOP;
lastWDir.rest ¬ cDir;
}
ELSE {
wDirs ¬ cDir;
};
Try to prevent connecting to ourselves.
IF (portNum = thisTool.localPort AND (Rope.Equal[thisTool.localHostIP, remoteNameIP] OR Rope.Equal[localhost, remoteName])) THEN {
IO.PutRope[cmd.out, "\nYou are attempting to connect Cirio to itself.\nPlease verify the correct <MachineName> and <PortNumber> and try again.\n\n"];
RETURN;
};
IO.PutF1[cmd.out, "Connecting to %g ... \n", IO.rope[remoteName]];
IF Rope.Equal["LocalWorld", remoteName, FALSE] THEN {
LocalWorld debugging isn't ready yet?.
GOTO punt;
connectionType ¬ Local;
currentLocalConnection ¬ LocalCirio.GetConnection[["CommandLineDriver", "BreakPointPopUp"], cmd.out];
}
ELSE {
connectionType ¬ Remote;
currentConnection ¬ RemoteCirio.OpenConnection[
remoteName: remoteName,
portNum: portNum,
workingDirectories: wDirs,
reports: cmd.out];
IF currentConnection # NIL THEN
RemoteCirio.InstallBreakCheckDaemon[currentConnection, cmd.out];
};
IF (currentConnection # NIL) OR (currentLocalConnection # NIL) THEN {
IO.PutRope[cmd.out, "done.\n"];
IF connectionType = Remote THEN
currentDummyStack ¬ RemoteCirio.GetDummyStack[currentConnection, cmd.out]
ELSE {
currentStack ¬ LocalCirio.GetStackForSelf[currentLocalConnection, cmd.out];
currentDummyStack ¬ LocalCirio.GetDummyStack[currentLocalConnection, cmd.out];
};
remoteWorldRunning ¬ TRUE;
remoteHost ¬ remoteName;
vpZeroFlag ¬ FALSE;
currentLanguage ¬ Cedar;
commandNum ¬ 1;
threadMapping ← NIL;
LevelZeroToLevelOne[];
SetPromptToName;
Termination.CallBeforeQuitWorld[WorldDisconnectProcInner, cmd]
}
ELSE {
connectionType ¬ Nil;
IO.PutRope[cmd.out, "couldn't.\n"];
};
EXITS
punt => {IO.PutRope[cmd.out, "Usage: CirioConnectToWorld MachineName [PortNumber [ListOfWorkingDirectories]]\n"];};
done => {};
};
};
WorldDisconnectProc: Commander.CommandProc ~ {
IF CheckLevel[LIST[CLCStarted, CLCConnected], cmd.out] THEN
RETURN;
WorldDisconnectProcInner[cmd];
};
WorldDisconnectProcInner: PROC[cmd: REF ¬ NIL] ~ {
IF connectionType # Nil THEN {
ch: Commander.Handle ¬ NARROW[cmd];
IF connectionType = Remote THEN
IO.PutRope[ch.out, "Disconnecting from remote world ... "]
ELSE
IO.PutRope[ch.out, "Disconnecting from local world ... "];
This shouldn't be done [PJames 2/28/92]
IF remoteWorldRunning # TRUE THEN {
[ , ] ← ResumeRemoteWorldProc[ch];
};
IF connectionType = Remote THEN
RemoteCirio.CloseConnection[currentConnection, ch.out]
ELSE
LocalCirio.ReleaseConnection[currentLocalConnection, ch.out];
IO.PutRope[ch.out, "done.\n"];
currentConnection ¬ NIL;
currentLocalConnection ¬ NIL;
LevelFourToLevelThree[];
LevelThreeToLevelTwo[];
LevelTwoToLevelOne[];
LevelOneToLevelZero[];
connectionType ¬ Nil;
SetPromptToName[];
};
};
LevelZeroToLevelOne: PROC ~ {
currentLevel ¬ CLCConnected;
};
LevelOneToLevelTwo: PROC ~ {
currentLevel ¬ CLCStopped;
remoteWorldRunning ¬ FALSE;
};
LevelTwoToLevelThree: PROC ~ {
currentLevel ¬ CLCThreadsAdded;
};
LevelThreeToLevelFour: PROC ~ {
currentLevel ¬ CLCDetailed;
focused ¬ TRUE;
};
LevelFourToLevelThree: PROC ~ {
currentLevel ¬ CLCThreadsAdded;
focused ¬ FALSE;
};
LevelThreeToLevelTwo: PROC ~ {
currentLevel ¬ CLCStopped;
};
LevelTwoToLevelOne: PROC ~ {
currentLevel ¬ CLCConnected;
currentThreads ¬ NIL;
currentThread ¬ -1;
};
LevelOneToLevelZero: PROC ~ {
currentLevel ¬ CLCStarted;
};
LanguageProc: Commander.CommandProc ~ {
numArgs: CARD ¬ CommanderOps.NumArgs[cmd];
nextArg: Rope.ROPE ¬ NIL;
clear: PROC ¬ NIL;
lang: StackCirio.Language ¬ Cedar;
stackToUse: StackCirio.Stack;
IF CheckLevel[LIST[CLCDetailed], cmd.out] THEN
RETURN;
IF connectionType = Remote THEN
stackToUse ¬ currentStack
ELSE
stackToUse ¬ currentDummyStack;
IF numArgs > 2 THEN {
IO.PutRope[cmd.out, "Usage: Language [Cedar | Machine | C]\n"];
RETURN[];
};
IF numArgs = 2 THEN {
nextArg ¬ CommanderOps.NextArgument[cmd];
SELECT TRUE FROM
Rope.Equal[nextArg, "C", FALSE] => lang ¬ C;
Rope.Equal[nextArg, "Cedar", FALSE] => lang ¬ Cedar;
Rope.Equal[nextArg, "Machine", FALSE] => lang ¬ Machine;
ENDCASE => {
IO.PutRope[cmd.out, "Usage: Language [Cedar | Machine | C]\n"];
RETURN[];
};
currentLanguage ¬ lang;
StackCirio.SetDesiredLanguage[stackToUse, lang, cmd.out];
SetPromptToName[];
IO.PutRope[cmd.out, "Language is now "];
SELECT lang FROM
C => IO.PutRope[cmd.out, "C.\n"];
Cedar => IO.PutRope[cmd.out, "Cedar.\n"];
Machine => IO.PutRope[cmd.out, "Machine.\n"];
ENDCASE => {};
}
ELSE lang ¬ StackCirio.ReportDesiredLanguage[stackToUse, cmd.out];
};
FlipFlopLanguage: PROC [cmd: Commander.Handle] ~ {
stackToUse: StackCirio.Stack;
IF connectionType = Remote THEN
stackToUse ¬ currentStack
ELSE
stackToUse ¬ currentDummyStack;
SELECT currentLanguage FROM
Cedar => {
StackCirio.SetDesiredLanguage[stackToUse, C, cmd.out];
IO.PutRope[cmd.out, "Language is now C.\n"];
currentLanguage ¬ C;
};
C => {
StackCirio.SetDesiredLanguage[stackToUse, Machine, cmd.out];
IO.PutRope[cmd.out, "Language is now Machine.\n"];
currentLanguage ¬ Machine;
};
Machine => {
StackCirio.SetDesiredLanguage[stackToUse, Cedar, cmd.out];
IO.PutRope[cmd.out, "Language is now Cedar.\n"];
currentLanguage ¬ Cedar;
};
ENDCASE => {};
SetPromptToName[];
};
CirioDoProc: Commander.CommandProc ~ {
done: BOOL ¬ FALSE;
line, reslt: Rope.ROPE ¬ NIL;
stackToUse: StackCirio.Stack;
prompt: Rope.ROPE ¬ NIL;
numArgs:CARD ¬ CommanderOps.NumArgs[cmd];
getprompt: PROC = {prompt ¬ StackCirio.FormatPrompt[stackToUse, commandNum]; commandNum ¬ commandNum + 1};
interpret: PROC = {reslt ¬ StackCirio.InterpretTextLine[stackToUse, prompt.Concat[line], cmd.out]};
IF connectionType = Nil THEN {
[] ¬ CheckLevel[LIST[CLCConnected], cmd.out];
RETURN;
};
IF connectionType = Local AND CheckLevel[LIST[CLCConnected], cmd.out] THEN
RETURN
ELSE IF connectionType = Remote AND CheckLevel[LIST[CLCConnected, CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF connectionType = Remote THEN
stackToUse ¬ IF focused THEN currentStack ELSE currentDummyStack
ELSE
stackToUse ¬ currentDummyStack;
IF numArgs > 1 THEN {
line ¬ CommanderOps.NextArgument[cmd];
numArgs ¬ numArgs - 1;
WHILE numArgs > 1 DO
line ¬ line.Cat[" ", CommanderOps.NextArgument[cmd]];
numArgs ¬ numArgs - 1;
ENDLOOP;
getprompt;
IO.PutF1[cmd.out, "%g\n", IO.rope[prompt.Concat[line]]];
IF connectionType = Local THEN
LocalCirio.DoUnderMonitorLock[currentLocalConnection, interpret]
ELSE
interpret[];
IO.PutF1[cmd.out, "%g\n", IO.rope[reslt]];
}
ELSE {
IO.PutRope[cmd.out, "ChL to change language, Exit to return\n"];
WHILE NOT done DO
getprompt;
IO.PutF1[cmd.out, "%g", IO.rope[prompt]];
line ¬ IO.GetLineRope[cmd.in];
IF Rope.Equal[line, "Quit", FALSE] OR Rope.Equal[line,"Q", FALSE] OR Rope.Equal[line, "Exit", FALSE] THEN {
commandNum ¬ commandNum - 1;
done ¬ TRUE;
}
ELSE IF Rope.Equal[line, "\n", FALSE] OR Rope.IsEmpty[line] THEN {
commandNum ¬ commandNum - 1;
}
ELSE IF Rope.Equal[line, "ChL", FALSE] THEN {
FlipFlopLanguage[cmd];
commandNum ¬ commandNum - 1;
}
ELSE {
IF connectionType = Local THEN
LocalCirio.DoUnderMonitorLock[currentLocalConnection, interpret]
ELSE
interpret[];
IO.PutF1[cmd.out, "%g\n", IO.rope[reslt]];
};
ENDLOOP;
};
};
SetBreakProc: Commander.CommandProc ~ {
ENABLE
Convert.Error => {GOTO Punt};
mesaFileName: PFS.PATH;
mesaFileN: Rope.ROPE;
mesaSourcePos: INT;
breakPos: SourceFileOps.Position;
stopAll: BOOLEAN ¬ FALSE;
uniqueID: SourceFileOps.UniqueID ¬ SourceFileOps.nullUniqueID;
numArgs: CARD ¬ CommanderOps.NumArgs[cmd];
IF connectionType = Local AND CheckLevel[LIST[CLCConnected], cmd.out] THEN
RETURN
ELSE IF CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF numArgs # 3 THEN {
IO.PutRope[cmd.out, "Usage: SetBreak FullPathOfSourceFile CharacterPositionInSourceFile\n"];
RETURN[];
};
IO.PutRope[cmd.out, "Setting break ... "];
mesaFileN ¬ CommanderOps.NextArgument[cmd];
mesaSourcePos ¬ Convert.IntFromRope[CommanderOps.NextArgument[cmd]];
mesaFileName ¬ PFS.PathFromRope[mesaFileN];
uniqueID ¬ PFS.FileInfo[mesaFileName !PFS.Error => {msg ¬ IO.PutFR["PFS.FileInfo[%g] => PFS.Error[%g, %g]", [rope[mesaFileN]], [atom[error.code]], [rope[error.explanation]] ]; CONTINUE}].uniqueID;
IF msg#NIL THEN RETURN [$Failure, msg];
{
set: PROC = {breakPos ¬ StackCirio.SetBreakPointAtPosition[currentDummyStack, [mesaFileName, uniqueID, [char: [mesaSourcePos], line: [mesaSourcePos]]], cmd.out, stopAllFlag]};
IF connectionType = Local THEN {
IO.PutRope[cmd.out, ". "];
LocalCirio.DoUnderMonitorLock[currentLocalConnection, set]
}
ELSE
set[];
};
IF breakPos # SourceFileOps.noPosition THEN
IO.PutRope[cmd.out, "done.\n"];
EXITS
Punt => {IO.PutRope[cmd.out, "Usage: SetBreak FullPathOfSourceFile CharacterPositionInSourceFile\n"]};
};
SetBreakAtAddressProc: Commander.CommandProc ~ {
stopAll: BOOLEAN ¬ FALSE;
addrRope: Rope.ROPE;
addr: CARD;
numArgs: CARD ¬ CommanderOps.NumArgs[cmd];
IF connectionType = Local AND CheckLevel[LIST[CLCConnected], cmd.out] THEN
RETURN
ELSE IF CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF numArgs # 2 THEN {
IO.PutRope[cmd.out, "Usage: BreakAtAddress Address\n"];
RETURN[];
};
addrRope ¬ CommanderOps.NextArgument[cmd];
TRUSTED {addr ¬ DisassembleSPARC.CardFromRope[addrRope !Convert.Error => {
cmd.out.PutF["Syntax error (VAL[%g]) at %g --- Address should be an unsigned number in C or Mesa syntax", [integer[reason.ORD]], [integer[index]] ];
GOTO Bail}]};
cmd.out.PutF1["Setting break at 0x%08x ... ", [cardinal[addr]] ];
StackCirio.SetBreakPointAtAddress[currentDummyStack, addr, cmd.out, stopAllFlag];
IO.PutRope[cmd.out, "done.\n"]
EXITS
Bail => NULL;
};
RemoteDisassembleProc: Commander.CommandProc ~ {
stopFlag: REF BOOLEAN ¬ NEW[BOOLEAN ¬ FALSE];
addrRope: Rope.ROPE;
numArgs: CARD ¬ CommanderOps.NumArgs[cmd];
IF connectionType = Local AND CheckLevel[LIST[CLCConnected], cmd.out] THEN
RETURN
ELSE IF CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF numArgs # 2 THEN {
IO.PutRope[cmd.out, "Usage: RemoteDisassemble [CProcName | PC]\n"];
RETURN[];
};
addrRope ¬ CommanderOps.NextArgument[cmd];
IO.PutRope[cmd.out, "Disassemble ... "];
StackCirio.Disassemble[currentDummyStack, addrRope, cmd.out, stopFlag];
IO.PutRope[cmd.out, "done.\n"]
};
ListBreakProc: Commander.CommandProc ~ {
list: PROC = { StackCirio.ListBreakPoints[currentDummyStack, cmd.out]};
IF connectionType = Local AND CheckLevel[LIST[CLCConnected], cmd.out] THEN
RETURN
ELSE IF connectionType = Remote AND CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IO.PutRope[cmd.out, "Listing break(s) ... \n"];
IF connectionType = Local THEN
LocalCirio.DoUnderMonitorLock[currentLocalConnection, list]
ELSE
list[];
IO.PutRope[cmd.out, "done.\n"];
};
ClearBreakProc: Commander.CommandProc ~ {
ENABLE
Convert.Error => {GOTO punt};
numArgs: CARD ¬ CommanderOps.NumArgs[cmd];
nextArg: Rope.ROPE ¬ NIL;
breakNum: INT ¬ 0;
stackToUse: StackCirio.Stack ¬ NIL;
mesaFileName: PFS.PATH;
mesaFileN: Rope.ROPE;
mesaSourcePos: INT;
uniqueID: SourceFileOps.UniqueID ¬ SourceFileOps.nullUniqueID;
IF connectionType = Local AND CheckLevel[LIST[CLCConnected], cmd.out] THEN
RETURN
ELSE IF connectionType = Remote AND CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF numArgs > 3 THEN {
IO.PutRope[cmd.out, "Usage: ClearBreak [# | All | FullPathOfSourceFile CharacterPositionInSourceFile]\n"];
RETURN[];
};
IF numArgs = 3 THEN {
IO.PutRope[cmd.out, "Clearing break ... "];
mesaFileN ¬ CommanderOps.NextArgument[cmd];
mesaSourcePos ¬ Convert.IntFromRope[CommanderOps.NextArgument[cmd]];
mesaFileName ¬ PFS.PathFromRope[mesaFileN];
uniqueID ¬ PFS.FileInfo[mesaFileName !PFS.Error => {msg ¬ IO.PutFR["PFS.FileInfo[%g] => PFS.Error[%g, %g]", [rope[mesaFileN]], [atom[error.code]], [rope[error.explanation]] ]; CONTINUE}].uniqueID;
IF msg#NIL THEN RETURN [$Failure, msg];
IF connectionType = Local THEN
stackToUse ¬ currentDummyStack
ELSE
stackToUse ¬ IF currentStack = NIL THEN currentDummyStack ELSE currentStack;
{
clear:PROC = {StackCirio.ClearBreakPointAtPosition[stackToUse, [mesaFileName, uniqueID, [char: [mesaSourcePos] ]], cmd.out]};
IF connectionType = Local THEN
LocalCirio.DoUnderMonitorLock[currentLocalConnection, clear]
ELSE
clear[];
}
}
ELSE {
IF numArgs = 2 THEN {
nextArg ¬ CommanderOps.NextArgument[cmd];
IF Rope.Equal[nextArg, "ALL", FALSE] THEN {
clear: PROC = {StackCirio.ClearAllBreakPoints[currentDummyStack, cmd.out]};
IO.PutRope[cmd.out, "Clearing all breaks ... \n"];
IF connectionType = Local THEN
LocalCirio.DoUnderMonitorLock[currentLocalConnection, clear]
ELSE
clear[];
}
ELSE {
breakNum ¬ Convert.IntFromRope[nextArg];
{
clear: PROC = {StackCirio.ClearIthBreakPoint[currentDummyStack, breakNum, cmd.out]};
IO.PutF1[cmd.out, "Clearing break #%g ... \n", IO.card[breakNum]];
IF connectionType = Local THEN
LocalCirio.DoUnderMonitorLock[currentLocalConnection, clear]
ELSE
clear[];
}
}
}
ELSE {
IO.PutRope[cmd.out, "Clearing current break ... \n"];
IF connectionType = Local THEN
stackToUse ¬ currentDummyStack
ELSE
stackToUse ¬ IF currentStack = NIL THEN currentDummyStack ELSE currentStack;
{
clear:PROC = {StackCirio.ClearBreakPoint[stackToUse, cmd.out]};
IF connectionType = Local THEN
LocalCirio.DoUnderMonitorLock[currentLocalConnection, clear]
ELSE
clear[];
}
}
}
IO.PutRope[cmd.out, "done.\n"];
EXITS
punt => {
IO.PutRope[cmd.out, "Usage: ClearBreak [# | All | FullPathOfSourceFile CharacterPositionInSourceFile]\n"];
};
};
ToggleBreakStopAllProc: Commander.CommandProc ~ {
IF CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF connectionType = Remote THEN
{stopAllFlag ¬ ~ stopAllFlag;
IO.PutRope[cmd.out, "stopAll mode becomes "];
IF stopAllFlag THEN IO.PutRope[cmd.out, "TRUE\n"] ELSE IO.PutRope[cmd.out, "FALSE\n"];}
ELSE
{IO.PutRope[cmd.out, "You can't use stopAll mode for the local world.\n"];};
};
StopRemoteWorldProc: Commander.CommandProc ~ {
ENABLE CCTypes.CCError => {
cmd.out.PutF1[" CCTypes.CCError: %g (try again)\n", [rope[msg]]];
GOTO dead;
};
IF connectionType = Local THEN {
IO.PutRope[cmd.out, "You don't want to stop the world you are running in.\n"];
RETURN;
};
IF CheckLevel[LIST[CLCConnected], cmd.out] THEN
RETURN;
IO.PutRope[cmd.out, "Stopping remote world execution ... "];
[] ¬ RemoteCirio.StopRemoteWorld[currentConnection, cmd.out];
IO.PutRope[cmd.out, "done.\n"];
vpZeroFlag ¬ FALSE;
currentStack ¬ NIL;
LevelOneToLevelTwo[];
SetPromptToName[];
EXITS dead => {};
};
ResumeRemoteWorldProc: Commander.CommandProc ~ {
ENABLE CCTypes.CCError => {
cmd.out.PutF1[" CCTypes.CCError: %g (probably worked - if not try again)\n", [rope[msg]]];
GOTO dead;
};
IF CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IO.PutRope[cmd.out, "Resuming remote world execution ... "];
RemoteCirio.ResumeRemoteWorld[currentConnection];
IO.PutRope[cmd.out, "resumed.\n"];
remoteWorldRunning ¬ TRUE;
LevelFourToLevelThree[];
LevelThreeToLevelTwo[];
LevelTwoToLevelOne[];
SetPromptToName[];
EXITS dead => {};
};
ResumeRemoteWorldVP0Proc: Commander.CommandProc ~ {
ENABLE CCTypes.CCError => {
cmd.out.PutF1[" CCTypes.CCError: %g (probably worked - if not try again)\n", [rope[msg]]];
GOTO dead;
};
IF CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IO.PutRope[cmd.out, "Resuming remote world execution with only VP0 ... "];
RemoteCirio.ResumeRemoteWorldWithOnlyVP0[currentConnection];
IO.PutRope[cmd.out, "resumed with only VP0.\n"];
remoteWorldRunning ¬ TRUE;
vpZeroFlag ¬ TRUE;
LevelFourToLevelThree[];
LevelThreeToLevelTwo[];
LevelTwoToLevelOne[];
SetPromptToName[];
EXITS dead => {};
};
KillWorldProc: Commander.CommandProc ~ {
inputLine: Rope.ROPE ¬ NIL;
response: CHAR;
IF connectionType = Local THEN {
IO.PutRope[cmd.out, "You don't want to kill the world you are running in.\n"];
RETURN;
};
IF CheckLevel[LIST[CLCConnected, CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IO.PutRope[cmd.out, "Really kill remote world? "];
inputLine ¬ IO.GetLineRope[cmd.in];
IF inputLine.IsEmpty[] THEN
RETURN;
response ¬ Rope.Fetch[inputLine, 0];
IF (response = 'Y OR response = 'y) THEN {
RemoteCirio.StopBreakCheckDaemon[connection: currentConnection, reports: cmd.out];
IO.PutRope[cmd.out, "Killing remote world ... "];
RemoteCirio.DestroyRemoteWorld[currentConnection];
IO.PutRope[cmd.out, "killed.\n"];
currentConnection ¬ NIL;
remoteWorldRunning ¬ TRUE;
LevelFourToLevelThree[];
LevelThreeToLevelTwo[];
LevelTwoToLevelOne[];
LevelOneToLevelZero[];
connectionType ¬ Nil;
SetPromptToName[];
}
};
FlushUFCProc: Commander.CommandProc ~ {
IF CheckLevel[LIST[CLCConnected, CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IO.PutRope[cmd.out, "Flushing file cache ... "];
IF connectionType = Local THEN
LocalCirio.FlushUnknownFileCache[currentLocalConnection, cmd.out]
ELSE
RemoteCirio.FlushUnknownFileCache[currentConnection, cmd.out];
IO.PutRope[cmd.out, "done.\n"];
};
SizeOfList: PROC[l: LIST OF CARD] RETURNS [num: CARD ¬ 0] ~ {
FOR index: LIST OF CARD ¬ l, index.rest WHILE index # NIL DO
num ¬ num + 1;
ENDLOOP;
};
ThreadInList: PROC [t: CARD, l: LIST OF CARD] RETURNS [BOOLEAN] ~ {
FOR index: LIST OF CARD ← l, index.rest WHILE index # NIL DO
IF index.first = t THEN
RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
};
PrintList: PROC [l: LIST OF CARD, cmd: Commander.Handle] ~ {
FOR index: LIST OF CARD ← l, index.rest WHILE index # NIL DO
IO.PutRope[cmd.out, "%g ", IO.card[index.first]];
ENDLOOP;
};
AddToList: PROC [ c: CARD, l: LIST OF CARD--, cmd: Commander.Handle--]
RETURNS [nl: LIST OF CARD ¬ NIL] ~ {
tl: LIST OF CARD ¬ NIL;
already: BOOL ¬ FALSE;
IF l = NIL THEN
nl ¬ LIST[c]
ELSE {
FOR index: LIST OF CARD ¬ l, index.rest WHILE index # NIL DO
tl ¬ CONS[index.first, tl];
IF index.first = c THEN
already ¬ TRUE;
ENDLOOP;
IF NOT already THEN
tl ¬ CONS[c, tl];
FOR index: LIST OF CARD ¬ tl, index.rest WHILE index # NIL DO
nl ¬ CONS[index.first, nl];
ENDLOOP;
};
};
AddNewThreads: PROC [newThreads: LIST OF CARD--, cmd: Commander.Handle--] ~ {
newThreadList: LIST OF CARD ¬ NIL;
index, index2: LIST OF CARD ¬ NIL;
IF newThreads # NIL THEN {
IF currentThreads = NIL THEN
currentThreads ¬ newThreads
ELSE {
index2 ¬ newThreads;
FOR index ¬ currentThreads, index.rest WHILE index # NIL DO
IF (index2 = NIL) THEN
newThreadList ¬ AddToList[index.first, newThreadList--, cmd--]
ELSE IF (index.first <= index2.first) THEN {
newThreadList ¬ AddToList[index.first, newThreadList--, cmd--];
IF index2.first = index.first THEN
index2 ¬ index2.rest;
}
ELSE {
FOR index2 ¬ index2, index2.rest
WHILE (index2 # NIL) AND (index2.first < index.first) DO
newThreadList ¬ AddToList[index2.first, newThreadList--, cmd--];
ENDLOOP;
index ¬ CONS [3, index];
}
ENDLOOP;
FOR index2 ¬ index2, index2.rest WHILE (index2 # NIL) DO
newThreadList ¬ AddToList[index2.first, newThreadList--, cmd--];
ENDLOOP;
currentThreads ¬ newThreadList;
};
};
FOR index2 ← newThreads, index2.rest WHILE index2 # NIL DO
AddThreadMapping[index2.first];
ENDLOOP;
};
AddThreadsProc: Commander.CommandProc ~ {
newThreads: LIST OF CARD ¬ NIL;
threadProp: REF RemoteCirio.ThreadProperty;
numArgs: CARD ¬ CommanderOps.NumArgs[cmd];
allRope: Rope.ROPE ¬ "All";
readyRope: Rope.ROPE ¬ "Ready";
callingRope: Rope.ROPE ¬ "Calling";
callingDRope: Rope.ROPE ¬ "CallingDebugger";
threadArg: Rope.ROPE ¬ callingDRope;
setCurrentThreadOptimization: BOOL ¬ FALSE;
IF CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF numArgs > 1 THEN
threadArg ¬ CommanderOps.NextArgument[cmd];
IF Rope.Equal[threadArg, allRope, FALSE] THEN {
IO.PutRope[cmd.out, "Adding all threads ... "];
threadProp ¬ NEW[RemoteCirio.ThreadProperty ¬ [any []]];
}
ELSE IF Rope.Equal[threadArg, readyRope, FALSE] THEN {
IO.PutRope[cmd.out, "Adding ready threads (including running) ... "];
threadProp ¬ NEW[RemoteCirio.ThreadProperty ¬ [ready[]]];
}
ELSE IF (Rope.Equal[threadArg, callingRope, FALSE ] OR
Rope.Equal[threadArg, callingDRope, FALSE]) THEN {
IO.PutRope[cmd.out, "Adding threads calling debugger ... "];
threadProp ¬ NEW[RemoteCirio.ThreadProperty ¬ [callingDebugger[]]];
setCurrentThreadOptimization ¬ TRUE;
}
ELSE {
IO.PutRope[cmd.out, "Bad argument. \nUsage: AddThreads [All | Ready | CallingDebugger]\n"];
RETURN;
};
newThreads ¬ RemoteCirio.FindThreadsWithProperty[currentConnection,
threadProp­, cmd.out];
AddNewThreads[newThreads];
IO.PutRope[cmd.out, "added.\n"];
ShowAvailableThreads[cmd];
IF SizeOfList[currentThreads] > 0 THEN {
realThreadID: CARD;
IF newThreads # NIL THEN {
realThreadID ¬ RemoteCirio.ThreadIDFromIndex[newThreads.first, currentConnection];
IF setCurrentThreadOptimization THEN
IF realThreadID # LAST[CARD] THEN
SetCurrentThreadProcInner[realThreadID];
};
LevelTwoToLevelThree[];
}
};
SetCurrentThreadProc: Commander.CommandProc ~ {
ENABLE
Convert.Error => {GOTO punt};
IF CheckLevel[LIST[CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
oldCurrentThread ¬ currentThread;
IF CommanderOps.NumArgs[cmd] = 1 THEN GOTO punt;
currentThread ¬ Convert.CardFromRope[CommanderOps.NextArgument[cmd]];
IO.PutF1[cmd.out, "Current thread set to %g.\n", IO.card[currentThread]];
EXITS
punt => {
IO.PutRope[cmd.out, "Usage: SetCurrentThread ThreadID\n"];
currentThread ¬ oldCurrentThread;
}
};
SetCurrentThreadProcInner: PROC[threadID: CARD] ~ {
oldCurrentThread ¬ currentThread;
currentThread ¬ threadID;
};
PrintCurrentThreadProc: Commander.CommandProc ~ {
IF CheckLevel[LIST[CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF currentThread = -1 THEN
IO.PutRope[cmd.out, "No current thread set.\n"]
ELSE
IO.PutF1[cmd.out, "Thread %g is the current thread.\n", IO.int[currentThread]];
};
ShowAvailableThreads: PROC [cmd: Commander.Handle] ~ {
IF currentThreads = NIL THEN
IO.PutRope[cmd.out, "No available Threads.\n"]
ELSE
FOR index: LIST OF CARD ¬ currentThreads, index.rest WHILE index # NIL DO
IO.PutF1[cmd.out, "%g\n", IO.rope[RemoteCirio.GetThreadTitleText[currentConnection,
index.first]]];
ENDLOOP;
};
ListThreadsProc: Commander.CommandProc ~ {
IF CheckLevel[LIST[CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IO.PutRope[cmd.out, "Available Threads:\n"];
ShowAvailableThreads[cmd];
};
SummaryProc: Commander.CommandProc ~ {
ENABLE
Convert.Error => {GOTO punt};
stopFlag: REF BOOLEAN ¬ NEW[BOOLEAN ¬ FALSE];
threads: LIST OF CARD;
threadIndex, threadID: CARD ¬ 0;
numArgs: CARDINAL ¬ 0;
IF CheckLevel[LIST[CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF currentThreads = NIL THEN {
IO.PutRope[cmd.out, "No threads avaliable\n"];
RETURN;
};
numArgs ¬ CommanderOps.NumArgs[cmd];
IF numArgs = 1 THEN
IF currentThread >= 0 THEN
threads ¬ LIST[RemoteCirio.ThreadIndexFromID[currentThread, currentConnection]]
ELSE {
IO.PutRope[cmd.out, "Must specify a thread.\n"];
RETURN;
}
ELSE
threads ¬ GetDesiredThreads[cmd];
FOR loop: LIST OF CARD ¬ threads, loop.rest WHILE loop # NIL DO
threadIndex ¬ loop.first;
IF (threadID ¬ RemoteCirio.ThreadIDFromIndex[threadIndex, currentConnection]) = LAST[CARD] THEN
IO.PutF1[cmd.out, "Thread %g is not available\n", IO.card[threadID]]
ELSE
RemoteCirio.ShowQuickSummary[currentConnection, threadIndex, stopFlag, cmd.out, TRUE];
ENDLOOP;
EXITS
punt => {
IO.PutRope[cmd.out, "Usage: Summary [ThreadID | listed]\n"];
}
};
FreezeThreadProc: Commander.CommandProc ~ {
ENABLE
Convert.Error => {GOTO punt};
threads: LIST OF CARD;
threadIndex, threadID: CARD ¬ 0;
numArgs: CARDINAL ¬ 0;
titleText: Rope.ROPE ¬ NIL;
IF CheckLevel[LIST[CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF currentThreads = NIL THEN {
IO.PutRope[cmd.out, "No threads avaliable\n"];
RETURN;
};
numArgs ¬ CommanderOps.NumArgs[cmd];
IF numArgs = 1 THEN
IF currentThread >= 0 THEN
threads ¬ LIST[RemoteCirio.ThreadIndexFromID[currentThread, currentConnection]]
ELSE {
IO.PutRope[cmd.out, "Must specify a thread.\n"];
RETURN
}
ELSE
threads ¬ GetDesiredThreads[cmd];
FOR loop: LIST OF CARD ¬ threads, loop.rest WHILE loop # NIL DO
threadIndex ¬ loop.first;
IF (threadID ¬ RemoteCirio.ThreadIDFromIndex[threadIndex, currentConnection]) = LAST[CARD] THEN
IO.PutF1[cmd.out, "Thread %g is not available\n", IO.card[threadID]]
ELSE {
IO.PutF1[cmd.out, "Freezing thread %g ... ", IO.card[threadID]];
titleText ¬ RemoteCirio.FreezeThread[currentConnection, threadIndex, cmd.out];
};
ENDLOOP;
IO.PutRope[cmd.out, "done.\n"];
EXITS
punt => {
IO.PutRope[cmd.out, "Usage: Freeze [ ThreadID | listed ]\n"];
};
};
GetDesiredThreads: PROCEDURE [cmd: Commander.Handle] RETURNS [list: LIST OF CARD ¬ NIL] ~ {
arg: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
IF arg.Length[] >=4 AND Rope.Equal[arg.Substr[0, 4], "list"] THEN
list ¬ currentThreads
ELSE
list ¬ LIST[RemoteCirio.ThreadIndexFromID[Convert.CardFromRope[arg], currentConnection]];
};
AbortThreadProc: Commander.CommandProc ~ {
ENABLE
Convert.Error => {GOTO punt};
threads: LIST OF CARD;
threadIndex, threadID: CARD ¬ 0;
numArgs: CARDINAL ¬ 0;
titleText: Rope.ROPE ¬ NIL;
IF CheckLevel[LIST[CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF currentThreads = NIL THEN {
IO.PutRope[cmd.out, "No threads avaliable\n"];
RETURN;
};
numArgs ¬ CommanderOps.NumArgs[cmd];
IF numArgs = 1 THEN
IF currentThread >= 0 THEN
threads ¬ LIST[RemoteCirio.ThreadIndexFromID[currentThread, currentConnection]]
ELSE {
IO.PutRope[cmd.out, "Must specify a thread.\n"];
RETURN
}
ELSE
threads ¬ GetDesiredThreads[cmd];
FOR loop: LIST OF CARD ¬ threads, loop.rest WHILE loop # NIL DO
threadIndex ¬ loop.first;
IF (threadID ¬ RemoteCirio.ThreadIDFromIndex[threadIndex, currentConnection]) = LAST[CARD] THEN
IO.PutF1[cmd.out, "Thread %g is not available\n", IO.card[threadID]]
ELSE {
IO.PutF1[cmd.out, "Aborting thread %g ... ", IO.card[threadID]];
titleText ¬ RemoteCirio.AbortThread[currentConnection, threadIndex, cmd.out];
};
ENDLOOP;
IO.PutRope[cmd.out, "done.\n"];
EXITS
punt => {
IO.PutRope[cmd.out, "Usage: Abort [ ThreadID | listed ]\n"];
};
};
KillThreadProc: Commander.CommandProc ~ {
ENABLE
Convert.Error => {GOTO punt};
threads: LIST OF CARD;
threadIndex, threadID: CARD ¬ 0;
numArgs: CARDINAL ¬ 0;
titleText: Rope.ROPE ¬ NIL;
IF CheckLevel[LIST[CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF currentThreads = NIL THEN {
IO.PutRope[cmd.out, "No threads avaliable\n"];
RETURN;
};
numArgs ¬ CommanderOps.NumArgs[cmd];
IF numArgs = 1 THEN
IF currentThread >= 0 THEN
threads ¬ LIST[RemoteCirio.ThreadIndexFromID[currentThread, currentConnection]]
ELSE {
IO.PutRope[cmd.out, "Must specify a thread.\n"];
RETURN
}
ELSE
threads ¬ GetDesiredThreads[cmd];
FOR loop: LIST OF CARD ¬ threads, loop.rest WHILE loop # NIL DO
threadIndex ¬ loop.first;
IF (threadID ¬ RemoteCirio.ThreadIDFromIndex[threadIndex, currentConnection]) = LAST[CARD] THEN
IO.PutF1[cmd.out, "Thread %g is not available\n", IO.card[threadID]]
ELSE {
IO.PutF1[cmd.out, "Killing thread %g ... ", IO.card[threadID]];
titleText ¬ RemoteCirio.KillThread[currentConnection, threadIndex, cmd.out];
};
ENDLOOP;
IO.PutRope[cmd.out, "done.\n"];
EXITS
punt => {
IO.PutRope[cmd.out, "Usage: Kill [ ThreadID | listed ]\n"];
};
};
ProceedThreadProc: Commander.CommandProc ~ {
ENABLE
Convert.Error => {GOTO punt};
threads: LIST OF CARD;
threadIndex, threadID: CARD ¬ 0;
numArgs: CARDINAL ¬ 0;
titleText: Rope.ROPE ¬ NIL;
IF CheckLevel[LIST[CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF currentThreads = NIL THEN {
IO.PutRope[cmd.out, "No threads avaliable\n"];
RETURN;
};
numArgs ¬ CommanderOps.NumArgs[cmd];
IF numArgs = 1 THEN
IF currentThread >= 0 THEN
threads ¬ LIST[RemoteCirio.ThreadIndexFromID[currentThread, currentConnection]]
ELSE {
IO.PutRope[cmd.out, "Must specify a thread.\n"];
RETURN
}
ELSE
threads ¬ GetDesiredThreads[cmd];
FOR loop: LIST OF CARD ¬ threads, loop.rest WHILE loop # NIL DO
threadIndex ¬ loop.first;
IF (threadID ¬ RemoteCirio.ThreadIDFromIndex[threadIndex, currentConnection]) = LAST[CARD] THEN
IO.PutF1[cmd.out, "Thread %g is not available\n", IO.card[threadID]]
ELSE {
IO.PutF1[cmd.out, "Proceeding thread %g ... ", IO.card[threadID]];
titleText ¬ RemoteCirio.ProceedThread[currentConnection, threadIndex, cmd.out];
};
ENDLOOP;
IO.PutRope[cmd.out, "done.\n"];
EXITS
punt => {
IO.PutRope[cmd.out, "Usage: Proceed [ ThreadID | listed ]\n"];
};
};
DbxExamineThreadProc: Commander.CommandProc ~ {
ENABLE
Convert.Error => {GOTO punt};
holdT, threadID: CARD ¬ 0;
numArgs: CARDINAL ¬ 0;
nThreads: CARD ¬ 0;
IF CheckLevel[LIST[CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF currentThreads = NIL THEN {
IO.PutRope[cmd.out, "No threads avaliable\n"];
RETURN;
};
numArgs ¬ CommanderOps.NumArgs[cmd];
IF numArgs = 1 THEN
IF currentThread >= 0 THEN
threadID ¬ currentThread
ELSE {
IO.PutRope[cmd.out, "Must specify a thread.\n"];
RETURN
}
ELSE
threadID ¬ Convert.CardFromRope[CommanderOps.NextArgument[cmd]];
holdT ¬ threadID;
IF (threadID ¬ RemoteCirio.ThreadIndexFromID[threadID, currentConnection]) = LAST[CARD] THEN {
IO.PutF1[cmd.out, "Thread %g is not available\n", IO.card[holdT]];
RETURN;
}
ELSE {
IO.PutF1[cmd.out, "Freezing thread %g ... \n", IO.card[holdT]];
nThreads ¬ RemoteCirio.DbxExamineThread[currentConnection, threadID, cmd.out];
IO.PutRope[cmd.out, "done.\n"];
};
EXITS
punt => {
IO.PutRope[cmd.out, "Usage: DbxExamine ThreadID\n"];
};
};
DetailedProc: Commander.CommandProc ~ {
ENABLE
Convert.Error => {GOTO punt};
holdT, threadID: CARD ¬ 0;
numArgs: CARDINAL ¬ 0;
newRemoteThreadIndex: CARD ¬ 0;
IF CheckLevel[LIST[CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF currentThreads = NIL THEN {
IO.PutRope[cmd.out, "No threads avaliable\n"];
RETURN;
};
numArgs ¬ CommanderOps.NumArgs[cmd];
IF numArgs = 1 THEN
IF currentThread >= 0 THEN
threadID ¬ currentThread
ELSE {
IO.PutRope[cmd.out, "Must specify a thread.\n"];
RETURN
}
ELSE
threadID ¬ Convert.CardFromRope[CommanderOps.NextArgument[cmd]];
holdT ¬ threadID;
IF (threadID ¬ RemoteCirio.ThreadIndexFromID[threadID, currentConnection]) = LAST[CARD] THEN {
IO.PutF1[cmd.out, "Thread %g is not available\n", IO.card[holdT]];
RETURN;
}
ELSE {
lastDetailed ¬ holdT;
IO.PutF1[cmd.out, "switching to thread %g ... ", IO.card[holdT]];
newRemoteThreadIndex ¬ RemoteCirio.FocusOnThread[currentConnection, threadID, cmd.out];
IF newRemoteThreadIndex # holdT THEN ERROR;
currentStack ¬ RemoteCirio.GetStackForCurrentThread[currentConnection, cmd.out];
threadID ← StackCirio.ResetStack[currentStack, cmd.out];
currentFrame ¬ StackCirio.ResetStack[currentStack, cmd.out];
IO.PutRope[cmd.out, "done.\n"];
SetCurrentThreadProcInner[lastDetailed];
LevelThreeToLevelFour[];
currentFrame ← 0;
SetPromptToName[];
};
EXITS
punt => {
IO.PutRope[cmd.out, "Usage: Detailed ThreadID\n"];
};
};
AddDirProc: Commander.CommandProc ~ {
numArgs: CARD ¬ CommanderOps.NumArgs[cmd];
dirToAdd: Rope.ROPE ¬ NIL;
IF connectionType = Local AND CheckLevel[LIST[CLCConnected], cmd.out] THEN
RETURN
ELSE IF connectionType = Remote AND CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF numArgs < 2 THEN {
IO.PutRope[cmd.out, "Usage: AddDir NewDirectory\n"];
RETURN;
}
ELSE {
dirToAdd ¬ CommanderOps.NextArgument[cmd];
IO.PutRope[cmd.out, "Adding search directory ... "];
IF connectionType = Local THEN
LocalCirio.AddSearchDirectory[currentLocalConnection, dirToAdd, cmd.out]
ELSE
RemoteCirio.AddSearchDirectory[currentConnection, dirToAdd, cmd.out];
IO.PutRope[cmd.out, "done.\n"];
};
};
RemoveDirProc: Commander.CommandProc ~ {
numArgs: CARD ¬ CommanderOps.NumArgs[cmd];
dirToRem: Rope.ROPE ¬ NIL;
IF connectionType = Local AND CheckLevel[LIST[CLCConnected], cmd.out] THEN
RETURN
ELSE IF connectionType = Remote AND CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF numArgs < 2 THEN {
IO.PutRope[cmd.out, "Usage: RemoveDir DirectoryToBeRemoved\n"];
RETURN;
}
ELSE {
dirToRem ¬ CommanderOps.NextArgument[cmd];
IO.PutRope[cmd.out, "Removing search directory ... "];
IF connectionType = Local THEN
LocalCirio.RemoveSearchDirectory[currentLocalConnection, dirToRem, cmd.out]
ELSE
RemoteCirio.RemoveSearchDirectory[currentConnection, dirToRem, cmd.out];
IO.PutRope[cmd.out, "done.\n"];
};
};
ListDirProc: Commander.CommandProc ~ {
IF connectionType = Local AND CheckLevel[LIST[CLCConnected], cmd.out] THEN
RETURN
ELSE IF connectionType = Remote AND CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IO.PutRope[cmd.out, "Listing search directory(s) ... "];
IF connectionType = Local THEN
LocalCirio.ListSearchDirectory[currentLocalConnection, cmd.out]
ELSE
RemoteCirio.ListSearchDirectory[currentConnection, cmd.out];
IO.PutRope[cmd.out, "done.\n"];
};
ClearDirsProc: Commander.CommandProc ~ {
IF connectionType = Local AND CheckLevel[LIST[CLCConnected], cmd.out] THEN
RETURN
ELSE IF connectionType = Remote AND CheckLevel[LIST[CLCStopped, CLCThreadsAdded, CLCDetailed], cmd.out] THEN
RETURN;
IF connectionType = Local THEN {
clear: PROC = {LocalCirio.ClearSearchDirectory[currentLocalConnection, cmd.out]};
LocalCirio.DoUnderMonitorLock[currentLocalConnection, clear];
}
ELSE
RemoteCirio.ClearSearchDirectory[currentConnection, cmd.out];
IO.PutRope[cmd.out, "done.\n"];
};
ShowSourceProc: Commander.CommandProc ~ {
IF CheckLevel[LIST[CLCDetailed], cmd.out] THEN
RETURN;
StackCirio.ShowSourcePosition[currentStack, cmd.out];
};
ShowFrameProc: Commander.CommandProc ~ {
IF CheckLevel[LIST[CLCDetailed], cmd.out] THEN
RETURN;
IO.PutF[cmd.out, "Showing frame %g for thread %g.\n", IO.card[currentFrame], IO.card[lastDetailed]];
IO.PutF1[cmd.out, "%g\n", IO.rope[StackCirio.ShowCurrentFrame[currentStack, cmd.out]]];
IO.PutF1[cmd.out, "%g\n", IO.rope[StackCirio.GetCurrentFrameBanner[currentStack, cmd.out]]];
};
WalkStackProc: Commander.CommandProc ~ {
ENABLE
Convert.Error => {GOTO punt};
numArgs: CARD ¬ CommanderOps.NumArgs[cmd];
arg: CommandLineCirio.WalkArg;
nextArg: Rope.ROPE ¬ NIL;
actual: INT ¬ 0;
didNum: BOOL ¬ FALSE;
IF CheckLevel[LIST[CLCDetailed], cmd.out] THEN
RETURN;
IO.PutF1[cmd.out, "Walking stack in thread %g.\n", IO.card[lastDetailed]];
FOR i: CARD IN [1..numArgs) DO
nextArg ¬ CommanderOps.NextArgument[cmd];
SELECT TRUE FROM
Rope.Equal[nextArg, "Cooler", FALSE] => arg.dir ¬ Cooler;
Rope.Equal[nextArg, "Cool", FALSE] => arg.dir ¬ Cooler;
Rope.Equal[nextArg, "Co", FALSE] => arg.dir ¬ Cooler;
Rope.Equal[nextArg, "Warmer", FALSE] => arg.dir ¬ Warmer;
Rope.Equal[nextArg, "Warm", FALSE] => arg.dir ¬ Warmer;
Rope.Equal[nextArg, "W", FALSE] => arg.dir ¬ Warmer;
Rope.Equal[nextArg, "Cedar", FALSE] => arg.typ ¬ Cedar;
Rope.Equal[nextArg, "C", FALSE] => arg.typ ¬ C;
ENDCASE => {
arg.num ¬ Convert.IntFromRope[nextArg];
didNum ¬ TRUE;
}
ENDLOOP;
IF NOT didNum AND arg.dir = Absolute THEN
arg.dir ¬ Cooler;
SELECT arg.dir FROM
Warmer => arg.num ¬ -arg.num;
Absolute => arg.num ¬ arg.num - currentFrame;
ENDCASE;
IO.PutF1[cmd.out,"Trying to walk %g ", IO.int[arg.num]];
SELECT arg.typ FROM
Cedar => IO.PutRope[cmd.out, "Cedar "];
C => IO.PutRope[cmd.out, "C "];
ENDCASE;
IO.PutF1[cmd.out,"frames from frame %g\n", IO.card[currentFrame]];
SELECT arg.typ FROM
Cedar => [actual, currentFrame] ¬ StackCirio.WalkStackCedarFrames[currentStack, arg.num, cmd.out];
C => [actual, currentFrame] ¬ StackCirio.WalkStack[currentStack, arg.num, cmd.out];
ENDCASE;
IF actual # 0 THEN {
IO.PutF[cmd.out, "Walked %g frames to frame #%g.\n", IO.int[actual], IO.card[currentFrame]];
IO.PutF1[cmd.out, "%g\n", IO.rope[StackCirio.GetCurrentFrameBanner[currentStack, cmd.out]]];
IO.PutRope[cmd.out, "%g\n", IO.rope[StackCirio.GetBannerForDotOofCurrentFrame[currentStack, cmd.out]]];
};
SetPromptToName[];
EXITS
punt => {
IO.PutRope[cmd.out,
"Usage: WalkStack [[Cooler | Warmer [NumberOfFrames]] | FrameNumber] [C | Cedar]\n"];
};
};
HelpRopes: TYPE ~ REF HelpRopeList ¬ NIL;
HelpRopeList: TYPE ~ RECORD [SEQUENCE length: CARD OF Rope.ROPE];
RemoteHelpMessages: ARRAY ConnectionLevel OF HelpRopes ¬ ALL[NIL];
RemoteHelpMessages[CLCStarted] ¬ NEW[HelpRopeList[5]];
RemoteHelpMessages[CLCStarted][0] ¬ "(Started CommandLineCirio Package)";
RemoteHelpMessages[CLCStarted][1] ¬ "QuitCommandLineCirio";
RemoteHelpMessages[CLCStarted][2] ¬ "ChangeCirioMessageLevel\t[urgent | normal | debug]";
RemoteHelpMessages[CLCStarted][3] ¬ "CirioConnectToWorld\tMachineName [PortNumber [ListOfWorkingDirectories]]";
RemoteHelpMessages[CLCStarted][4] ¬ "WatchFiles\t[ListOfFilePatternsToBeAddedToTheDefaultVersionMap]";
RemoteHelpMessages[CLCConnected] ¬ NEW[HelpRopeList[5]];
RemoteHelpMessages[CLCConnected][0] ¬ "(Connected to world)";
RemoteHelpMessages[CLCConnected][1] ¬ "CirioDisconnectFromWorld";
RemoteHelpMessages[CLCConnected][2] ¬ "FlushUnknownFileCache";
RemoteHelpMessages[CLCConnected][3] ¬ "KillRemoteWorld";
RemoteHelpMessages[CLCConnected][4] ¬ "StopRemoteWorld";
RemoteHelpMessages[CLCStopped] ¬ NEW[HelpRopeList[16]];
RemoteHelpMessages[CLCStopped][0] ¬ "(Remote world stopped)";
RemoteHelpMessages[CLCStopped][1] ¬ "ResumeRemoteWorld";
RemoteHelpMessages[CLCStopped][2] ¬ "ResumeVP0";
RemoteHelpMessages[CLCStopped][3] ¬ "AddDir\tDirectoryName";
RemoteHelpMessages[CLCStopped][4] ¬ "ListDir";
RemoteHelpMessages[CLCStopped][5] ¬ "RemoveDir\tDirectoryName";
RemoteHelpMessages[CLCStopped][6] ¬ "SetBreak\tFullPathOfSourceFile CharacterPositionInFile";
RemoteHelpMessages[CLCStopped][7] ¬ "BreakAtAddress\tAddress";
RemoteHelpMessages[CLCStopped][8] ¬ "ListBreaks";
RemoteHelpMessages[CLCStopped][9] ¬ "ClearBreak\t[# | All | FullPathOfSourceFile CharacterPositionInSourceFile]";
RemoteHelpMessages[CLCStopped][10] ¬ "ToggleBreakStopAll";
RemoteHelpMessages[CLCStopped][11] ¬ "CirioDo\t[expression]";
RemoteHelpMessages[CLCStopped][12] ¬ "RemoteDisassemble\t[CProcName | PC]";
RemoteHelpMessages[CLCStopped][13] ¬ "SetCurrentThread\tThreadID";
RemoteHelpMessages[CLCStopped][14] ¬ "PrintCurrentThread";
RemoteHelpMessages[CLCStopped][15] ¬ "AddThreads\t[All | Ready | CallingDebugger]";
RemoteHelpMessages[CLCThreadsAdded] ¬ NEW[HelpRopeList[9]];
RemoteHelpMessages[CLCThreadsAdded][0] ¬ "(Threads have been added)";
RemoteHelpMessages[CLCThreadsAdded][1] ¬ "ListAvailableThreads";
RemoteHelpMessages[CLCThreadsAdded][2] ¬ "Freeze\t[ThreadID | listed]";
RemoteHelpMessages[CLCThreadsAdded][3] ¬ "Abort\t[ThreadID | listed]";
RemoteHelpMessages[CLCThreadsAdded][4] ¬ "Kill\t[ThreadID | listed]";
RemoteHelpMessages[CLCThreadsAdded][5] ¬ "Proceed\t[ThreadID | listed]";
RemoteHelpMessages[CLCThreadsAdded][6] ¬ "DbxExamine\t[ThreadID]";
RemoteHelpMessages[CLCThreadsAdded][7] ¬ "Summary\t[ThreadID | listed]";
RemoteHelpMessages[CLCThreadsAdded][8] ¬ "Detailed\t[ThreadID]";
RemoteHelpMessages[CLCDetailed] ¬ NEW[HelpRopeList[5]];
RemoteHelpMessages[CLCDetailed][0] ¬ "(A thread has been focused on)";
RemoteHelpMessages[CLCDetailed][1] ¬ "ShowSourcePosition";
RemoteHelpMessages[CLCDetailed][2] ¬ "ShowFrame";
RemoteHelpMessages[CLCDetailed][3] ¬ "WalkStack\t[[Cooler | Warmer [NumberOfFrames]] | FrameNumber] [C | Cedar]";
RemoteHelpMessages[CLCDetailed][4] ¬ "Language\t[Cedar | Machine | C]";
Commander.Register["StartCommandLineCirio", StartComLineProc, "Start the command line cirio package."];
}.