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;
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;
}
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]
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]
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]
}
};
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"]
};
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]
IO.PutRope[cmd.out, "done.\n"];
};
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."];
}.