<<>> <> <> <> <> <> <> <> DIRECTORY CirioBackstop USING[Protect], Commander USING[CommandProc, Handle], CommandLineCirio, Convert USING [Error, IntFromRope], IO, LocalCirio USING[AddSearchDirectory, Connection, DoUnderMonitorLock, FlushUnknownFileCache, GetConnection, GetDummyStack, GetStackForSelf, ListSearchDirectory, RemoveSearchDirectory], PFS USING[Error, FileInfo, PATH, PathFromRope], Rope USING[Concat, Equal, Find, Index, IsEmpty, Length, Substr, ROPE], SourceFileOps, StackCirio USING[ClearAllBreakPoints, ClearBreakPoint, ClearIthBreakPoint, FormatPrompt, GetBannerForDotOofCurrentFrame, GetCurrentFrameBanner, ShowSourcePosition, InterpretTextLine, Language, ListBreakPoints, ReportDesiredLanguage, SetBreakPointAtPosition, SetDesiredLanguage, ShowCurrentFrame, ShowQuickSummary, Stack, WalkStack, WalkStackCedarFrames]; CommandLineDriver: CEDAR MONITOR IMPORTS CirioBackstop, CommandLineCirio, Convert, IO, LocalCirio, PFS, Rope, StackCirio EXPORTS = { connection: LocalCirio.Connection ¬ NIL; ch: PRIVATE Commander.Handle; stack: StackCirio.Stack ¬ NIL; dummyStack: StackCirio.Stack ¬ NIL; currentFrame: CARD ¬ 0; currentLanguage: StackCirio.Language ¬ Cedar; CommandType: TYPE = {help, adddir, listdir, removedir, setbreak, listbreak, clearbreak, flush, summary, abort, language, proceed, showsource, showframe, walkstack, exit, interpret, interpret2, notunique}; BreakPointPopUp: PUBLIC PROCEDURE [key: CARD32] = { Protected: PROC RETURNS [Rope.ROPE] ~ { connection ¬ LocalCirio.GetConnection[["CommandLineDriver", "BreakPointPopUp"], ch.out]; stack ¬ LocalCirio.GetStackForSelf[connection, ch.out]; dummyStack ¬ LocalCirio.GetDummyStack[connection, ch.out]; IO.PutF1[ch.out, "\n\nCirio Of %g\N", IO.rope[StackCirio.GetBannerForDotOofCurrentFrame[stack, ch.out]]]; IO.PutRope[ch.out, "CirioHelp for list of Commands\n"]; MainLoop[]; RETURN [NIL]}; err: Rope.ROPE ¬ NIL; <> ch ¬ CommandLineCirio.ch; currentLanguage ¬ Cedar; currentFrame ¬ 0; err ¬ CirioBackstop.Protect[Protected, ch.out]; IF err#NIL THEN ch.out.PutF1["%g\n", [rope[err]] ]; }; CheckCommand: PROC [tryC, oldC: CommandType ] RETURNS [newC: CommandType] = { IF (oldC # interpret) OR (oldC = notunique) THEN newC ¬ notunique ELSE newC ¬ tryC; }; ParseLine: PROC [line: Rope.ROPE] RETURNS [command: CommandType ¬ interpret, args: Rope.ROPE] = { len, firstSpace: INT ¬ 0; cmdRope: Rope.ROPE ¬ NIL; len ¬ Rope.Length[line]; firstSpace ¬ Rope.Index[line, , " ", FALSE]; IF firstSpace = len THEN { cmdRope ¬ line; args ¬ NIL; } ELSE { cmdRope ¬ Rope.Substr[line, , firstSpace]; args ¬ Rope.Substr[line, firstSpace+1, len-firstSpace-1]; }; IF (Rope.Find["AddDir", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[adddir, command]; IF (Rope.Find["ListDir", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[listdir, command]; IF (Rope.Find["SetBreak", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[setbreak, command]; IF (Rope.Find["ListBreaks", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[listbreak, command]; IF (Rope.Find["ClearBreaks", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[clearbreak, command]; IF (Rope.Find["CirioHelp", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[help, command]; IF (Rope.Find["FlushUnknownFileCache", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[flush, command]; IF (Rope.Find["Quick", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[summary, command]; IF (Rope.Find["Summary", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[summary, command]; IF (Rope.Find["Abort", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[abort, command]; IF (Rope.Find["Proceed", cmdRope,, FALSE] = 0) THEN command ¬ CheckCommand[proceed, command]; IF (Rope.Find["RemoveDir", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[removedir, command]; IF (Rope.Find["Language", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[language, command]; IF (Rope.Find["ShowSourcePosition", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[showsource, command]; IF (Rope.Find["ShowFrame", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[showframe, command]; IF (Rope.Find["WalkStack", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[walkstack, command]; IF (Rope.Find["Exit", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[exit, command]; IF (Rope.Find["QuitLocalCirio", cmdRope, , FALSE] = 0) THEN command ¬ CheckCommand[exit, command]; <> IF (Rope.Equal["I", cmdRope, FALSE]) THEN command ¬ interpret2; IF command = interpret THEN args ¬ line; }; HelpAction: PROC = { IO.PutRope[ch.out, "\n Local Cirio Commands\n\nAddDir\nListDir\nRemoveDir\nSetBreak\nListBreaks\nClearBreaks\nFlushUnknownFileCache\nQuick\nSummary\nAbort\nAbort\nProceed\nRemoveDir\nLanguage\nShowSourcePosition\nShowFrame\nWalkStack\nExit\nexpression\nI expression (forced interpret)\n\n"]; }; MainLoop: PROC = { done: BOOL ¬ FALSE; line, args: Rope.ROPE ¬ NIL; cmd: CommandType; commandNum: CARD ¬ 1; stackToUse: StackCirio.Stack; prompt: Rope.ROPE ¬ NIL; WHILE NOT done DO stackToUse ¬ IF stack # NIL THEN stack ELSE dummyStack; prompt ¬ StackCirio.FormatPrompt[stackToUse, commandNum]; IO.PutF[ch.out, "LocalWorld (Frame: %g) %g", IO.card[currentFrame], IO.rope[prompt]]; line ¬ IO.GetLineRope[ch.in]; IF NOT Rope.IsEmpty[line] AND NOT Rope.Equal[line, "\n", FALSE] THEN { [cmd, args] ¬ ParseLine[line]; SELECT cmd FROM notunique => {IO.PutRope[ch.out, "Command is not unique.\n"]}; interpret => { InterpAction[prompt.Concat[args]]; commandNum ¬ commandNum + 1}; interpret2 => { InterpAction[prompt.Concat[args]]; commandNum ¬ commandNum + 1}; adddir => {AddDirAction[args]}; removedir => {RemoveDirAction[args]}; listdir => {ListDirAction}; setbreak => {SetBreakAction[args]}; listbreak => {ListBreakAction}; help => {HelpAction}; language => {LanguageAction[args]}; clearbreak => {ClearBreakAction[args]}; flush => {FlushUFCAction[]}; summary => {SummaryAction[]}; abort => {AbortAction[]}; showsource => {ShowSourceAction[]}; showframe => {ShowFrameAction[]}; walkstack => {WalkStackAction[args]}; proceed => {ProceedAction[]}; exit => {done ¬ TRUE}; ENDCASE => {}; }; ENDLOOP; currentFrame ¬ 0; }; InterpAction: PROC [args: Rope.ROPE] = { reslt: Rope.ROPE ¬ NIL; interpret: PROC = {reslt ¬ StackCirio.InterpretTextLine[stack, args, ch.out]}; LocalCirio.DoUnderMonitorLock[connection, interpret]; IO.PutF1[ch.out, "%g\n", IO.rope[reslt]]; }; AddDirAction: PROC [args: Rope.ROPE] = { dir: Rope.ROPE ¬ NIL; [dir, args] ¬ GetNextArg[args]; IO.PutRope[ch.out, "Adding search directory ... "]; LocalCirio.AddSearchDirectory[connection, dir, ch.out]; IO.PutRope[ch.out, "done.\n"]; }; RemoveDirAction: PROC [args: Rope.ROPE] = { dir: Rope.ROPE ¬ NIL; [dir, args] ¬ GetNextArg[args]; IO.PutRope[ch.out, "Removing search directory ... "]; LocalCirio.RemoveSearchDirectory[connection, dir, ch.out]; IO.PutRope[ch.out, "done.\n"]; }; LanguageAction: PROC [args: Rope.ROPE] = { lang: Rope.ROPE ¬ NIL; [lang, args] ¬ GetNextArg[args]; SELECT TRUE FROM Rope.Equal[lang, "Machine", FALSE] => { StackCirio.SetDesiredLanguage[stack, Machine, ch.out]; currentLanguage ¬ Machine; }; Rope.Equal[lang, "C", FALSE] => { StackCirio.SetDesiredLanguage[stack, C, ch.out]; currentLanguage ¬ C; }; Rope.Equal[lang, "Cedar", FALSE] => { StackCirio.SetDesiredLanguage[stack, Cedar, ch.out]; currentLanguage ¬ Cedar; }; (lang = NIL) => { [] ¬ StackCirio.ReportDesiredLanguage[stack, ch.out]; RETURN []; }; ENDCASE => { IO.PutRope[ch.out, "Usage: Language [C|Cedar]\n"]; RETURN []; }; IO.PutF1[ch.out, "Language is now %g.\n", IO.rope[lang]]; }; ListDirAction: PROC = { IO.PutRope[ch.out, "Listing directories ... "]; LocalCirio.ListSearchDirectory[connection, ch.out]; IO.PutRope[ch.out, "done.\n"]; }; ClearBreakAction: PROC [args: Rope.ROPE] = { ENABLE Convert.Error => {GOTO punt}; arg1: Rope.ROPE ¬ NIL; breakNum: INT ¬ 0; [arg1, args] ¬ GetNextArg[args]; IF Rope.Equal[arg1, "All", FALSE] THEN { clear: PROC = {StackCirio.ClearAllBreakPoints[dummyStack, ch.out]}; IO.PutRope[ch.out, "Clearing all breaks ... "]; LocalCirio.DoUnderMonitorLock[connection, clear]; } ELSE IF arg1 = NIL THEN { clear: PROC = {StackCirio.ClearBreakPoint[stack, ch.out]}; IO.PutRope[ch.out, "Clearing break ... "]; LocalCirio.DoUnderMonitorLock[connection, clear]; } ELSE { breakNum ¬ Convert.IntFromRope[arg1]; { clear: PROC = {StackCirio.ClearIthBreakPoint[dummyStack, breakNum, ch.out]}; IO.PutF1[ch.out, "Clearing break #%g ... ", IO.int[breakNum]]; LocalCirio.DoUnderMonitorLock[connection, clear]; }; }; IO.PutRope[ch.out, "done.\n"]; EXITS punt => { IO.PutRope[ch.out, "Usage: ClearBreak [#|All]\n"]; }; }; ListBreakAction: PROC = { list:PROC = {StackCirio.ListBreakPoints[dummyStack, ch.out]}; IO.PutRope[ch.out, "Listing breaks ... "]; LocalCirio.DoUnderMonitorLock[connection, list]; IO.PutRope[ch.out, "done.\n"]; }; FlushUFCAction: PROC = { IO.PutRope[ch.out, "Flushing unknown file cache ..."]; LocalCirio.FlushUnknownFileCache[connection, ch.out]; IO.PutRope[ch.out, " done flushing.\n"]; }; SummaryAction: PROC = { stopFlag: REF BOOL ¬ NEW[BOOL ¬ FALSE]; show: PROC = {StackCirio.ShowQuickSummary[stack, stopFlag, ch.out, TRUE]}; LocalCirio.DoUnderMonitorLock[connection, show]; }; AbortAction: PROC = { <> }; ProceedAction: PROC = { <> }; ShowSourceAction: PROC = { StackCirio.ShowSourcePosition[stack, ch.out]; IO.PutRope[ch.out, "\n"]; }; ShowFrameAction: PROC = { IO.PutF1[ch.out, "%g\n", IO.rope[StackCirio.ShowCurrentFrame[stack, ch.out]]]; IO.PutF1[ch.out, "%g\n", IO.rope[StackCirio.GetCurrentFrameBanner[stack, ch.out]]]; }; WalkStackAction: PROC [args: Rope.ROPE] = { ENABLE Convert.Error => {GOTO punt}; arg: ARRAY[1..3] OF Rope.ROPE ¬ ALL[NIL]; numArgs: INT ¬ 3; dirArgs: CommandLineCirio.WalkArg; actual: INT ¬ 0; didNum: BOOL ¬ FALSE; [arg[1], args] ¬ GetNextArg[args]; [arg[2], args] ¬ GetNextArg[args]; [arg[3], args] ¬ GetNextArg[args]; IF arg[3] = NIL THEN numArgs ¬ 2; IF arg[2] = NIL THEN numArgs ¬ 1; IF arg[1] = NIL THEN numArgs ¬ 0; FOR i: CARD IN [1..numArgs] DO SELECT TRUE FROM Rope.Equal[arg[i], "Cooler", FALSE] => dirArgs.dir ¬ Cooler; Rope.Equal[arg[i], "Warmer", FALSE] => dirArgs.dir ¬ Warmer; Rope.Equal[arg[i], "Cedar", FALSE] => dirArgs.typ ¬ Cedar; Rope.Equal[arg[i], "C", FALSE] => dirArgs.typ ¬ C; ENDCASE => { dirArgs.num ¬ Convert.IntFromRope[arg[i]]; didNum ¬ TRUE; } ENDLOOP; IF NOT didNum AND dirArgs.dir = Absolute THEN dirArgs.dir ¬ Cooler; SELECT dirArgs.dir FROM Warmer => dirArgs.num ¬ -dirArgs.num; Absolute => dirArgs.num ¬ dirArgs.num - currentFrame; ENDCASE; IO.PutF1[ch.out,"Trying to walk %g ", IO.int[dirArgs.num]]; SELECT dirArgs.typ FROM Cedar => IO.PutRope[ch.out, "Cedar "]; C => IO.PutRope[ch.out, "C "]; ENDCASE; IO.PutF1[ch.out,"frames from frame %g\n", IO.card[currentFrame]]; SELECT dirArgs.typ FROM Cedar => { walk: PROC = {[actual, currentFrame] ¬ StackCirio.WalkStackCedarFrames[stack, dirArgs.num, ch.out]}; LocalCirio.DoUnderMonitorLock[connection, walk]; }; C => { walk: PROC = {[actual, currentFrame] ¬ StackCirio.WalkStack[stack, dirArgs.num, ch.out]}; LocalCirio.DoUnderMonitorLock[connection, walk]; }; ENDCASE; IF actual # 0 THEN { IO.PutF[ch.out, "Walked %g frames to frame #%g.\n", IO.int[actual], IO.card[currentFrame]]; IO.PutF1[ch.out, "%g\n", IO.rope[StackCirio.GetCurrentFrameBanner[stack, ch.out]]]; <> }; EXITS punt => { IO.PutRope[ch.out, "Usage: WalkStack [[Cooler|Warmer [NumberOfFrames]] | FrameNumber] [C|Cedar]\n"]; }; }; GetNextArg: PROC [args: Rope.ROPE] RETURNS [nextArg, newArgs: Rope.ROPE ¬ NIL] = { len, firstSpace: INT ¬ 0; len ¬ Rope.Length[args]; IF len = 0 THEN RETURN [NIL, NIL]; firstSpace ¬ Rope.Index[args, , " ", FALSE]; IF firstSpace = len THEN { nextArg ¬ args; newArgs ¬ NIL; } ELSE { nextArg ¬ Rope.Substr[args, , firstSpace]; newArgs ¬ Rope.Substr[args, firstSpace+1, len-firstSpace-1]; }; << IO.PutF[ch.out, "\nGetNextArg: \n In: %g\n Out: %g, %g\n", IO.rope[args], IO.rope[nextArg], IO.rope[newArgs]]; >> }; SetBreakAction: PROC [args: Rope.ROPE] ~ { ENABLE Convert.Error => {GOTO Punt}; mesaFileName: PFS.PATH; mesaFileN: Rope.ROPE; sourcePosRope: Rope.ROPE; mesaSourcePos: INT; breakPos: SourceFileOps.Position; stopAll: BOOLEAN ¬ FALSE; uniqueID: SourceFileOps.UniqueID ¬ SourceFileOps.nullUniqueID; [mesaFileN, args] ¬ GetNextArg[args]; [sourcePosRope, args] ¬ GetNextArg[args]; IF (mesaFileN = NIL) OR (sourcePosRope = NIL) THEN { IO.PutRope[ch.out, "Usage: SetBreak FileName SourcePosition\n"]; RETURN[]; }; mesaSourcePos ¬ Convert.IntFromRope[sourcePosRope]; mesaFileName ¬ PFS.PathFromRope[mesaFileN]; uniqueID ¬ PFS.FileInfo[mesaFileName !PFS.Error => {ch.out.PutF["PFS.FileInfo[%g] => PFS.Error[%g, %g]", [rope[mesaFileN]], [atom[error.code]], [rope[error.explanation]] ]; CONTINUE}].uniqueID; IF uniqueID = SourceFileOps.nullUniqueID THEN RETURN[]; IO.PutRope[ch.out, "Setting break ... "]; { set: PROC = {breakPos ¬ StackCirio.SetBreakPointAtPosition[dummyStack, [mesaFileName, uniqueID, [char: [mesaSourcePos] ]], ch.out, stopAll]}; LocalCirio.DoUnderMonitorLock[connection, set] }; IF breakPos # SourceFileOps.noPosition THEN IO.PutRope[ch.out, "done.\n"]; EXITS Punt => {IO.PutRope[ch.out, "Usage: SetBreak FileName SourcePosition\n"]}; }; ListBreakProc: Commander.CommandProc ~ { list: PROC = { StackCirio.ListBreakPoints[dummyStack, ch.out]}; IO.PutRope[ch.out, "Listing break(s) ... "]; LocalCirio.DoUnderMonitorLock[connection, list]; IO.PutRope[ch.out, "done.\n"]; }; }.