CommandLineDriver.mesa
Copyright Ó 1989, 1990, 1992 by Xerox Corporation. All rights reserved.
Philip James, January 14, 1991 3:20 pm PST
Spreitze, December 12, 1991 3:25 pm PST
Laurie Horton, November 28, 1990 5:59 pm PST
Udagawa, February 12, 1991 8:48 pm PST
Willie-s, May 15, 1992 2:48 pm PDT
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;
This needs to be here so that the PopUpDriver gets the handle for the commander that it should output to AFTER the handle has been established, not before, SO DON'T MOVE THIS:
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];
so that variables beginning with command names can be printed.
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 = {
No LocalCirio.Abort - is this a valid option in a local world?
};
ProceedAction: PROC = {
No LocalCirio.Proceed - is this a valid option in a local world?
};
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]]];
IO.PutF[ch.out, "%g\n", IO.rope[StackCirio.GetBannerForDotOofCurrentFrame[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"];
};
}.