DIRECTORY BasicTime USING [FromPupTime, GetClockPulses, GMT, Now, Period, Pulses, PulsesToMicroseconds, PulsesToSeconds], Booting USING [Boot, Checkpoint], Commander USING [CommandObject, CommandProc, CommandProcHandle, CommandProcObject, Enumerate, Handle, Lookup, Register], CommandExtras USING [MakeUninterpreted], CommandTool USING [AddProcToList, AddSearchRule, ArgumentVector, DoCommand, Failed, LookupCommand, LookupWithSearchRules, Parse, ParseToList, RemoveProcFromList, StarExpansion], Convert USING [AppendChar, Error, IntFromRope, RopeFromTime], EditedStream USING [Rubout], FileNames USING [ConvertToSlashFormat, CurrentWorkingDirectory, ResolveRelativePath, StripVersionNumber], FS USING [EnumerateForNames, Error, NameProc, StreamOpen], IO USING [Close, EndOf, EndOfStream, Error, GetBlock, GetLine, PutBlock, PutChar, PutF, PutFR, PutRope, STREAM], List USING [AList, Assoc, CompareProc, Memb, PutAssoc, Sort], Process USING [Abort, GetCurrent, Pause, SecondsToTicks], ProcessExtras USING [CheckForAbort], Real USING [Fix, RealException], Rope USING [Cat, Compare, Concat, Equal, Fetch, Find, IsEmpty, Length, Match, ROPE, Substr], RopeList USING [DReverse], SafeStorage USING [NWordsAllocated], SystemVersion USING [bootFileDate, release], TiogaMenuOps USING [Open], UserCredentials USING [Get], ViewerClasses USING [Viewer], VMStatistics USING [pageFaults]; InitialCommandsImpl: CEDAR MONITOR IMPORTS BasicTime, Booting, Commander, CommandExtras, CommandTool, Convert, EditedStream, FileNames, FS, IO, List, Process, ProcessExtras, Real, Rope, RopeList, SafeStorage, SystemVersion, TiogaMenuOps, UserCredentials, VMStatistics = BEGIN ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; Date: Commander.CommandProc = { RETURN[NIL, Convert.RopeFromTime[from: BasicTime.Now[], includeDayOfWeek: TRUE]]; }; User: Commander.CommandProc = { user: ROPE _ UserCredentials.Get[].name; IF user.Length[] = 0 THEN user _ "??"; RETURN[NIL, user]; }; Version: Commander.CommandProc = TRUSTED { PutVersion[cmd.out]; }; PutVersion: PROC [out: STREAM] = { IO.PutF[out, "Cedar %g.%g", [integer[SystemVersion.release.major]], [integer[SystemVersion.release.minor]]]; IF SystemVersion.release.patch # 0 THEN IO.PutF[out, ".%g", [integer[SystemVersion.release.patch]]]; IO.PutF[out, " of %t\n", [time[BasicTime.FromPupTime[SystemVersion.bootFileDate]]]]; }; Fail: Commander.CommandProc = { RETURN[$Failure, "This Command Always Fails"]; }; ECell: TYPE = RECORD [name, doc: ROPE]; EnumerateCommands: Commander.CommandProc = { el: LIST OF REF ANY; eCell: REF ECell; matchList: LIST OF ROPE _ NIL; lookupCmd: Commander.Handle _ NEW[Commander.CommandObject]; i: NAT _ 1; flag: BOOL _ FALSE; full: BOOL _ cmd.procData.clientData = $Full; EProc: PROC [key: ROPE, procData: Commander.CommandProcHandle] RETURNS [stop: BOOL] = { ProcessExtras.CheckForAbort[]; IF procData # NIL THEN { FOR list: LIST OF ROPE _ matchList, list.rest WHILE list # NIL DO IF list.first.Find["*"] = -1 THEN LOOP; -- handled elsewhere flag _ TRUE; IF list.first.Match[key, FALSE] THEN { el _ CONS[NEW[ECell _ [name: key, doc: procData.doc]], el]; ProcessExtras.CheckForAbort[]; EXIT; }; ENDLOOP; }; RETURN[FALSE]; }; FSProc: FS.NameProc = { commandName: ROPE _ Rope.Substr[base: FileNames.ConvertToSlashFormat[fullFName], start: 0, len: Rope.Find[s1: fullFName, pos1: 0, s2: ".load", case: FALSE]]; ProcessExtras.CheckForAbort[]; FOR list: LIST OF REF ANY _ el, list.rest WHILE list # NIL DO IF Rope.Equal[commandName, NARROW[list.first, REF ECell].name, FALSE] THEN RETURN[TRUE]; ENDLOOP; el _ CONS[NEW[ECell _ [name: commandName, doc: "not yet loaded"]], el]; RETURN[TRUE]; }; MyCompare: List.CompareProc = { a, b: REF ECell; a _ NARROW[ref1]; b _ NARROW[ref2]; RETURN[Rope.Compare[a.name, b.name, FALSE]]; }; argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd: cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO oops}]; DO match: ROPE _ NIL; ProcessExtras.CheckForAbort[]; IF i = argv.argc THEN EXIT; match _ argv[i]; i _ i + 1; IF match.IsEmpty[] OR match.Equal["\n"] THEN EXIT; IF match.Equal["*"] THEN { --exactly * matchList _ LIST["*"]; EXIT; } ELSE { match _ FileNames.ResolveRelativePath[match]; IF match.Fetch[0] # '/ AND match.Fetch[0] # '* AND match.Find["*"] # -1 THEN match _ Rope.Concat["*", match]; IF match.Fetch[match.Length[] - 1] = '/ THEN match _ Rope.Concat[match, "*"]; }; matchList _ CONS[match, matchList]; ENDLOOP; IF matchList = NIL THEN { cmd.out.PutRope["Usage: "]; cmd.out.PutRope[cmd.command]; cmd.out.PutRope[" list-of-patterns ...\n"]; RETURN; }; lookupCmd.err _ cmd.out; FOR list: LIST OF ROPE _ matchList, list.rest WHILE list # NIL DO IF list.first.Find["*"] = -1 THEN { ProcessExtras.CheckForAbort[]; lookupCmd.command _ list.first; lookupCmd.commandLine _ NIL; lookupCmd.procData _ NIL; lookupCmd.propertyList _ cmd.propertyList; CommandTool.LookupCommand[lookupCmd]; IF lookupCmd.procData # NIL THEN { IF lookupCmd.commandLine # NIL THEN cmd.out.PutRope["(Generic command) "]; cmd.out.PutF["%-20g %g %g\n", [rope[lookupCmd.command]], [rope[lookupCmd.commandLine]], [rope[lookupCmd.procData.doc]]]; } ELSE cmd.out.PutF["%-20g Not found\n", [rope[lookupCmd.command]]]; ProcessExtras.CheckForAbort[]; }; ENDLOOP; [] _ Commander.Enumerate[EProc]; IF full THEN FOR list: LIST OF ROPE _ matchList, list.rest WHILE list # NIL DO IF list.first.Find["*"] # -1 THEN { withStarExt: ROPE _ Rope.Concat[list.first, "*.load"]; FS.EnumerateForNames[pattern: withStarExt, proc: FSProc, wDir: NIL]; IF list.first.Fetch[0] # '/ AND list.first.Fetch[0] # '[ THEN { rules: LIST OF REF ANY _ NARROW[List.Assoc[key: $SearchRules, aList: cmd.propertyList]]; WHILE rules # NIL DO ProcessExtras.CheckForAbort[]; FS.EnumerateForNames[ pattern: withStarExt, proc: FSProc, wDir: NARROW[rules.first, ROPE]]; rules _ rules.rest; ENDLOOP; }; }; ENDLOOP; IF el = NIL AND flag = TRUE THEN { msg _ "No matching registered commands."; RETURN; }; IF el # NIL THEN { cmd.out.PutRope["Matching registered commands:\n"]; el _ List.Sort[list: el, compareProc: MyCompare]; WHILE el # NIL DO eCell _ NARROW[el.first]; cmd.out.PutF["%-20g %g\n", [rope[eCell.name]], [rope[eCell.doc]]]; el _ el.rest; ProcessExtras.CheckForAbort[]; ENDLOOP; }; EXITS oops => result _ $Failure; }; CopyCommand: Commander.CommandProc = { argv: CommandTool.ArgumentVector _ ExpandAndParse[cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO oops}]; IF argv.argc # 4 OR NOT Rope.Equal[argv[2], "_"] THEN { msg _ "Usage: CopyCommand newname _ oldname"; GO TO oops; }; { cth: Commander.Handle _ NEW[Commander.CommandObject _ []]; lresult: REF ANY; lmsg: ROPE; newName: ROPE; cth.err _ cmd.out; cth.command _ argv[3]; -- oldname cth.propertyList _ cmd.propertyList; -- so the search rules are accessible [result: lresult, msg: lmsg] _ CommandTool.LookupWithSearchRules[cth]; IF lresult = $Failure OR lmsg # NIL THEN {msg _ lmsg; GO TO oops}; IF cth.commandLine # NIL THEN { msg _ Rope.Concat[argv[2], " uses a generic command, can't copy or rename it"]; GO TO oops}; IF cth.procData = NIL OR cth.procData.proc = NIL THEN { msg _ Rope.Concat["CopyCommand: Can't find ", argv[3]]; GO TO oops}; newName _ FileNames.ResolveRelativePath[argv[1]]; IF newName.Fetch[0] # '/ AND newName.Fetch[0] # '[ THEN { cwd: ROPE _ FileNames.CurrentWorkingDirectory[]; IF NOT cwd.Equal["///"] THEN newName _ Rope.Concat[cwd, newName]; }; IF Commander.Lookup[newName] # NIL THEN { msg _ Rope.Cat["CopyCommand: ", newName, " already exists"]; GO TO oops}; Commander.Register[ key: newName, proc: cth.procData.proc, doc: cth.procData.doc, clientData: cth.procData.clientData]; cmd.out.PutF["CopyCommand %g _ %g\n", [rope[newName]], [rope[cth.command]]]; }; EXITS oops => result _ $Failure; }; Unregister: Commander.CommandProc = { procData: Commander.CommandProcHandle; argv: CommandTool.ArgumentVector _ ExpandAndParse[cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO oops}]; IF argv.argc = 2 THEN { procData _ Commander.Lookup[argv[1]]; IF procData # NIL AND procData.proc # NIL THEN Commander.Register[key: argv[1], proc: NIL, doc: NIL] ELSE cmd.out.PutF["Unregister: %g not found\n", [rope[argv[1]]]]; } ELSE cmd.out.PutRope["Usage: Unregister commandname\n"]; EXITS oops => result _ $Failure; }; Open: Commander.CommandProc = { argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO oops}]; IF argv.argc < 2 THEN {OpenViewer[NIL, cmd.out]; RETURN}; FOR i: NAT IN [1..argv.argc) DO list: LIST OF ROPE _ ExpandStar[argv[i]]; WHILE list # NIL DO name: ROPE _ FileNames.ResolveRelativePath[list.first]; OpenViewer[name, cmd.out]; list _ list.rest; ENDLOOP; ENDLOOP; EXITS oops => result _ $Failure; }; ExpandStar: PROC [token: ROPE] RETURNS [LIST OF ROPE] = { IF Rope.Find[token, "*"] # -1 THEN { stripVersion: BOOL; listOfTokens: LIST OF ROPE _ NIL; ConsProc: FS.NameProc = { fullFName _ FileNames.ConvertToSlashFormat[fullFName]; IF stripVersion THEN fullFName _ FileNames.StripVersionNumber[fullFName]; listOfTokens _ CONS[fullFName, listOfTokens]; -- on front of list RETURN[TRUE]; }; IF token.Find["!"] = -1 THEN token _ Rope.Concat[token, "!H"]; stripVersion _ token.Find["!H", 0, FALSE] # -1; FS.EnumerateForNames[pattern: FileNames.ResolveRelativePath[token], proc: ConsProc]; RETURN[RopeList.DReverse[listOfTokens]]; } ELSE RETURN[LIST[token]]; }; New: Commander.CommandProc = { OpenViewer[NIL, cmd.out]; }; Comment: Commander.CommandProc = { }; OpenViewer: PROC [name: ROPE, out: STREAM] = { viewer: ViewerClasses.Viewer; IF Rope.IsEmpty[name] THEN name _ FileNames.CurrentWorkingDirectory[]; viewer _ TiogaMenuOps.Open[name]; IF viewer = NIL THEN out.PutF["\tViewer file not found: %g\n", [rope[name]]] ELSE out.PutF["\tCreated Viewer: %g\n", [rope[viewer.name]]]; }; statBeforeRef: Commander.CommandProcHandle _ NEW[Commander.CommandProcObject _ [StatBefore]]; statAfterRef: Commander.CommandProcHandle _ NEW[Commander.CommandProcObject _ [StatAfter]]; StatDataObject: TYPE = RECORD [ cmd: Commander.Handle _ NIL, startTime: BasicTime.GMT, startPulses: BasicTime.Pulses, 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 = { ENABLE UNWIND => NULL; FOR i: NAT IN [0..MaxStats) DO IF stats.a[i].cmd = NIL THEN { stats.a[i] _ [ cmd: cmd, startTime: BasicTime.Now[], startPulses: BasicTime.GetClockPulses[], startFaults: VMStatistics.pageFaults, startWords: SafeStorage.NWordsAllocated[] ]; EXIT; }; ENDLOOP; result _ $Preserve; }; StatAfter: ENTRY Commander.CommandProc = { ENABLE UNWIND => NULL; pulses: BasicTime.Pulses = BasicTime.GetClockPulses[]; now: BasicTime.GMT = BasicTime.Now[]; wordsNow: INT = SafeStorage.NWordsAllocated[]; faultsNow: INT = VMStatistics.pageFaults; FOR i: NAT IN [0..MaxStats) DO statObj: StatDataObject = stats.a[i]; IF statObj.cmd = cmd THEN { seconds: INT _ BasicTime.Period[statObj.startTime, now]; nw: INT = wordsNow - statObj.startWords; nf: INT = faultsNow - statObj.startFaults; stats.a[i].cmd _ NIL; cmd.out.PutF[" {"]; SELECT seconds FROM < 0 => cmd.out.PutRope["?? seconds"]; >= 60 => { cmd.out.PutF["%r seconds", [integer[seconds]]]; }; ENDCASE => { tt: REAL _ BasicTime.PulsesToSeconds[pulses - statObj.startPulses]; fraction: INT _ 0; seconds _ Real.Fix[tt ! Real.RealException => { seconds _ LAST[INT]; CONTINUE; }]; fraction _ Real.Fix[(tt - seconds) * 100.0 ! Real.RealException => { fraction _ 0; CONTINUE; }]; cmd.out.PutF["%d.%02d seconds", [integer[seconds]], [integer[fraction]]] }; IF nw > 0 AND nw < 10000000 THEN cmd.out.PutF[", %d words", [integer[nw]]]; IF nf > 0 AND nf < 10000000 THEN cmd.out.PutF[", %d page faults", [integer[nf]]]; cmd.out.PutRope["}\n"]; EXIT; }; ENDLOOP; result _ $Preserve; }; Statistics: Commander.CommandProc = { rb: REF ANY _ List.Assoc[key: $Before, aList: cmd.propertyList]; rbl: LIST OF REF ANY; exists: BOOL; IF rb # NIL AND ISTYPE[rb, LIST OF REF ANY] THEN rbl _ NARROW[rb]; exists _ rbl # NIL AND List.Memb[ref: statBeforeRef, list: rbl]; IF exists THEN { cmd.propertyList _ CommandTool.RemoveProcFromList[aList: cmd.propertyList, listKey: $Before, proc: statBeforeRef]; cmd.propertyList _ CommandTool.RemoveProcFromList[aList: cmd.propertyList, listKey: $After, proc: statAfterRef]; } ELSE { cmd.propertyList _ CommandTool.AddProcToList[aList: cmd.propertyList, listKey: $Before, proc: statBeforeRef]; cmd.propertyList _ CommandTool.AddProcToList[aList: cmd.propertyList, listKey: $After, proc: statAfterRef]; }; }; Echo: Commander.CommandProc = { argv: CommandTool.ArgumentVector _ ExpandAndParse[cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO oops}]; FOR i: NAT IN [1..argv.argc) DO cmd.out.PutRope[argv[i]]; cmd.out.PutChar[' ]; ProcessExtras.CheckForAbort[]; ENDLOOP; cmd.out.PutChar['\n]; EXITS oops => result _ $Failure; }; PrintSearchRules: Commander.CommandProc = { rules: LIST OF REF ANY _ NARROW[List.Assoc[key: $SearchRules, aList: cmd.propertyList]]; cmd.out.PutRope["( "]; IF rules = NIL THEN cmd.out.PutChar[' ]; WHILE rules # NIL DO cmd.out.PutRope[NARROW[rules.first, ROPE]]; rules _ rules.rest; cmd.out.PutChar[' ]; ProcessExtras.CheckForAbort[]; ENDLOOP; cmd.out.PutRope[")\n"]; }; SetSearchRules: Commander.CommandProc = { args: LIST OF ROPE; dir: ROPE; first: CHAR; CommandTool.StarExpansion[cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO oops}]; args _ CommandTool.ParseToList[cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO oops}].list; IF cmd.procData.clientData = $SetSearchRules THEN cmd.propertyList _ List.PutAssoc[key: $SearchRules, val: NIL, aList: cmd.propertyList]; WHILE args # NIL DO dir _ args.first; dir _ FileNames.ResolveRelativePath[dir]; IF dir.Length[] < 3 THEN { msg _ Rope.Concat["Directory name too short: ", dir]; GO TO oops}; first _ dir.Fetch[0]; IF first # '[ AND first # '/ THEN { msg _ Rope.Concat["Bad directory name: ", dir]; GO TO oops}; CommandTool.AddSearchRule[cmd: cmd, dir: dir, append: TRUE]; args _ args.rest; ProcessExtras.CheckForAbort[]; ENDLOOP; EXITS oops => result _ $Failure; }; Sleep: Commander.CommandProc = { seconds: INT; secondsCard: CARDINAL; argv: CommandTool.ArgumentVector _ ExpandAndParse[cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO oops}]; IF argv.argc # 2 THEN {msg _ "Usage: Sleep seconds"; GO TO oops}; seconds _ Convert.IntFromRope[argv[1] ! Convert.Error => {msg _ "Bad arg"; GO TO oops}]; IF seconds NOT IN [0..LAST[CARDINAL]] THEN {msg _ "Bad arg"; GO TO oops}; secondsCard _ seconds; Process.Pause[Process.SecondsToTicks[seconds]]; EXITS oops => result _ $Failure; }; Indent: Commander.CommandProc = { depth: INT; depthNAT: NAT; spaces: REF TEXT; line: REF TEXT _ NEW[TEXT[200]]; argv: CommandTool.ArgumentVector _ ExpandAndParse[cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO oops}]; IF argv.argc > 2 THEN {msg _ "Usage: Indent depth"; GO TO oops}; IF argv.argc < 2 THEN { depth _ 8; depthNAT _ 8; } ELSE { depth _ Convert.IntFromRope[argv[1] ! Convert.Error => {msg _ "Bad arg"; GO TO oops}]; IF depth NOT IN [0..80] THEN {msg _ "depth should be in [0..80]"; GO TO oops}; depthNAT _ depth; }; spaces _ NEW[TEXT[depthNAT]]; FOR i: NAT IN [0..depthNAT) DO spaces[i] _ ' ; ENDLOOP; spaces.length _ depthNAT; DO IF cmd.in.EndOf[ ! IO.Error => EXIT] THEN EXIT; line _ cmd.in.GetLine[buffer: line ! IO.EndOfStream => GOTO Finished; IO.Error => EXIT; EditedStream.Rubout => GOTO Finished; ]; cmd.out.PutBlock[block: spaces ! IO.Error => EXIT]; cmd.out.PutBlock[block: line ! IO.Error => EXIT]; cmd.out.PutChar['\n ! IO.Error => EXIT]; ENDLOOP; EXITS Finished => NULL; oops => result _ $Failure; }; Tee: Commander.CommandProc = { fileStream: STREAM _ NIL; block: REF TEXT _ NEW[TEXT[512]]; { ENABLE UNWIND => IF fileStream # NIL THEN fileStream.Close[]; argv: CommandTool.ArgumentVector _ ExpandAndParse[cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO oops}]; IF argv.argc > 2 THEN {msg _ "Usage: Tee filename"; GO TO oops}; IF argv.argc = 2 THEN fileStream _ FS.StreamOpen[fileName: argv[1], accessOptions: $create ! FS.Error => IF error.group # $bug THEN {msg _ error.explanation; GO TO oops}]; DO count: NAT; block.length _ 0; IF cmd.in.EndOf[] THEN EXIT; count _ cmd.in.GetBlock[block: block ! IO.EndOfStream => EXIT; IO.Error => EXIT; EditedStream.Rubout => EXIT; ]; IF count = 0 THEN EXIT; IF fileStream # NIL THEN fileStream.PutBlock[block: block ! IO.Error => EXIT]; cmd.out.PutBlock[block: block ! IO.Error => EXIT]; ProcessExtras.CheckForAbort[]; ENDLOOP; fileStream.Close[ ! IO.Error => CONTINUE]; }; EXITS oops => RETURN[$Failure, msg]; }; Abort: Commander.CommandProc = TRUSTED { Process.Abort[LOOPHOLE[Process.GetCurrent[], UNSPECIFIED]]; }; Shift: Commander.CommandProc = { result _ CommandTool.DoCommand[commandLine: cmd.commandLine, parent: cmd]; }; ShiftInterp: Commander.CommandProc = { result _ CommandTool.DoCommand[commandLine: cmd.commandLine, parent: cmd]; }; Time: Commander.CommandProc = { start: BasicTime.Pulses _ BasicTime.GetClockPulses[]; stop: BasicTime.Pulses; microseconds, seconds: LONG CARDINAL; digit: CARDINAL; any: BOOL _ FALSE; text: REF TEXT _ NEW[TEXT[8]]; result _ CommandTool.DoCommand[commandLine: cmd.commandLine, parent: cmd]; stop _ BasicTime.GetClockPulses[]; microseconds _ BasicTime.PulsesToMicroseconds[stop - start]; seconds _ microseconds / 1000000; microseconds _ microseconds MOD 1000000; THROUGH [0..6) DO microseconds _ microseconds * 10; digit _ microseconds / 1000000; microseconds _ microseconds MOD 1000000; IF NOT any THEN { text _ Convert.AppendChar[to: text, from: '., quote: FALSE]; any _ TRUE; }; text _ Convert.AppendChar[to: text, from: digit + '0, quote: FALSE]; IF microseconds = 0 THEN EXIT; ENDLOOP; RETURN [NIL, IO.PutFR["Running time: %r%g\n", [cardinal[seconds]], [text[text]]]]; }; Checkpoint: Commander.CommandProc = { errmsg: ROPE; out: STREAM = cmd.out; IO.PutF[out, "Creating checkpoint at %g\n", [time[BasicTime.Now[]]]]; IO.PutF[out, " made by %g\n", [rope[UserCredentials.Get[].name]]]; errmsg _ Booting.Checkpoint[]; IF errmsg.Length[] # 0 THEN RETURN[$Failure, errmsg]; IO.PutF[out, "Rollback at %g\n User: %g\n Version: ", [time[BasicTime.Now[]]], [rope[UserCredentials.Get[].name]]]; PutVersion[cmd.out]; }; Rollback: Commander.CommandProc = { RETURN[$Failure, Booting.Boot[[self[]], [r: TRUE]]]; }; ExpandAndParse: PROC [cmd: Commander.Handle] RETURNS [CommandTool.ArgumentVector] = { CommandTool.StarExpansion[cmd]; RETURN [CommandTool.Parse[cmd]]; }; Init: PROC = { Register: PROC [name: ROPE, proc: Commander.CommandProc, doc: ROPE, data: REF _ NIL, un: BOOL _ FALSE] = { name _ Rope.Concat["///Commands/", name]; Commander.Register[name, proc, doc, data]; IF un THEN CommandExtras.MakeUninterpreted[Commander.Lookup[name]]; }; Commander.Register["-", Comment, "Comment"]; CommandExtras.MakeUninterpreted[Commander.Lookup["-"]]; Commander.Register["--", Comment, "Comment"]; CommandExtras.MakeUninterpreted[Commander.Lookup["--"]]; Commander.Register["/", Comment, "Comment"]; CommandExtras.MakeUninterpreted[Commander.Lookup["/"]]; Commander.Register["//", Comment, "Comment"]; CommandExtras.MakeUninterpreted[Commander.Lookup["//"]]; Commander.Register["///", Comment, "Comment"]; CommandExtras.MakeUninterpreted[Commander.Lookup["///"]]; Register["?", EnumerateCommands, "List registered commands"]; Register["??", EnumerateCommands, "List registered commands (including those not yet loaded)", $Full]; Register["Help", EnumerateCommands, "List registered commands"]; Register["HelpFull", EnumerateCommands, "List registered commands (including those not yet loaded)", $Full]; Register["Abort", Abort, "Abort -- Raises ABORTED"]; Register["AddSearchRules", SetSearchRules, "Add command search rules: AddSearchRules list-of-directories"]; Register["CopyCommand", CopyCommand, "CopyCommand newName _ oldName - Attach a new name to an existing command"]; Register["Checkpoint", Checkpoint, "Create a checkpoint"]; Register["Date", Date, "Print date and time"]; Register["Echo", Echo, "Print command line"]; Register["Fail", Fail, "This command always fails"]; Register["Indent", Indent, "Indent n -- Indent n spaces"]; Register["New", New, "Open an empty viewer"]; Register["Open", Open, "Open fileName - open a viewer"]; Register["PrintSearchRules", PrintSearchRules, "Print command search rules"]; Register["Rollback", Rollback, "Roll back to previous checkpoint"]; Register["SetSearchRules", SetSearchRules, "Set command search rules: SetSearchRules directory*", $SetSearchRules]; Register["Shift", Shift, "Shift command-line (uninterpreted)", NIL, TRUE]; Register["ShiftInterp", ShiftInterp, "ShiftInterp command-line (interpreted)"]; Register["Sleep", Sleep, "Sleep n -- pause for n seconds"]; Register["Statistics", Statistics, "Turn statistics printing on or off"]; Register["Tee", Tee, "Tee file -- copy standard input to file"]; Register["Time", Time, "Time command-line (uninterpreted)", NIL, TRUE]; Register["Unregister", Unregister, "Unregister a command"]; Register["User", User, "Print name of logged in user"]; Register["Version", Version, "Print Cedar version number"]; }; Init[]; END. April 4, 1983 4:42 pm, Stewart, Created April 20, 1983 7:10 pm, Stewart, add commandfile arguments and auto commandfiles September 7, 1983 11:10 am, Stewart, Cedar 5 October 24, 1983 9:42 am, Stewart, New CommandTool November 3, 1983 9:37 am, Stewart, Bulletproofing November 3, 1983 9:37 am, Stewart, add Checkpoint and Rollback January 14, 1984 8:18 pm, Stewart, new Open |InitialCommandsImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. L. Stewart, January 17, 1984 5:03 pm Russ Atkinson, October 22, 1984 8:15:27 pm PDT Paul Rovner, November 29, 1983 8:51 am Doug Wyatt, May 25, 1984 2:52:01 pm PDT [cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] see if we have a match there is a match with the command name, so add it to the list (once only) strip off the .load and any version number Linear search the batch already loaded and don't bother with duplicates At this point, we've got the fullFName of a new .load file First, construct the list of patterns to match against the command names. Preprocess it! If no patterns given, remind the user to supply at least one. First handle any non-star cases using LookupProc This one has no pattern Now search the file system If no matches found, indicate this result explicitly. Now there has been at least one match, so sort the results and display them to the user. Long elapsed time, so use low precision clock to avoid overflow High precision elapsed time Now we have to preserve the result, or else we will not preserve $Failure! Ê®˜šœ™Jšœ Ïmœ1™˜oKšœžœ˜!Kšœ žœi˜xKšœžœ˜(Kšœ žœ ˜±Kšœžœ0˜=Kšœ žœ ˜Kšœ žœZ˜iKšžœžœ2˜:Kšžœžœ`žœ˜pKšœžœ3˜=Kšœžœ,˜9Kšœžœ˜$Kšœžœ˜ KšœžœDžœ ˜\Kšœ žœ ˜Kšœ žœ˜$Kšœžœ˜,Kšœ žœ˜Kšœžœ˜Kšœžœ ˜Kšœ žœ˜ —J˜šœžœž˜"Kšžœ^žœžœ}˜èKšœž˜—˜Jšžœžœžœ˜Jšžœžœžœžœ˜—J˜šœ˜Jšžœžœ@žœ˜QJ˜—J˜šœ˜Jšœžœ˜(Jšžœžœ ˜&Jšžœžœ˜J˜—J˜šœ!žœ˜*Jšœ˜J˜J˜—šÏn œžœžœ˜"šžœ˜JšœP˜P—šžœ!ž˜'Jšžœ:˜<—JšžœR˜TJ˜—J˜šœ˜Jšžœ(˜.J˜—J˜Jšœžœžœ žœ˜'J˜šœ,˜,Jš œžœ žœžœžœžœ™:Jš œžœžœžœžœ˜Jšœžœ˜Jš œ žœžœžœžœ˜Jšœžœ˜;Jšœžœ˜ Jšœžœžœ˜Jšœžœ#˜-š Ÿœžœžœ)žœžœ˜WJ˜šžœ žœžœ˜Jšœ™š žœžœžœžœžœžœž˜AJšžœžœžœÏc˜=Jšœžœ˜ šžœžœžœ˜&JšœI™IJšœžœžœ.˜;J˜Jšžœ˜J˜—Jšžœ˜—J˜—Jšžœžœ˜J˜—šœžœ ˜J™*Jšœ žœ„žœ˜J™GJ˜šžœžœžœžœžœžœžœž˜=šžœžœ žœžœ˜EJšžœžœžœ˜—Jšžœ˜—Jšœ:™:Jšœžœžœ:˜GJšžœžœ˜ Jšœ˜—šœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšžœžœ˜,J˜—šœ=˜=Jšœ)žœžœ˜6J˜—JšœI™Išž˜Jšœžœžœ˜J˜Jšžœžœžœ˜Jšœ˜J˜ Jšžœžœžœžœ˜2J™šžœ˜šžœ  ˜Jšœ žœ˜Jšžœ˜J˜—šžœ˜Jšœ-˜-šžœžœžœž˜LJšœ ˜ —Jšžœ&žœ!˜MJ˜——Jšœ žœ˜#Jšžœ˜—šžœ žœžœ˜Jšœ=™=Jšœ˜Jšœ˜Jšœ+˜+Jšžœ˜J˜—J™0J˜š žœžœžœžœžœžœž˜Ašžœžœ˜#J™J˜Jšœ˜Jšœžœ˜Jšœžœ˜Jšœ*˜*Jšœ%˜%šžœž˜šžœ˜šžœžœž˜#Jšœ&˜&—šœ˜JšœZ˜Z—J˜—Jšžœ>˜B—J˜J˜—Jšžœ˜—J˜ šžœž˜ J™š žœžœžœžœžœžœž˜Ašžœžœ˜#Jšœ žœ%˜6Jšžœ=žœ˜Dšžœžœžœ˜?šœžœžœžœž˜Jšœžœ9˜A—šžœ žœž˜J˜šžœ˜Jšœ*žœžœ˜E—Jšœ˜Jšžœ˜—J˜—J˜—Jšžœ˜——š žœžœžœžœžœ˜"Jšœ5™5Jšœ)˜)Jšžœ˜J˜—JšœX™Xšžœžœžœ˜J˜3Jšœ1˜1šžœžœž˜Jšœžœ ˜JšœB˜BJ˜ J˜Jšžœ˜—J˜—Jšžœ˜ J˜—J˜šœ&˜&šœ ˜ Jšœ>žœžœ˜K—šžœžœžœžœ˜7Jšœ-˜-Jšžœžœ˜ J˜—šœ˜Jšœžœ˜:Jšœ žœžœ˜Jšœžœ˜ Jšœ žœ˜J˜Jšœ  ˜"Jšœ& %˜KJšœF˜FJš žœžœžœžœžœžœ˜Bšžœžœžœ˜JšœO˜OJšžœžœ˜ —š žœžœžœžœžœ˜7Jšœ8žœžœ˜D—J˜1šžœžœžœ˜9Jšœžœ'˜0Jšžœžœžœ%˜AJ˜—šžœžœžœ˜)Jšœ=žœžœ˜I—šœ˜Jšœc˜c—JšœL˜LJ˜—Jšžœ˜ J˜—J˜šœ%˜%J˜&šœ ˜ Jšœ>žœžœ˜K—šžœ˜šžœ˜Jšœ%˜%šžœ žœžœž˜)Jšžœ(žœžœ˜:Jšžœ=˜A—J˜—Jšžœ4˜8—Jšžœ˜ J˜—J˜šœ˜šœ ˜ JšœAžœžœ˜N—Jšžœžœ žœ žœ˜9šžœžœžœž˜Jšœžœžœžœ˜)šžœžœž˜Jšœžœ-˜7Jšœ˜J˜Jšžœ˜—Jšžœ˜—Jšžœ˜ J˜—J˜šŸ œžœ žœžœžœžœžœ˜9šžœžœ˜$Jšœžœ˜Jš œžœžœžœžœ˜!šœ žœ ˜Jšœ6˜6Jšžœžœ5˜IJšœžœ ˜BJšžœžœ˜ J˜—Jšžœžœ"˜>Jšœ#žœ˜/JšžœR˜TJšžœ"˜(J˜—Jšžœžœžœ ˜J˜—J˜šœ˜Jšœ žœ ˜J˜—J˜šœ"˜"J˜—J˜šŸ œžœžœžœ˜0Jšœ˜Jšžœžœ,˜FJšœ!˜!Jšžœ žœžœ8˜LJšžœ9˜=J˜—J˜šœ*˜*Jšœžœ-˜2—šœ)˜)Jšœžœ,˜1—J˜šœžœžœ˜Jšœžœ˜Jšœžœ˜Jšœ˜Jšœ žœ˜Jšœ ž˜J˜—J˜Jšœ žœ˜J˜šœ žœžœ˜Jšœžœžœ˜5J˜J˜—Jšœžœ žœ˜0J˜šœ žœ˜+Jšžœžœžœ˜šžœžœžœž˜šžœžœžœ˜šœ˜Jšœ ˜ Jšœ˜Jšœ(˜(Jšœ%˜%Jšœ,˜,—Jšžœ˜J˜—Jšžœ˜—J˜J˜—J˜šœ žœ˜*Jšžœžœžœ˜Jšœ6˜6Jšœžœ˜%Jšœ žœ!˜.Jšœ žœ˜)J˜šžœžœžœž˜Jšœ%˜%šžœžœ˜Jšœ žœ,˜8Jšœžœ!˜(Jšœžœ#˜*Jšœžœ˜Jšœ˜šžœ ž˜J˜%šœ ˜ Jšœ?™?Jšœ/˜/J˜—šžœ˜ Jšœ™Jšœžœ;˜CJšœ žœ˜šœ˜Jšœ$žœžœžœ˜<—šœ*˜*Jšœ(žœ˜5—JšœH˜HJ˜——Jšžœžœžœ,˜LJšžœžœžœ2˜RJšœ˜Jšžœ˜J˜—Jšžœ˜—JšœJ™JJšœ˜J˜—J˜šœ%˜%Jšœžœžœ5˜@Jš œžœžœžœžœ˜Jšœžœ˜ Jšžœžœžœžœžœžœžœžœžœžœ˜BJšœžœžœ*˜@šžœ˜ šžœ˜Jšœr˜rJšœp˜pJ˜—šžœ˜Jšœm˜mJšœk˜kJ˜——J˜—J˜šœ˜šœ ˜ Jšœ>žœžœ˜K—šžœžœžœž˜J˜J˜J˜Jšžœ˜—J˜Jšžœ˜ J˜—J˜šœ+˜+šœžœžœžœž˜Jšœžœ9˜A—Jšœ˜Jšžœ žœžœ˜(šžœ žœž˜Jšœžœžœ˜+Jšœ˜Jšœ˜J˜Jšžœ˜—Jšœ˜J˜—J˜šœ)˜)Jšœžœžœžœ˜Jšœžœ˜ Jšœžœ˜ šœ˜Jšœ)žœžœ˜6—šœ"˜"Jšœ)žœžœ ˜;—šžœ+ž˜1Jšœ9žœ˜W—šžœžœž˜Jšœ˜Jšœ)˜)šžœžœ˜Jšœ6žœžœ˜B—Jšœ˜šžœ žœ žœ˜#Jšœ0žœžœ˜<—Jšœ6žœ˜žœžœ˜K—Jšžœžœ žœžœ˜AJšœKžœžœ˜XJšžœ žœžœžœžœžœžœžœ˜IJšœ˜Jšœ/˜/Jšžœ˜ J˜—J˜šœ!˜!Jšœžœ˜ Jšœ žœ˜Jšœžœžœ˜Jš œžœžœžœžœ˜ šœ ˜ Jšœ>žœžœ˜K—Jšžœžœžœžœ˜@šžœ˜šžœ˜Jšœ ˜ Jšœ ˜ J˜—šžœ˜JšœIžœžœ˜VJš žœžœžœ žœ&žœžœ˜NJšœ˜J˜——Jšœ žœžœ ˜Jš žœžœžœžœžœ˜7Jšœ˜šž˜Jš žœžœÏr žœžœžœ˜/šœ%˜%Jšžœ¡Ðkr¡ ˜ Jšžœ¡ ž¡˜Jšœ¢¡ ˜%Jšœ˜—Jšœ!žœ¡ žœ˜3Jšœžœ¡ žœ˜1Jšœžœ¡ žœ˜(Jšžœ˜—šž˜Jšœ žœ˜Jšœ˜—J˜—J˜šœ˜Jšœ žœžœ˜Jš œžœžœžœžœ˜!˜Jš žœžœžœžœžœ˜=šœ ˜ Jšœ>žœžœ˜K—Jšžœžœžœžœ˜@šžœž˜šœ žœ5˜DJš œžœ žœžœžœžœ˜P——šž˜Jšœžœ˜ Jšœ˜Jšžœžœžœ˜šœ'˜'Jšžœ¡ž¡˜Jšžœ¡ ž¡˜Jšœž¡˜Jšœ˜—Jšžœ žœžœ˜Jš žœžœžœ$žœ¡ žœ˜NJšœ žœ¡ žœ˜2J˜Jšžœ˜—Jšœžœ¡ žœ˜*J˜—Jšžœ žœ˜$J˜—J˜šœžœ˜(Jšœžœž œ˜;J˜—J˜šœ ˜ JšœJ˜JJ˜—J˜šœ&˜&JšœJ˜JJ˜—J˜šœ˜Jšœ5˜5Jšœ˜Jšœžœžœ˜%Jšœžœ˜Jšœžœžœ˜Jš œžœžœžœžœ˜JšœJ˜JJšœ"˜"Jšœ<˜˜>Jšœ+˜+J˜J˜J˜J˜J˜—…—TZq„