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 ... "]; 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."]; }.  CommandLineCirioImpl.mesa Copyright Ó 1989, 1990, 1991, 1992, 1993 by Xerox Corporation. All rights reserved. Philip James, March 16, 1992 1:21 pm PST Spreitze, December 12, 1991 3:41 pm PST Laurie Horton, September 21, 1992 5:09 pm PDT Udagawa, February 13, 1991 7:58 pm PST Willie-s, March 2, 1993 4:03 pm PST Katsuyuki Komatsu January 23, 1993 4:30 pm PST Rope returned by SystemNames.MachineName if yp isn't running. localhost: Rope.ROPE ¬ "localhost"; Get user supplied and default working directories Try to prevent connecting to ourselves. LocalWorld debugging isn't ready yet?. GOTO punt; threadMapping _ NIL; IF CheckLevel[LIST[CLCStarted, CLCConnected], cmd.out] THEN RETURN; This shouldn't be done [PJames 2/28/92] IF remoteWorldRunning # TRUE THEN { [ , ] _ ResumeRemoteWorldProc[ch]; }; IO.PutRope[cmd.out, "done.\n"]; ThreadInList: PROC [t: CARD, l: LIST OF CARD] RETURNS [BOOLEAN] ~ { FOR index: LIST OF CARD _ l, index.rest WHILE index # NIL DO IF index.first = t THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; PrintList: PROC [l: LIST OF CARD, cmd: Commander.Handle] ~ { FOR index: LIST OF CARD _ l, index.rest WHILE index # NIL DO IO.PutRope[cmd.out, "%g ", IO.card[index.first]]; ENDLOOP; }; FOR index2 _ newThreads, index2.rest WHILE index2 # NIL DO AddThreadMapping[index2.first]; ENDLOOP; threadID _ StackCirio.ResetStack[currentStack, cmd.out]; currentFrame _ 0; IO.PutRope[cmd.out, "done.\n"]; IO.PutRope[cmd.out, "done.\n"]; IO.PutRope[cmd.out, "%g\n", IO.rope[StackCirio.GetBannerForDotOofCurrentFrame[currentStack, cmd.out]]]; Ê<••NewlineDelimiter –"cedarcode" style™codešœ™Kšœ ÏeœH™SKšœ(™(K™'K™-K™&K™#K™.—K˜šÏk œ˜ Kšœžœ ˜Kšœ žœ"˜1Kšœžœ(˜?Kšœ žœ%˜7Kšœ˜KšœžœA˜NKšœ˜KšžœžœMžœ˜^Kšœ žœÒ˜âKšœ žœ˜,Kšžœžœžœ˜HKšœ žœ—˜¨Kšœžœ.žœ ˜GKšœžœ1˜DKšœ žœí˜ýKšœ žœ˜Kšœ žœ˜'K˜—šÏnœžœžœ˜$KšžœQžœžœ:˜²Kšžœ˜K˜Kšœ žœžœ˜-K˜K˜+Kšœžœžœ˜"Kšœ,žœ˜0Kšœžœžœ˜!Kšœžœžœ˜Kšœžœ˜/Kšœ!žœ˜.Kšœ žœ˜Kšœ žœžœ˜Kšœžœžœžœ˜Kšœžœžœ˜Kšœ!žœ˜%Kšœ&žœ˜*Kšœžœ˜Kšœ žœžœ˜K˜-Kšœžœ˜Kšœ žœžœ˜Kšœžœ˜—˜K˜.K˜Kšœžœ˜#K˜Kšœ=™=Kšœžœ˜,K˜šœ žœžœ˜Kšœžœžœ˜Kšœ žœ˜Kšœžœžœ˜Kšœžœžœ˜Kšœžœ˜Kšœžœž˜K˜K˜—Kšœ˜K˜KšŸ œžœ˜KšÐbn œžœ˜Kš  œžœ˜Kš œžœ˜Kš  œžœ˜KšœžœÏb œ¡ œ˜2K˜Kšœžœe˜}K˜šŸ œžœžœ žœ˜Ešžœžœž˜Kšžœžœ˜ —šžœ˜Kšžœ6˜8Kšžœžœ˜K˜—K˜——˜šŸœžœžœ žœ˜Ašžœžœž˜Kšžœžœ˜ —šžœ˜KšžœO˜QKšžœžœ˜K˜—K˜——˜šŸœžœ˜3Kšžœ ˜"K˜——˜šŸœžœ˜Kšœžœžœ˜Kšœžœžœ˜'Kšœžœžœ˜!K˜Kšžœžœžœ˜!˜šžœž˜šžœ ž˜K˜—šž˜K˜——šž˜K˜—K˜šžœ žœžœ˜K˜0K˜/K˜mšžœž˜K˜3K˜;KšžœA˜H—K˜/˜K˜——˜˜ K˜K˜—Kšœ$˜$—K˜—šžœžœžœž˜)K˜—šžœ˜K˜$—K˜——˜šŸ œž œžœžœžœžœžœžœžœžœ˜uK˜(Kšœ žœžœ˜Kšœ žœžœžœ˜Kšœžœ˜š žœžœžœ(žœžœž˜HKšœžœ˜,Kšœžœ˜*šžœž˜Kšœ žœ˜—Kšžœ˜—šžœ žœ˜šžœ žœžœ˜šžœžœ˜šžœž˜K˜šžœ ž˜Kšœžœ9˜@Kšœžœ1˜8Kšœžœ,˜3Kšœžœ1˜8Kšžœ˜—Kšž˜—šžœ˜šžœž˜KšœžœH˜OKšœžœL˜SKšœžœG˜NKšœžœ<˜CKšžœ˜———Kšžœžœ˜ K˜—Kšœ˜—K˜—šŸœ˜+Kšœ-žœ˜1K˜šžœžœžœ˜Kšœ"˜"Kšœ/˜/šžœ/žœ˜7Kšœ˜Kšžœg˜iK˜—Kšœfžœ˜‚Kšœ4˜4Kšœžœ˜"Kšœžœ˜KšœžœÃžœžœžœžœžœžœ!˜ÿKšœžœDžœ˜|˜K˜——K˜K˜šžœžœžœ˜ K˜4—˜K˜ K˜K˜#Kšœžœ˜KšžœG˜IK˜Kšœ,žœ˜1K˜XK˜aK˜dK˜]K˜§K˜yK˜vK˜[K˜OKšœa˜aKšœw˜wKšœ®˜®Kšœ`˜`Kšœf˜fKšœ{˜{Kšœ`˜`K˜dK˜fKšœ“˜“KšœŽ˜ŽKšœT˜TKšœ®˜®Kšœ“˜“K˜`Kšœ™˜™K˜xK˜WK˜MK˜JK˜GK˜PK˜PK˜DK˜aK˜XK˜³Kšœ‰˜‰K˜—K˜—K˜K˜šŸœ˜)Kšœ žœ˜*Kšœžœžœ˜Kšœžœ˜2Kšœžœ%˜<šžœ ž˜K˜—šžœ˜K˜šžœžœžœž˜K˜AKšž˜—K˜—K˜*Kšœ˜K˜—šŸ œžœžœ˜K˜—KšŸœžœžœ˜#K˜šŸœžœžœ˜$K˜K˜—KšŸ œžœ%žœžœ˜C˜Kšœ žœ˜,K˜šžœžœž˜šœžœ˜$šžœžœ˜#Kšžœ5˜7K˜—šžœ˜Kšœ žœ4žœ˜`K˜)Kšœžœ˜!K˜"Kšœ˜—K˜K˜—šœžœ˜%šžœžœžœ˜'Kšžœ1˜3K˜—šžœ˜K˜K˜)Kšœžœ˜"K˜#K˜—K˜K˜—šžœ˜ K˜)Kšœ˜K˜—Kšžœ!˜#—Kšœ˜K˜—šŸ œ˜(Kšœ žœ˜*Kšœ žœ˜šžœ ž˜Kšœ9˜9—šž˜K˜%šžœžœžœ˜-K˜Kšœ˜—šž˜šžœžœžœ˜'K˜šžœžœž˜,Kšœ/˜/Kšž˜—K˜—šž˜Kšžœ:˜<———Kšœ˜—K˜š Ÿ œžœ žœžœ$žœ ˜TKšœ žœžœ˜šžœžœžœž˜$K˜Kšžœ˜—Kšžœ<˜>šžœžœžœž˜&Kšžœ?˜AKšžœ˜—K˜K˜—šŸœ˜*Kšœ-žœ˜1K˜š žœžœžœžœžœ˜EK˜!˜K˜——K˜4K˜Kšœžœ˜K˜K˜K˜K˜K˜Kšœ+žœ˜1Kšœ*žœ˜0Kšœ žœ˜%Kšœžœ˜ Kšœ/žœ˜4Kšœ,žœ˜1Kšœ&žœ˜+Kšœ&žœ˜+Kšœ(žœ˜-Kšœ žœ˜%Kšœ!žœ˜&Kšœ'žœ˜,Kšœ)žœ˜.Kšœžœ˜"Kšœžœ˜#Kšœ žœ˜%Kšœ žœ˜%Kšœžœ˜$Kšœ%žœ˜*Kšœ!žœ˜&Kšœ!žœ˜&Kšœ)žœ˜.Kšœžœ˜#Kšœ(žœ˜-Kšœžœ˜#Kšœ+žœ˜0Kšœžœ˜"Kšœžœ˜!Kšœžœ˜ Kšœžœ˜#Kšœ!žœ˜&Kšœžœ˜$Kšœ)žœ˜.Kšœ žœ˜%Kšœ žœ˜%Kšœžœ˜$K˜K˜gK˜K˜Kšœ˜K˜—šŸ œ˜(Kšžœ`˜bK˜—K˜š Ÿ œžœžœžœžœžœž˜5K˜K˜—šŸœ˜+Kšœžœ™#Kšœžœ˜%Kšœžœžœ˜Kšœžœžœ˜Kšœ žœ˜Kšœ žœ˜)Kš œžœžœžœžœ˜Kš œ žœžœžœžœ˜"Kš œžœžœžœžœžœžœ ˜@K˜šœ˜Kšžœ˜Kšœžœ˜šœ˜Kšœžœžœ˜Kšžœe˜gK˜šžœ žœžœžœžœ žœžœ˜JKšœ/žœ˜6Kšžœ)˜+Kšžœ˜K˜—Kšžœd˜fKšžœ˜ K˜—K˜—K˜šžœ žœ¡ œ ž˜-Kšžœ˜—šžœžœ˜KšžœA˜CKšžœ˜ K˜—šžœžœ˜K˜,šžœžœ$žœžœ˜9KšœVžœ˜rK˜—K˜—šžœž˜K˜?—K˜K™1šžœžœ˜šžœžœžœž˜šžœ žœžœ˜Kšœžœ"˜.K˜Kšœ˜—šžœ˜Kšœžœ"˜6K˜K˜——Kšžœ˜K˜Kšœ˜—šžœ˜K˜ K˜—K˜K™'šžœžœ1žœ%žœ˜‚Kšžœ“˜•Kšžœ˜K˜—Kšžœ+žœ˜Bšžœ&žœžœ˜5Kšœ&™&Kšžœ™ K˜K˜eK˜—šžœ˜K˜˜/K˜K˜Kšœ˜K˜—šžœžœž˜Kšœ@˜@—K˜—š žœžœžœžœžœ˜EKšžœ˜šžœž˜K˜I—šžœ˜K˜KK˜NK˜—Kšœžœ˜K˜Kšœ žœ˜K˜K˜Kšœžœ™K˜K˜Kšœ>˜>K˜—šž˜K˜Kšžœ!˜#K˜—K˜šž˜Kšœ žœi˜tK˜ —K˜—K˜K˜šŸœ˜.šžœ žœ¡œ ž™;Kšžœ™—K˜K˜——˜šŸœžœžœžœ˜2šžœžœ˜Kšœžœ˜#šžœž˜Kšžœ8˜:—šžœ˜Kšžœ8˜:K™'—šžœžœžœ™#K™"K™—šžœž˜K˜6—šž˜K˜=—Kšžœ˜Kšœžœ˜Kšœžœ˜K˜K˜K˜K˜K˜K˜K˜—K˜K˜—šŸœžœ˜Kšœ¡ œ˜K˜K˜—šŸœžœ˜Kšœ¡ œ˜Kšœžœ˜K˜K˜—šŸœžœ˜Kšœ¡œ˜K˜K˜—šŸœžœ˜Kšœ¡ œ˜Kšœ žœ˜K˜K˜—šŸœžœ˜Kšœ¡œ˜Kšœ žœ˜K˜K˜—šŸœžœ˜Kšœ¡ œ˜K˜K˜—šŸœžœ˜Kšœ¡ œ˜Kšœžœ˜K˜K˜K˜—šŸœžœ˜K˜K˜K˜—šŸ œ˜'Kšœ žœ˜*Kšœžœžœ˜Kšœžœžœ˜K˜"K˜K˜šžœ žœ¡ œ ž˜.Kšžœ˜—šžœžœ˜ K˜—šž˜K˜—K˜šžœ žœ˜Kšžœ>˜@Kšžœ˜ K˜K˜—šžœ žœ˜K˜)šžœžœž˜Kšœžœ˜,Kšœžœ˜4Kšœžœ˜8šžœ˜ Kšžœ>˜@Kšžœ˜ K˜——K˜K˜9K˜Kšžœ&˜(šžœž˜Kšœžœ˜!Kšœ žœ˜)Kšœ žœ ˜-Kšžœ˜—K˜—Kšžœ>˜BK˜—K˜šŸœžœ˜2K˜K˜šžœžœ˜ K˜—šž˜K˜—šžœž˜˜ K˜6Kšžœ*˜,K˜K˜—˜K˜˜@šžœžœž˜K˜ Kšžœžœ˜)Kšœžœ˜šžœžœžœžœžœžœžœ˜kK˜Kšœžœ˜ K˜—š žœžœžœžœžœ˜BK˜Kšœ˜—šžœžœžœžœ˜-K˜K˜K˜—šžœ˜šžœžœ˜K˜@—šž˜K˜ —Kšžœžœ˜*K˜—Kšžœ˜—K˜—K˜—K˜šŸ œ˜'šž˜Kšœžœ˜—Kšœžœžœ˜Kšœžœ˜Kšœžœ˜K˜!Kšœ žœžœ˜K˜K˜>Kšœ žœ˜*K˜š žœžœ žœ¡ œ ž˜JKšž˜—š žœžœ žœ¡ œ¡œ¡ œ ž˜PKšžœ˜K˜—šžœ žœ˜Kšžœ[˜]Kšžœ˜ K˜—Kšžœ(˜*K˜+K˜DKšœžœ˜+Kš œ žœžœžœtžœ ˜ÄKšžœžœžœžœ˜'K˜˜Kšœžœ¦˜¯šžœžœ˜ Kšžœ˜K˜:K˜—šž˜K˜—K˜—šžœ%ž˜+Kšžœ˜—šž˜Kšœ žœ\˜g—K˜K˜—šŸœ˜0Kšœ žœžœ˜Kšœžœ˜Kšœžœ˜ K˜Kšœ žœ˜*K˜š žœžœ žœ¡ œ ž˜JKšž˜—š žœžœ žœ¡ œ¡œ¡ œ ž˜PKšžœ˜K˜—šžœ žœ˜Kšžœ6˜8Kšžœ˜ K˜—K˜*šžœC˜JKšœzžœ˜”Kšžœ ˜ —KšœA˜AKšœQ˜QKšžœ˜šž˜Kšœžœ˜ —K˜K˜—šŸœ˜0Kš œ žœžœžœžœžœ˜-Kšœžœ˜K˜Kšœ žœ˜*K˜š žœžœ žœ¡ œ ž˜JKšž˜—š žœžœ žœ¡ œ¡œ¡ œ ž˜PKšžœ˜K˜—šžœ žœ˜KšžœB˜DKšžœ˜ K˜—K˜*Kšžœ&˜(KšœG˜GKšžœ˜K˜K˜—šŸ œ˜(Kšœžœ=˜Gš žœžœ žœ¡ œ ž˜JKšž˜—šžœžœžœ žœ¡ œ¡œ¡ œ ž˜lKšžœ˜—Kšžœ-˜/šžœžœ˜K˜;—šž˜K˜—Kšžœ˜K˜——˜šŸœ˜)šžœ˜Kšœžœ˜—Kšœ žœ˜*Kšœžœžœ˜Kšœ žœ˜Kšœžœ˜#Kšœžœžœ˜Kšœžœ˜Kšœžœ˜K˜>K˜š žœžœ žœ¡ œ ž˜JKšž˜—šžœžœžœ žœ¡ œ¡œ¡ œ ž˜lKšžœ˜—šžœ žœ˜Kšžœi˜kKšžœ˜ K˜K˜—šžœ žœ˜Kšžœ)˜+K˜+K˜DKšœžœ˜+Kšœ žœžœžœtžœ žœžœžœžœ˜ìK˜šžœž˜K˜—šž˜Kš œ žœžœžœžœ˜L—˜Kšœžœs˜}šžœž˜K˜<—šž˜K˜—K˜—K˜—šžœ˜šžœ žœ˜K˜)šžœžœžœ˜+Kšœžœ@˜KKšžœ0˜2šžœž˜Kšœ<˜<—šž˜Kšœ˜—Kšœ˜—šžœ˜K˜(šœ˜KšœžœI˜TKšžœ-žœ˜Bšžœžœ˜Kšœ<˜<—šž˜Kšœ˜——Kšœ˜—K˜—Kšœ˜šžœ˜Kšžœ3˜5šžœž˜K˜—šž˜Kš œ žœžœžœžœ˜L—˜Kšœžœ5˜?šžœž˜K˜<—šž˜K˜——K˜—K˜—˜K˜—Kšžœ™K˜šž˜˜ Kšžœh˜jK˜——K˜K˜K˜—šŸœ˜1š žœ žœ¡ œ¡œ¡ œ ž˜KKšžœ˜—šžœž˜K˜Kšžœ+˜-Kš žœ žœžœžœžœ˜W—šž˜KšœžœI˜L——K˜K˜šŸœ˜.šžœ˜K˜AKšžœ˜ K˜—šžœžœ˜!KšžœL˜NKšžœ˜K˜—šžœ žœ¡ œ ž˜/Kšžœ˜—Kšžœ:˜—Kšžœ˜K˜—K˜šŸ œžœžœžœžœžœžœ ˜=šžœžœžœžœžœ žœžœ˜=K˜Kšžœ˜—˜K˜——šŸ œžœžœžœžœžœžœžœ™Cš žœžœžœžœžœ žœž™<šžœžœ™Kšžœžœ™ —Kšžœ™—Kšžœžœ™K™——˜š Ÿ œžœžœžœžœ™<š žœžœžœžœžœ žœž™—šžœžœžœ˜,Kšœ4¢ œ˜?šžœž˜"K˜—K˜—šžœ˜šžœ˜!šžœ žœžœž˜8Kšœ5¢ œ˜@Kšžœ˜——Kšœžœ ˜K˜—Kšžœ˜—šžœžœ žœž˜8Kšœ5¢ œ˜@Kšžœ˜—K˜K˜—K˜—šžœ"žœ žœž™:Kšœ™Kšžœ™—K˜K˜—šŸœ˜)Kš œ žœžœžœžœ˜Kšœ žœ˜+Kšœ žœ˜*Kšœžœ ˜Kšœžœ ˜Kšœžœ ˜#Kšœžœ˜,Kšœžœ˜$Kšœžœžœ˜+K˜š žœ žœ¡ œ¡œ¡ œ ž˜KKšžœ˜—šžœ ž˜K˜+—šžœ žœžœ˜/Kšžœ-˜/Kšœ žœ(˜8K˜—šžœžœ"žœžœ˜6KšžœC˜EKšœ žœ)˜9K˜—šžœžœ%žœž˜6Kšœ$žœžœ˜2Kšžœ:˜K˜——K˜K˜—šŸœ˜/šžœ˜Kšœžœ˜—Kšœžœ˜Kšœ žœ˜Kšœ žœ˜K˜š žœ žœ¡œ¡ œ ž˜?Kšžœ˜—šžœžœžœ˜Kšžœ,˜.Kšžœ˜K˜—K˜$šžœ ž˜šžœž˜K˜—šžœ˜Kšžœ.˜0Kšž˜K˜——šž˜K˜@—K˜K˜šžœKžœžœžœ˜^Kšžœ0žœ˜BKšžœ˜K˜—šžœ˜Kšžœ-žœ˜?K˜NKšžœ˜K˜—K˜šž˜˜ Kšžœ2˜4K˜——K˜K˜—šŸ œ˜'šžœ˜Kšœžœ˜—Kšœžœ˜Kšœ žœ˜Kšœžœ˜K˜š žœ žœ¡œ¡ œ ž˜?Kšžœ˜—šžœžœžœ˜Kšžœ,˜.Kšžœ˜K˜—K˜$šžœ ž˜šžœž˜K˜—šžœ˜Kšžœ.˜0Kšž˜K˜——šž˜K˜@—K˜K˜šžœKžœžœžœ˜^Kšžœ0žœ˜BKšžœ˜K˜—šžœ˜K˜Kšžœ/žœ˜AK˜WKšžœžœžœ˜+K˜PK™8K˜˜@Kšžœ˜K˜—šžœ˜K˜*Kšžœ4˜6šžœžœ˜K˜K—šž˜K˜H—Kšžœ˜K˜—K˜K˜—šŸ œ˜&š žœžœ žœ¡ œ ž˜JKšž˜—š žœžœžœ žœ¡œ¡ œ ž˜lKšžœ˜—Kšžœ6˜8šžœžœ˜K˜?—šž˜K˜<—Kšžœ™K˜K˜—šŸ œ˜(š žœžœ žœ¡ œ ž˜JKšž˜—š žœžœžœ žœ¡œ¡ œ ž˜lKšžœ˜—šžœžœ˜ KšœžœF˜QK˜=K˜—šž˜K˜=—Kšžœ™K˜K˜—šŸœ˜)šžœ žœ¡ œ ž˜.Kšžœ˜—K˜5K˜K˜—šŸ œ˜(šžœ žœ¡ œ ž˜.Kšžœ˜—Kšžœ4žœžœ˜dKšžœžœ;˜WKšžœžœ@˜\K˜K˜—šŸ œ˜(šžœ˜Kšœžœ˜—Kšœ žœ˜*K˜Kšœžœžœ˜Kšœžœ˜Kšœžœžœ˜K˜šžœ žœ¡ œ ž˜.Kšžœ˜—Kšžœ1žœ˜Jšžœžœžœž˜K˜)šžœžœž˜Kšœžœ˜9Kšœžœ˜7Kšœžœ˜5Kšœžœ˜9Kšœžœ˜7Kšœžœ˜4Kšœžœ˜8Kšœžœ˜4šžœ˜ K˜'Kšœ žœ˜K˜——Kšžœ˜—šžœžœžœž˜)K˜—K˜šžœ ž˜K˜ K˜.Kšžœ˜—K˜Kšžœ%žœ˜8šžœ ž˜Kšœ žœ˜'Kšœžœ˜Kšžœ˜—Kšžœ)žœ˜BK˜šžœ ž˜K˜bK˜SKšžœ˜—šžœ žœ˜Kšžœ3žœžœ˜\Kšžœžœ@˜\KšžœžœI™gK˜—K˜šž˜˜ šžœ˜K˜V—K˜——K˜—K˜Kšœ žœžœžœ˜)Kš œžœžœžœ žœžœžœ˜AKš Ÿœžœžœ žœžœ˜BK˜Kšœ!žœ˜6K˜IK˜;K˜YK˜oK˜fK˜Kšœ¡ œžœ˜8Kšœ¡ œ˜=Kšœ¡ œ"˜AKšœ¡ œ˜>Kšœ¡ œ˜8Kšœ¡ œ˜8K˜Kšœ¡ œžœ˜7Kšœ¡ œ ˜=Kšœ¡ œ˜8Kšœ¡ œ˜0Kšœ¡ œ˜Kšœ¡ œ˜1Kšœ¡ œT˜qKšœ¡ œ˜:Kšœ¡ œ ˜=Kšœ¡ œ.˜KKšœ¡ œ%˜BKšœ¡ œ˜:Kšœ¡ œ6˜SK˜Kšœ¡œžœ˜;Kšœ¡œ#˜EKšœ¡œ˜@Kšœ¡œ%˜GKšœ¡œ$˜FKšœ¡œ#˜EKšœ¡œ&˜HKšœ¡œ ˜BKšœ¡œ&˜HKšœ¡œ˜@K˜Kšœ¡ œžœ˜7Kšœ¡ œ(˜FKšœ¡ œ˜:Kšœ¡ œ˜1Kšœ¡ œS˜qKšœ¡ œ)˜GK˜K˜gK˜—K˜—…—ÛLû