InitialCommandsB.mesa
Last editted: April 22, 1983 10:05 am by L. Stewart
DIRECTORY
Commander,
CommandTool USING [EachCommand],
FileIO USING [Open, OpenFailed],
IO,
List,
Process USING [Detach],
ReadEvalPrint,
Rope,
RTProcess,
SafeStorage,
ShowTime,
System,
UECP USING [Argv, Parse],
ViewerIO USING [CreateViewerStreams];
InitialCommandsB: CEDAR MONITOR
IMPORTS Commander, CommandTool, FileIO, IO, List, Process, ReadEvalPrint, Rope, RTProcess, SafeStorage, ShowTime, System, UECP, ViewerIO =
BEGIN
Time: Commander.CommandProc = {
startTime: System.Pulses ← System.GetClockPulses[];
stopTime: System.Pulses;
seconds, microseconds: LONG CARDINAL;
[] ← Shift[cmd];
stopTime ← System.GetClockPulses[];
microseconds ← System.PulsesToMicroseconds[[stopTime - startTime]];
seconds ← microseconds/1000000;
microseconds ← microseconds - (seconds*1000000);
cmd.out.PutF["Running time: %r.%06d\n", IO.card[seconds], IO.card[microseconds]];
};
Detach: ENTRY Commander.CommandProc = {
process: PROCESSFORK DetachInternal[cmd];
cmd.out.PutF["Detaching process: %bB\n", IO.card[LOOPHOLE[process, CARDINAL]]];
TRUSTED { Process.Detach[process]; };
};
DetachInternal: Commander.CommandProc = {
commandProc: Commander.CommandProc;
GetLockTemp: ENTRY PROC = { NULL; };
GetLockTemp[];
commandProc ← Shift[cmd, FALSE];
IF commandProc# NIL THEN {
[in: cmd.in, out: cmd.out] ← ViewerIO.CreateViewerStreams[name: cmd.command];
commandProc[cmd];
};
};
Shift: PROC [cmd: Commander.Handle, call: BOOLTRUE] RETURNS [commandProc: Commander.CommandProc] = {
cmdStream: IO.STREAMIO.RIS[cmd.commandLine];
cmd.command ← cmdStream.GetToken[];
cmdStream.Close[];
IF cmd.command.Length[] = 0 THEN RETURN;
commandProc ← Commander.Lookup[cmd.command].proc;
cmd.commandLine ← Rope.Substr[base: cmd.commandLine, start: Rope.Find[s1: cmd.commandLine, s2: cmd.command] + cmd.command.Length[]];
IF call AND commandProc # NIL THEN commandProc[cmd];
};
statBeforeRef: REF Commander.ProcCell ← NEW[Commander.ProcCell ← [StatBefore]];
statAfterRef: REF Commander.ProcCell ← NEW[Commander.ProcCell ← [StatAfter]];
cmdfileFindRef: REF Commander.ProcCell ← NEW[Commander.ProcCell ← [CmdFileFind]];
StatDataObject: TYPE = RECORD [
cmd: Commander.Handle ← NIL,
startTime: ShowTime.Microseconds,
startFaults: INT,
startWords: INT
];
MaxStats: NAT = 10;
StatArray: TYPE = RECORD [
a: SEQUENCE length: [0..MaxStats+1) OF StatDataObject
];
stats: REF StatArray ← NEW[StatArray[MaxStats]];
StatBefore: ENTRY Commander.CommandProc = {
FOR i: NAT IN [0..MaxStats) DO
IF stats.a[i].cmd = NIL THEN TRUSTED {
stats.a[i] ← [
cmd: cmd,
startTime: ShowTime.GetMark[],
startFaults: RTProcess.GetTotalPageFaults[],
startWords: SafeStorage.NWordsAllocated[]
];
EXIT;
};
ENDLOOP;
};
StatAfter: ENTRY Commander.CommandProc = {
Put: PROC [char: CHAR] RETURNS [BOOLFALSE] = {cmd.out.PutChar[char]};
FOR i: NAT IN [0..MaxStats) DO
IF stats.a[i].cmd = cmd THEN {
nw: INT;
nf: INT;
nw ← SafeStorage.NWordsAllocated[] - stats.a[i].startWords;
cmd.out.PutF[" {"];
ShowTime.Show[from: stats.a[i].startTime, p: Put, places: 2];
cmd.out.PutRope[" seconds"];
IF nw > 0 AND nw < 10000000 THEN cmd.out.PutF[", %d words", IO.int[nw]];
TRUSTED {nf ← RTProcess.GetTotalPageFaults[] - stats.a[i].startFaults};
IF nf > 0 AND nf < 10000000 THEN cmd.out.PutF[", %d page faults", IO.int[nf]];
cmd.out.PutRope["}\n"];
stats.a[i].cmd ← NIL;
EXIT;
};
ENDLOOP;
};
Statistics: Commander.CommandProc = {
rb: REF ANY ← Commander.GetProperty[key: $Before, aList: cmd.propertyList];
ra: REF ANY ← Commander.GetProperty[key: $After, aList: cmd.propertyList];
rbl, ral: LIST OF REF ANY;
beforeOK, afterOK: BOOL;
IF rb # NIL AND ISTYPE[rb, LIST OF REF ANY] THEN rbl ← NARROW[rb];
IF ra # NIL AND ISTYPE[ra, LIST OF REF ANY] THEN ral ← NARROW[ra];
beforeOK ← rbl # NIL AND List.Memb[ref: statBeforeRef, list: rbl];
afterOK ← ral # NIL AND List.Memb[ref: statAfterRef, list: ral];
SELECT TRUE FROM
afterOK AND beforeOK => {
[] ← Commander.PutProperty[key: $Before, val: List.Remove[ref: statBeforeRef, list: rbl], aList: cmd.propertyList];
[] ← Commander.PutProperty[key: $After, val: List.Remove[ref: statAfterRef, list: ral], aList: cmd.propertyList];
cmd.out.PutRope["Statistics OFF\n"];
};
NOT afterOK AND NOT beforeOK => {
[] ← Commander.PutProperty[key: $Before, val: List.Cons[ref: statBeforeRef, list: rbl], aList: cmd.propertyList];
[] ← Commander.PutProperty[key: $After, val: List.Cons[ref: statAfterRef, list: ral], aList: cmd.propertyList];
cmd.out.PutRope["Statistics ON\n"];
};
ENDCASE => cmd.out.PutRope["Statistics Confusion\n"];
};
AutoCommandFile: Commander.CommandProc = {
rp: REF ANY ← Commander.GetProperty[key: $PreLookup, aList: cmd.propertyList];
rpl: LIST OF REF ANY;
ok: BOOL;
IF rp # NIL AND ISTYPE[rp, LIST OF REF ANY] THEN rpl ← NARROW[rp];
ok ← rpl # NIL AND List.Memb[ref: cmdfileFindRef, list: rpl];
IF ok THEN {
[] ← Commander.PutProperty[key: $PreLookup, val: List.Remove[ref: cmdfileFindRef, list: rpl], aList: cmd.propertyList];
cmd.out.PutRope["Auto Command Files OFF\n"];
}
ELSE {
[] ← Commander.PutProperty[key: $PreLookup, val: List.Cons[ref: cmdfileFindRef, list: rpl], aList: cmd.propertyList];
cmd.out.PutRope["Auto Command Files ON\n"];
};
};
CmdFileFind: Commander.CommandProc = {
if the command is in the registry then return
IF Commander.Lookup[cmd.command].proc # NIL THEN RETURN;
IF Rope.Find[cmd.command, ".cm", 0, FALSE] = -1 THEN RETURN;
try it as a command file
cmd.commandLine ← Rope.Cat[cmd.command, " ", cmd.commandLine];
cmd.command ← "@";
};
MyClientProc: ReadEvalPrint.ClientProc = {
newCommand: Rope.ROPE;
cmd: Commander.Handle ← NARROW[h.clientData];
argv: UECP.Argv ← NARROW[Commander.GetProperty[key: $OriginalArgs, aList: cmd.propertyList]];
state: {normal, haveDollar} ← normal;
char: CHAR;
ncs: IO.STREAMIO.ROS[];
FOR i: INT IN [0..command.Length) DO
char ← command.Fetch[i];
SELECT state FROM
normal => {
IF char = '$ THEN state ← haveDollar
ELSE ncs.PutChar[char];
};
haveDollar => {
IF char IN ['0..'9] AND ((char - '0) + 1) <= argv.argc THEN ncs.PutRope[argv[(char - '0) + 1]]
ELSE {
ncs.PutChar['$];
ncs.PutChar[char];
};
state ← normal;
};
ENDCASE => ERROR;
ENDLOOP;
IF state = haveDollar THEN ncs.PutChar['$];
newCommand ← ncs.GetOutputStreamRope[];
h.out.PutRope[newCommand];
RETURN[CommandTool.EachCommand[h, newCommand]];
};
CommandFile: Commander.CommandProc = {
argv: UECP.Argv ← UECP.Parse[cmd.commandLine];
commandStream: IO.STREAM;
h: ReadEvalPrint.Handle;
prompt: Rope.ROPE;
IF argv.argc < 2 THEN {
cmd.out.PutF["Commandfile usage: @Commandfilename\n"];
RETURN;
};
argv[0] ← cmd.command;
commandStream ← FileIO.Open[fileName: argv[1] ! FileIO.OpenFailed => {
cmd.out.PutF["\tCannot open %g\n", IO.rope[argv[1]]];
GOTO Error;
}];
WHILE NOT commandStream.EndOf[] DO
c: CHAR ← commandStream.GetChar[];
IF c = 0C OR c >= 200C THEN {
cmd.err.PutF["%g appears to be a binary file\n", IO.rope[argv[1]]];
commandStream.Close[];
GOTO Error;
};
ENDLOOP;
commandStream.SetIndex[0];
prompt ← NARROW[Commander.GetProperty[key: "prompt", aList: cmd.propertyList] ! ANY => {
prompt ← "%% ";
CONTINUE;
}];
cmd.propertyList ← Commander.PutProperty[key: $OriginalArgs, val: argv, aList: cmd.propertyList];
h ← ReadEvalPrint.CreateStreamEvaluator[clientProc: MyClientProc, prompt: prompt, in: commandStream, out: cmd.out, deliverWhen: ReadEvalPrint.IsACR, clientData: cmd];
ReadEvalPrint.MainLoop[h, FALSE];
cmd.propertyList ← Commander.PutProperty[key: $OriginalArgs, val: NIL, aList: cmd.propertyList];
commandStream.Close[];
EXITS
Error => NULL;
};
RegCm: Commander.CommandProc = {
Register the given name as a command file
argv: UECP.Argv ← UECP.Parse[cmd.commandLine];
doc: Rope.ROPE;
IF argv.argc < 2 THEN {
cmd.out.PutF["RegCm usage: RegCm commandFileName {documentation rope}\n"];
RETURN;
};
doc ← IF argv.argc > 2 THEN argv[2] ELSE "Command file";
Commander.Register[key: argv[1], proc: CommandFileByName, doc: doc];
};
CommandFileByName: Commander.CommandProc = {
cmd.commandLine ← Rope.Cat[cmd.command, ".cm ", cmd.commandLine];
cmd.command ← "@";
CommandFile[cmd];
};
Echo: Commander.CommandProc = {
cmd.out.PutRope[cmd.commandLine];
};
Init: PROC = {
Commander.Register[key: "Time", proc: Time, doc: "Time commandline - print running time of a command"];
Commander.Register[key: "Statistics", proc: Statistics, doc: "Turn statistics printing on or off"];
Commander.Register[key: "Detach", proc: Detach, doc: "Detach commandline - create a new viewer for a command"];
Commander.Register[key: "@", proc: CommandFile, doc: "Execute commands from a file"];
Commander.Register[key: "AutoCommandFiles", proc: AutoCommandFile, doc: "Automatically look for a command file if a command ends in .cm"];
Commander.Register[key: "RegCm", proc: RegCm, doc: "Register a command file"];
Commander.Register[key: "Echo", proc: Echo, doc: "Print command line"];
};
Init[];
END.
April 4, 1983 4:42 pm, Stewart, Created
April 20, 1983 7:10 pm, Stewart, add commandfile arguments and auto commandfiles