<<>> <> <> <> <> <> <> <> <> 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"; <> 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 ~ { <> 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 and 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]]; <> 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; }; <> 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 and and try again.\n\n"]; RETURN; }; IO.PutF1[cmd.out, "Connecting to %g ... \n", IO.rope[remoteName]]; IF Rope.Equal["LocalWorld", remoteName, FALSE] THEN { <> <> 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; <> 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 ~ { <> <> 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 ... "]; <> <> <<[ , ] _ 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[]; } } } <> 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; }; <> <> <> <> <> <> <<};>> <> <> <> <> <<};>> 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; }; }; <> <> <> }; 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]; <> currentFrame ¬ StackCirio.ResetStack[currentStack, cmd.out]; IO.PutRope[cmd.out, "done.\n"]; SetCurrentThreadProcInner[lastDetailed]; LevelThreeToLevelFour[]; <> 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]; <> }; 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]; <> }; 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]]]; <> }; 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."]; }.