DIRECTORY CharIO: TYPE USING [NumberFormat, CR, PutChar, PutDecimal, PutLine, PutNumber, PutString], CIFS: TYPE USING [OpenFile, Close, Delete, Error, GetFC, Open, read], CommandUtil: TYPE USING [ PairList, CommandObject, CommandPtr, CopyString, Echo, Failed, FreePairList, FreeString, GetNth, ListLength, Parse, SetExtension], CompilerOps: TYPE USING [ LetterSwitches, StreamId, Transaction, AppendHerald, DefaultSwitches, DoTransaction, Punt, Start, Stop], ConvertUnsafe: TYPE USING [ToRope], ExecOps: TYPE USING [Command, Outcome], Feedback: TYPE USING [Handle, Procs, ProcsHandle], File: TYPE USING [Capability, nullCapability], FileParms: TYPE USING [BindingProc, nullActual], FileParmOps: TYPE USING [ClearAList, Finalize, Initialize, SetAList], FileStream: TYPE USING [Create, GetLeaderProperties, SetLength], Heap: TYPE USING [Create, Delete], Inline: TYPE USING [DIVMOD, LongDivMod], IO: TYPE USING [UserAborted], OSMiscOps: TYPE USING [DeleteFile, FindFile], Stream: TYPE USING [Delete, Handle], String: TYPE USING [AppendDecimal], Strings: TYPE USING [String, SubStringDescriptor, AppendChar, AppendString], TemporarySpecialExecOps: TYPE USING [], Time: TYPE USING [Packed, AppendCurrent, Current], TimeStamp: TYPE USING [Null]; FSInterface: PROGRAM [] IMPORTS CharIO, CIFS, CommandUtil, CompilerOps, ConvertUnsafe, FileStream, FileParmOps, Heap, Inline, IO, OSMiscOps, Stream, String, Strings, Time EXPORTS ExecOps, TemporarySpecialExecOps = { Command: TYPE = ExecOps.Command; StreamHandle: TYPE = Stream.Handle; feedback: Feedback.ProcsHandle; fbh: Feedback.Handle _ NIL; feedbackGoing: BOOL; userAbort: BOOL; -- set by ^DEL useLog: BOOL; -- for compiler.log for error reporting commandObject: CommandUtil.CommandObject _ [pos: 0, len: 0, data: NIL]; commandPtr: CommandUtil.CommandPtr _ @commandObject; SetCommandInput: PROC [cmd: Command] = { commandObject.pos _ 0; commandObject.data _ cmd; FOR i: CARDINAL IN [0..CARDINAL.LAST] DO c: CHAR = commandObject.data[i]; IF c # 11c AND c < 40c THEN {commandObject.len _ i; RETURN}; ENDLOOP}; log: StreamHandle _ NIL; GetCompilerLog: PUBLIC PROC RETURNS [StreamHandle] = {RETURN [log]}; SetTypescript: PROC = {IF log = NIL THEN log _ NewOutputStream["Compiler.Log"L]}; NewLine: PROC = {CharIO.PutChar[log, CharIO.CR]}; NewOutputStream: PROC [s: Strings.String] RETURNS [stream: StreamHandle] = { file: File.Capability; file _ OSMiscOps.FindFile[s, $write]; stream _ FileStream.Create[file]; FileStream.SetLength[stream, 0]}; CIFSInputStream: PROC [file: CIFS.OpenFile] RETURNS [StreamHandle] = { RETURN [IF file # NIL THEN FileStream.Create[CIFS.GetFC[file]] ELSE NIL]}; WriteHerald: PROC [s: StreamHandle, id: Strings.String] = { OPEN CharIO; herald: STRING _ [60]; CompilerOps.AppendHerald[herald]; PutLine[s, herald]; IF ~feedbackGoing AND feedback.create # NIL THEN fbh _ feedback.create[system: "Compiler"L, herald: herald]; feedbackGoing _ TRUE; IF id # NIL THEN {PutString[s, id]; PutString[s, " -- "L]}; herald.length _ 0; Time.AppendCurrent[herald]; PutLine[s, herald]}; WriteTime: PROC [time: LONG CARDINAL] = { OPEN CharIO; hr, min, sec: CARDINAL; f: NumberFormat _ [base: 10, unsigned: TRUE, zerofill: FALSE, columns: 1]; W: PROC [t: CARDINAL] = { IF t # 0 OR f.zerofill THEN { PutNumber[log, t, f]; PutChar[log, ':]; f _ [base: 10, unsigned: TRUE, zerofill: TRUE, columns: 2]}}; [min, sec] _ Inline.LongDivMod[time, 60]; [hr, min] _ Inline.DIVMOD[min, 60]; W[hr]; W[min]; PutNumber[log, sec, f]}; ErrorInit: PROC = { IF errorStream = NIL THEN IF useLog THEN errorStream _ log ELSE { errorName _ MakeErrorName[rootName]; errorStream _ NewOutputStream[errorName]; WriteHerald[errorStream, errorName]; CharIO.PutChar[errorStream, CharIO.CR]}}; MakeErrorName: PROC [root: Strings.String] RETURNS [Strings.String] = { RETURN [CommandUtil.SetExtension[ CommandUtil.CopyString[root, 2+("errlog"L).length], "errlog"L]]}; GetStream: PROC [id: CompilerOps.StreamId] RETURNS [s: Stream.Handle] = { SELECT id FROM $source => s _ sourceStream; $object => ERROR; -- should be obtained from CIFSFileParmPack $log => {IF errorStream = NIL THEN ErrorInit[]; s _ errorStream}; ENDCASE => ERROR; RETURN}; Initialize: PROC = { sourceFile _ CIFS.Open[ConvertUnsafe.ToRope[sourceName], CIFS.read]; parms.sourceStream _ sourceStream _ CIFSInputStream[sourceFile]; parms.source.version _ TimeStamp.Null; parms.source.version.time _ FileStream.GetLeaderProperties[sourceStream].create}; Finalize: PROC [started: BOOL] = { IF objectStream # NIL THEN Stream.Delete[objectStream]; IF sourceStream # NIL THEN Stream.Delete[sourceStream]; IF errorStream # NIL AND errorStream # log THEN Stream.Delete[errorStream]; objectStream _ sourceStream _ errorStream _ NIL; IF sourceFile # NIL THEN CIFS.Close[sourceFile]; sourceFile _ NIL; IF parms.nErrors # 0 AND started THEN CIFS.Delete[ConvertUnsafe.ToRope[objectName] ! CIFS.Error => TRUSTED {CONTINUE}]; IF errorName = NIL THEN { errorName _ MakeErrorName[rootName]; OSMiscOps.DeleteFile[errorName]}}; WriteErrlogName: PROC = { IF useLog OR log = NIL THEN RETURN; CharIO.PutString[log, " on "L]; CharIO.PutString[log, rootName]; CharIO.PutString[log, ".errlog"L]}; WriteClosing: PROC [startTime: Time.Packed] = { OPEN CharIO; PutString[log, sourceName]; PutString[log, " -- "L]; IF parms.nErrors # 0 THEN { errors _ TRUE; PutString[log, "aborted, "L]; PutDecimal[log, parms.nErrors]; PutString[log, " errors"L]; IF parms.nWarnings # 0 THEN { warnings _ TRUE; PutString[log, " and "L]; PutDecimal[log, parms.nWarnings]; PutString[log, " warnings"L]}; WriteErrlogName[]; PutString[log, ", time: "L]; WriteTime[Time.Current[]-startTime]} ELSE { PutString[log, "source tokens: "L]; PutDecimal[log, parms.sourceTokens]; PutString[log, ", time: "L]; WriteTime[Time.Current[]-startTime]; IF parms.objectBytes # 0 THEN { NewLine[]; PutString[log, " code bytes: "L]; PutDecimal[log, parms.objectBytes]; PutString[log, ", links: "L]; PutDecimal[log, parms.linkCount]; PutString[log, ", frame size: "L]; PutDecimal[log, parms.objectFrameSize]; IF parms.matched THEN PutChar[log, '.]}; IF parms.nWarnings # 0 THEN { warnings _ TRUE; NewLine[]; PutDecimal[log, parms.nWarnings]; PutString[log, " warnings"L]; WriteErrlogName[]}}; IF feedback.finishItem # NIL THEN { outcome: ExecOps.Outcome = SELECT TRUE FROM userAbort => aborted, parms.nErrors # 0 => IF parms.nWarnings # 0 THEN errorsAndWarnings ELSE errors, parms.nWarnings # 0 => warnings, ENDCASE => ok; msg: STRING _ [30]; IF parms.nErrors = 0 THEN Strings.AppendString[msg, "no"L] ELSE String.AppendDecimal[msg, parms.nErrors]; Strings.AppendString[msg, " errors"L]; IF parms.nWarnings # 0 THEN { Strings.AppendString[msg, ", "L]; String.AppendDecimal[msg, parms.nWarnings]; Strings.AppendString[msg, " warnings"L]}; feedback.finishItem[fbh, outcome, msg]}}; StopCompiler: PROC [startTime: Time.Packed] = { IF feedback.destroy # NIL THEN feedback.destroy[fbh, "End of compilation"L]; IF moduleCount > 1 THEN { NewLine[]; CharIO.PutString[log, "Total elapsed time: "L]; WriteTime[Time.Current[]-startTime]}; NewLine[]; Stream.Delete[log]; log _ NIL}; transaction: CompilerOps.Transaction; parms: POINTER TO CompilerOps.Transaction = @transaction; standardDefaults: CompilerOps.LetterSwitches = CompilerOps.DefaultSwitches[]; switchDefaults: CompilerOps.LetterSwitches; sourceName, objectName, errorName: Strings.String _ NIL; rootName: Strings.String _ NIL; sourceFile: CIFS.OpenFile _ NIL; sourceStream, objectStream, errorStream: StreamHandle _ NIL; errors, warnings: BOOL _ FALSE; moduleCount: CARDINAL; SetRoot: PROC [s: Strings.String] RETURNS [root: Strings.String] = { root _ CommandUtil.CopyString[s]; FOR i: CARDINAL IN [0..s.length) DO IF s[i] = '. THEN {root.length _ i; EXIT}; ENDLOOP}; Compile: PUBLIC PROC [cmd: Command] RETURNS [outcome: ExecOps.Outcome] = { fProcs: Feedback.Procs _ []; -- all NIL RETURN [CompileUsingFeedback[cmd, @fProcs]]}; CompileUsingFeedback: PUBLIC PROC [cmd: Command, feedbackProcs: Feedback.ProcsHandle] RETURNS [ExecOps.Outcome] = { StartPass: PROC [pass: CARDINAL] RETURNS [goOn: BOOL] = { IF feedback.noteProgress # NIL THEN feedback.noteProgress[fbh, pass ! IO.UserAborted => {userAbort _ TRUE; CONTINUE}]; RETURN [~userAbort]}; compilerStartTime, moduleStartTime: Time.Packed; scratchZone: UNCOUNTED ZONE _ Heap.Create[initial: 8, increment: 8]; fbh _ NIL; feedbackGoing _ FALSE; switchDefaults _ CompilerOps.DefaultSwitches[]; parms.fileParms _ FileParmOps.Initialize[scratchZone]; CompilerOps.Start[scratchZone]; compilerStartTime _ Time.Current[]; moduleCount _ 0; userAbort _ FALSE; SetCommandInput[cmd]; SetTypescript[]; feedback _ feedbackProcs; WriteHerald[log, NIL]; -- starts feedback stuff also errors _ warnings _ FALSE; DO args, results: CommandUtil.PairList; switches: Strings.String _ NIL; localPause: BOOL; sense: BOOL; BEGIN OPEN CharIO; parms.switches _ switchDefaults; parms.switches['p] _ FALSE; parms.debugPass _ CARDINAL.LAST; parms.getStream _ GetStream; parms.startPass _ StartPass; parms.objectBytes _ 0; parms.objectFrameSize _ 0; parms.linkCount _ 0; parms.nErrors _ 0; parms.nWarnings _ 0; parms.sourceTokens _ 0; [sourceName, args, results, switches] _ CommandUtil.Parse[ s: commandPtr, opX: 2+("mesa"L).length, resultX: 2+("bcd"L).length ! CommandUtil.Failed => {GO TO badSyntax}]; IF sourceName = NIL AND switches = NIL THEN EXIT; NewLine[]; PutString[log, "Command: "L]; CommandUtil.Echo[log, sourceName, args, results, switches]; IF CommandUtil.ListLength[results] > 1 THEN GO TO badSemantics; IF sourceName = NIL THEN GO TO globalSwitches; rootName _ SetRoot[IF CommandUtil.ListLength[results] = 1 THEN CommandUtil.GetNth[results, 0] ELSE sourceName]; IF switches # NIL THEN { sense _ TRUE; FOR i: CARDINAL IN [0..switches.length) DO c: CHAR = switches[i]; SELECT c FROM '-, '~ => sense _ ~sense; IN ['a..'z] => {parms.switches[c] _ sense; sense _ TRUE}; IN ['A..'Z] => { parms.switches[c+('a-'A)] _ sense; sense _ TRUE}; IN ['1..'5] => {parms.debugPass _ c-'0; sense _ TRUE}; ENDCASE; ENDLOOP; switches _ CommandUtil.FreeString[switches]}; sourceName _ CommandUtil.SetExtension[sourceName, "mesa"L]; parms.source.locator _ [sourceName, 0, sourceName.length]; IF CommandUtil.ListLength[results] # 0 THEN { objectName _ CommandUtil.GetNth[list: results, n: 0, delete: TRUE]; results _ CommandUtil.FreePairList[results]} ELSE objectName _ CommandUtil.CopyString[rootName, 2+("bcd"L).length]; objectName _ CommandUtil.SetExtension[objectName, "bcd"L]; parms.objectName _ CommandUtil.CopyString[objectName]; parms.objectFile _ File.nullCapability; moduleCount _ moduleCount + 1; IF feedback.beginItem # NIL THEN { item: Strings.String _ CommandUtil.CopyString[NIL, rootName.length + 12 + 53]; first: BOOL _ TRUE; Strings.AppendString[item, "Compiling: "L]; Strings.AppendString[item, rootName]; FOR c: CHAR IN ['a..'z] DO sd: BOOL = IF c = 'p THEN FALSE ELSE standardDefaults[c]; IF parms.switches[c] # sd THEN { IF first THEN {first _ FALSE; Strings.AppendChar[item, '/]}; IF sd THEN Strings.AppendChar[item, '-]; Strings.AppendChar[item, c]}; ENDLOOP; feedback.beginItem[fbh, item]; item _ CommandUtil.FreeString[item]}; useLog _ parms.switches['g]; parms.switches['g] _ FALSE; localPause _ parms.switches['p]; parms.switches['p] _ FALSE; Initialize[ ! ANY => {GOTO noSource}]; FileParmOps.SetAList[args]; BEGIN BindPattern: FileParms.BindingProc = { parms.pattern _ actual; parms.op _ IF actual = FileParms.nullActual THEN $compile ELSE $replace}; parms.fileParms.Binding[ formalId: ["$"L, 0, 1], formalType: [NIL, 0, 0], binder: BindPattern]; END; NewLine[]; moduleStartTime _ Time.Current[]; CompilerOps.DoTransaction[parms ! CompilerOps.Punt => {GO TO punt}]; Finalize[TRUE]; FileParmOps.ClearAList[]; WriteClosing[moduleStartTime]; EXITS globalSwitches => { objectName _ NIL; sense _ TRUE; FOR i: CARDINAL IN [0..switches.length) DO c: CHAR = switches[i]; SELECT c FROM '-, '~ => sense _ ~sense; IN ['a..'z] => {switchDefaults[c] _ sense; sense _ TRUE}; IN ['A..'Z] => {switchDefaults[c+('a-'A)] _ sense; sense _ TRUE}; ENDCASE => EXIT; ENDLOOP; switches _ CommandUtil.FreeString[switches]; args _ CommandUtil.FreePairList[args]}; noSource => { PutString[log, " -- source not found\n"L]; errors _ TRUE; parms.nErrors _ 1; WriteClosing[Time.Current[]]; args _ CommandUtil.FreePairList[args]}; badSemantics => { objectName _ NIL; errors _ TRUE; PutString[log, " -- Illegal command"L]; args _ CommandUtil.FreePairList[args]}; END; sourceName _ CommandUtil.FreeString[sourceName]; rootName _ CommandUtil.FreeString[rootName]; objectName _ CommandUtil.FreeString[objectName]; parms.objectName _ CommandUtil.FreeString[parms.objectName]; errorName _ CommandUtil.FreeString[errorName]; results _ CommandUtil.FreePairList[results]; NewLine[]; IF userAbort THEN { NewLine[]; CharIO.PutString[log, "... command aborted"L]; NewLine[]; GO TO truncateList}; IF (errors OR warnings) AND localPause THEN GO TO truncateList; REPEAT badSyntax => { NewLine[]; CharIO.PutString[log, "-- Illegal syntax"L]; errors _ TRUE}; truncateList => switchDefaults['p] _ TRUE; punt => {Finalize[TRUE]; WriteClosing[moduleStartTime]; NewLine[]}; ENDLOOP; StopCompiler[compilerStartTime]; CompilerOps.Stop[]; FileParmOps.Finalize[]; Heap.Delete[scratchZone]; RETURN [SELECT TRUE FROM userAbort => aborted, errors => errors, warnings => warnings, ENDCASE => ok]}; }.  FSInterface.mesa last modified by Satterthwaite, May 10, 1983 9:04 am feedback control command line input control special output stream control compiler sequencing * * * * * * M A I N B O D Y C O D E * * * * * * do the compilation pattern for replacement ʘJšœ™Jšœ4™4J˜šÏk ˜ Jšœœœœ6˜ZJšœœœ5˜Ešœ œœ˜J˜>J˜C—šœ œœ˜J˜&J˜A—Jšœœœ ˜#Jšœ œœ˜'Jšœ œœ˜2Jšœœœ˜.Jšœ œœ˜0Jšœ œœ.˜EJšœ œœ*˜@Jšœœœ˜"Jšœœœœ˜(Jšœœœ˜Jšœ œœ˜-Jšœœœ˜$Jšœœœ˜#Jšœ œœ9˜LJšœœœ˜'Jšœœœ"˜2Jšœ œœ˜J˜—šœ œ˜š˜Jšœœ6˜BJšœœ*˜G—Jšœ&˜-J˜Jšœ œ˜ Jšœœ˜#J˜J˜—Jšœ™˜J˜Jšœœ˜Jšœœ˜Jšœ œÏc˜Jšœœž'˜6J˜J˜—Jšœ™˜JšœBœ˜GJ˜4J˜šÏnœœ˜(J˜J˜š œœœœœ˜(Jšœœ˜ Jšœ œ œœ˜