<> <> 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: PROCESS _ FORK 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: BOOL _ TRUE] RETURNS [commandProc: Commander.CommandProc] = { cmdStream: IO.STREAM _ IO.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 [BOOL _ FALSE] = {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 Commander.Lookup[cmd.command].proc # NIL THEN RETURN; IF Rope.Find[cmd.command, ".cm", 0, FALSE] = -1 THEN RETURN; <> 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.STREAM _ IO.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 = { <> 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