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[];
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
};
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"];
};
}.