-- SLControl.mesa -- Last edited by Satterthwaite on September 16, 1982 8:29 am DIRECTORY CharIO: TYPE USING [PutChar, PutLine, PutString], CommandUtil: TYPE USING [ CommandObject, CopyString, Echo, Failed, FreePairList, FreeString, --GetNth,-- ListLength, PairList, Parse], Exec: TYPE USING [AddCommand, commandLine, w], ExecOps: TYPE USING [CheckForAbort, Command], ListerOps: TYPE USING [ListSymbols], OSMiscOps: TYPE USING [BcdCreateTime], Runtime: TYPE USING [CallDebugger], Stream: TYPE USING [ Handle, Object, PutByteProcedure, DeleteProcedure, Delete], Strings: TYPE USING [ AppendString, EquivalentSubString, String, SubStringDescriptor], Time: TYPE USING [Append, AppendCurrent, Current, Unpack], TTY: TYPE USING [PutChar]; SLControl: PROGRAM IMPORTS CharIO, CommandUtil, Exec, ExecOps, ListerOps, OSMiscOps, Runtime, Stream, Strings, Time, TTY = { EquivalentString: PROC [s1, s2: Strings.String] RETURNS [BOOL] = { ss1: Strings.SubStringDescriptor ← [base: s1, offset: 0, length: s1.length]; ss2: Strings.SubStringDescriptor ← [base: s2, offset: 0, length: s2.length]; RETURN [Strings.EquivalentSubString[@ss1, @ss2]]}; -- command gathering and logging log: Stream.Handle ← NIL; logStreamObject: Stream.Object; SetLogStream: PROC = { logStreamObject ← [ options: TRASH, getByte: TRASH, putByte: PutTTY, getWord: TRASH, putWord: TRASH, get: TRASH, put: TRASH, setSST: TRASH, sendAttention: TRASH, waitAttention: TRASH, delete: NullDelete]; log ← @logStreamObject}; PutTTY: Stream.PutByteProcedure = {(Exec.w).PutChar['\000 + byte]}; NullDelete: Stream.DeleteProcedure = {}; LogString: PROC [s: Strings.String] = {CharIO.PutString[log, s]}; LogChar: PROC [c: CHAR] = {CharIO.PutChar[log, c]}; renamedOutput: BOOL ← FALSE; RepeatCommand: PROC [s: Stream.Handle] = { OPEN CharIO; PutString[s, "\nListing "L]; PutString[s, inputName]; IF renamedOutput THEN { PutString[s, ", code to "L]; PutString[s, outputName]}; PutChar[s, '\n]}; WriteHerald: PROC [s: Stream.Handle, id: Strings.String] = { OPEN Time, CharIO; herald: STRING ← [60]; Strings.AppendString[herald, "Cedar 3.4 Symbol Lister of "L]; Time.Append[herald, Time.Unpack[[OSMiscOps.BcdCreateTime[]]]]; herald.length ← herald.length-3; PutLine[s, herald]; IF id # NIL THEN {PutString[s, id]; PutString[s, " -- "L]}; herald.length ← 0; Time.AppendCurrent[herald]; PutLine[s, herald]}; -- file name bookkeeping inputName, outputName, rootName: Strings.String ← NIL; commandArgs: CommandUtil.PairList; FileRoot: PROC [s: Strings.String] RETURNS [root: Strings.String] = { root ← CommandUtil.CopyString[s, 0]; FOR i: CARDINAL DECREASING IN [0..s.length) DO IF s[i] = '. THEN {s.length ← i; EXIT}; ENDLOOP}; -- switches StandardDefaults: PACKED ARRAY CHAR ['a..'z] OF BOOL = [ FALSE, -- A FALSE, -- B FALSE, -- C FALSE, -- D Call debugger on error FALSE, -- E FALSE, -- F FALSE, -- G FALSE, -- H FALSE, -- I FALSE, -- J FALSE, -- K FALSE, -- L FALSE, -- M FALSE, -- N FALSE, -- O FALSE, -- P FALSE, -- Q FALSE, -- R TRUE , -- S Symbols FALSE, -- T Trees (for bodies) FALSE, -- U FALSE, -- V FALSE, -- W FALSE, -- X FALSE, -- Y FALSE];-- Z -- others are unused -- Exec interfaces DoCommand: PROC = { theCommand: CommandUtil.CommandObject ← [ pos: Exec.commandLine.i, len: Exec.commandLine.s.length, -- data: @Exec.commandLine.s.text]; data: LOOPHOLE[Exec.commandLine.s + StringBody[0].SIZE]]; results: CommandUtil.PairList; switches: Strings.String; defaultSwitches: PACKED ARRAY CHAR ['a..'z] OF BOOL ← StandardDefaults; localSwitches: PACKED ARRAY CHAR ['a..'z] OF BOOL; SetLogStream[]; WriteHerald[log, NIL]; -- main loop DO { Initialize: PROC = {RepeatCommand[log]}; Finalize: PROC = {}; startTime: LONG CARDINAL; localSwitches ← defaultSwitches; renamedOutput ← FALSE; [inputName, commandArgs, results, switches] ← CommandUtil.Parse[ s: @theCommand, opX: 2+("bcd"L).length, resultX: 2+("sl"L).length ! CommandUtil.Failed => {GO TO badSyntax}]; IF inputName = NIL AND switches = NIL THEN EXIT; -- done listing LogString["\nCommand: "L]; CommandUtil.Echo[ d: log, operator: inputName, argList: commandArgs, resultList: results, switches: switches]; IF inputName = NIL THEN GO TO globalSwitches; SELECT CommandUtil.ListLength[results] FROM 0 => NULL; -- 1 => { -- outputName ← CommandUtil.GetNth[list: results, n: 0]; -- renamedOutput ← TRUE} ENDCASE => GO TO badSemantics; rootName ← FileRoot[inputName]; IF switches # NIL THEN { i: CARDINAL ← 0; sense: BOOL ← TRUE; WHILE i < switches.length DO c: CHAR = switches[i]; SELECT c FROM '-, '~ => sense ← ~sense; IN ['a..'z] => {localSwitches[c] ← sense; sense ← TRUE}; IN ['A..'Z] => {localSwitches[c + ('a-'A)] ← sense; sense ← TRUE}; '! => {Runtime.CallDebugger[NIL]; sense ← TRUE}; ENDCASE; i ← i+1; ENDLOOP; switches ← CommandUtil.FreeString[switches]}; startTime ← Time.Current[]; Initialize[]; ListerOps.ListSymbols[rootName, localSwitches['s], localSwitches['t] ! UNWIND => {Finalize[]}]; Finalize[]; IF ExecOps.CheckForAbort[] THEN EXIT; EXITS globalSwitches => { sense: BOOL ← TRUE; results ← CommandUtil.FreePairList[results]; FOR i: CARDINAL IN [0..switches.length) DO c: CHAR = switches[i]; SELECT c FROM '-, '~ => sense ← ~sense; '! => Runtime.CallDebugger[NIL]; IN ['a..'z] => {defaultSwitches[c] ← sense; sense ← TRUE}; IN ['A..'Z] => {defaultSwitches[c + ('a-'A)] ← sense; sense ← TRUE}; ENDCASE => EXIT; ENDLOOP; switches ← CommandUtil.FreeString[switches]}; badSemantics => { results ← CommandUtil.FreePairList[results]; LogString["\n -- Illegal command"L]}}; inputName ← CommandUtil.FreeString[inputName]; outputName ← CommandUtil.FreeString[outputName]; commandArgs ← CommandUtil.FreePairList[commandArgs]; rootName ← CommandUtil.FreeString[rootName]; REPEAT badSyntax => {LogString["-- Illegal syntax"L]}; ENDLOOP; Stream.Delete[log]; log ← NIL}; -- global Binder initialization Init: PROC = { Exec.AddCommand["sl"L, DoCommand]; Exec.AddCommand["SymbolLister"L, DoCommand]}; Init[]; }.