-- file Interface.Mesa -- last modified by Satterthwaite, April 13, 1981 10:45 AM -- last modified by Sweet, March 27, 1981 8:50 AM -- last modified by Karlton, Feb 14, 1981 11:54 AM DIRECTORY AltoDisplay: TYPE USING [ CursorBits, Coordinate, DCB, DCBHandle, DCBchainHead, Cursor, CursorXY, MaxBitsPerLine, MaxScanLines], CharIO: TYPE USING [ CR, NumberFormat, GetChar, PutChar, PutDecimal, PutLine, PutNumber, PutString], CommandUtil: TYPE USING [ PairList, CopyString, Echo, Failed, FreePairList, FreeString, GetNth, ListLength, Parse, SetExtension, SkipNonBlank], CompilerOps: TYPE USING [ TableHandle, TableId, StreamId, Transaction, CompileAction, Punt, Sequencer], CoreSwapDefs: TYPE USING [level], FrameDefs: TYPE USING [IsBound], ImageDefs: TYPE USING [ FileRequest, AbortMesa, AddFileRequest, ImageTime, RunImage, StopMesa], Inline: TYPE USING [DIVMOD], KeyDefs: TYPE USING [Keys, KeyBits], MiniDisplay: TYPE USING [Append, Clear, Initialize, Finalize], MiscDefs: TYPE USING [CallDebugger, CommandLineCFA], MiscOps: TYPE USING [AllocateDebuggerBitmap, BitmapPages, ReleaseDebuggerBitmap], OsStaticDefs: TYPE USING [OsStatics], SDDefs: TYPE USING [sAddFileRequest, SD], Segments: TYPE USING [ FHandle, FP, FPHandle, SHandle, Read, Write, DeleteSegment, DestroyFile, EnumerateDirectory, GetFileTimes, InsertFile, LockFile, NewFile, NewSegment, SetFileTimes, UnlockFile], Storage: TYPE USING [FreePages, Pages], StreamDefs: TYPE USING [JumpToFA], Streams: TYPE USING [ Handle, CreateStream, Destroy, Ended, FileFromStream, GetBlock, GetIndex, PutChar, PutBlock, Restart, Suspend], String: TYPE USING [AppendChar, AppendString, EquivalentString], StringDefs: TYPE USING [MesaToBcplString, WordsForBcplString], Style: TYPE USING [ItemQueueInit], Time: TYPE USING [Append, AppendCurrent, Unpack]; Interface: PROGRAM [ explicitSwapping: BOOLEAN, tableSegment: ARRAY CompilerOps.TableId [parse..debug] OF CompilerOps.TableHandle] IMPORTS CharIO, CommandUtil, CompilerOps, CoreSwapDefs, FrameDefs, ImageDefs, Inline, MiniDisplay, MiscDefs, MiscOps, Segments, Storage, StreamDefs, Streams, String, StringDefs, Style, Time EXPORTS CompilerOps, Style = BEGIN -- command input formatting: BOOLEAN = FrameDefs.IsBound[Style.ItemQueueInit]; headerComment: PUBLIC STRING _ NIL; commandStream: Streams.Handle; comCmRequest: ImageDefs.FileRequest _ [ name: "Com.Cm.", file: NIL, access: Segments.Read, link: ]; SetCommandInput: PROC = INLINE { IF comCmRequest.file = NIL THEN { comCmRequest.file _ Segments.NewFile[comCmRequest.name, Segments.Read]; Segments.LockFile[comCmRequest.file]}; commandStream _ Streams.CreateStream[comCmRequest.file, Segments.Read]; IF ~image THEN StreamDefs.JumpToFA[commandStream, @(MiscDefs.CommandLineCFA[]).fa] ELSE CommandUtil.SkipNonBlank[commandStream]}; -- command logging log: Streams.Handle; logName: STRING = IF formatting THEN "Formatter.log." ELSE "Compiler.Log."; logRequest: ImageDefs.FileRequest _ [ name: logName, file: NIL, access: Segments.Write, link: ]; SetTypescript: PROC = INLINE { IF logRequest.file = NIL THEN { logRequest.file _ Segments.NewFile[logName, Segments.Write]; Segments.LockFile[logRequest.file]}; log _ Streams.CreateStream[logRequest.file, Segments.Write]}; NewLine: PROC = {CharIO.PutChar[log, CharIO.CR]}; WriteHerald: PROC [s: Streams.Handle, id: STRING] = { OPEN CharIO; time: STRING _ [20]; PutString[s, IF formatting THEN "Mesa Formatter 7.0/6.1 of "L ELSE "Mesa Compiler 6.1 of "L]; time.length _ 0; Time.Append[time, Time.Unpack[ImageDefs.ImageTime[]]]; PutLine[s, time]; IF id # NIL THEN {PutString[s, id]; PutString[s, " -- "L]}; time.length _ 0; Time.AppendCurrent[time]; PutLine[s, time]}; WriteTime: PROC [sec: CARDINAL] = { OPEN CharIO; hr, min: 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.DIVMOD[sec, 60]; [hr, min] _ Inline.DIVMOD[min, 60]; W[hr]; W[min]; PutNumber[log, sec, f]}; -- user feedback fontSeg: Segments.SHandle; fontRequest: ImageDefs.FileRequest _ [ name: "sysfont.al", file: NIL, access: Segments.Read, link: ]; -- compiler input and output stream management sourceName: STRING; objectName: STRING; rootName: STRING _ [40]; sourceFile: Segments.FHandle _ NIL; sourceStream: Streams.Handle _ NIL; objectFile: Segments.FHandle _ NIL; objectStream: Streams.Handle _ NIL; scratchFile: Segments.FHandle _ NIL; ObjectInit: PROC = INLINE { IF objectFile = NIL THEN { objectFile _ Segments.NewFile[objectName, Segments.Write]; Segments.LockFile[objectFile]}; objectStream _ Streams.CreateStream[objectFile, Segments.Write]}; ObjectReset: PROC [keep: BOOLEAN] = INLINE { IF keep THEN { IF objectFile # NIL THEN Segments.UnlockFile[objectFile]; IF objectStream # NIL THEN Streams.Destroy[objectStream]} ELSE { IF objectStream # NIL THEN Streams.Destroy[objectStream]; IF objectFile # NIL THEN { IF formatting THEN { sourceFile _ Streams.FileFromStream[sourceStream]; Segments.LockFile[sourceFile]; CopyFile[from: sourceFile, to: objectFile]; Segments.UnlockFile[objectFile]; Segments.UnlockFile[sourceFile]; sourceFile _ NIL} ELSE {Segments.UnlockFile[objectFile]; Segments.DestroyFile[objectFile]}}}; objectStream _ NIL; objectFile _ NIL}; errorFile: Segments.FHandle _ NIL; errorStream: Streams.Handle _ NIL; ErrorInit: PROC = { errorName: STRING _ CommandUtil.SetExtension[ CommandUtil.CopyString[rootName, 2+("errlog"L).length], "errlog"L]; IF errorFile = NIL THEN { errorFile _ Segments.NewFile[errorName, Segments.Write]; Segments.LockFile[errorFile]}; errorStream _ Streams.CreateStream[errorFile, Segments.Write]; WriteHerald[errorStream, errorName]; CharIO.PutChar[errorStream, CharIO.CR]; errorName _ CommandUtil.FreeString[errorName]}; ErrorReset: PROC = INLINE { IF errorFile # NIL THEN { Segments.UnlockFile[errorFile]; SELECT TRUE FROM errorStream # NIL => {errorStream.destroy[errorStream]; errorStream _ NIL}; errorFile # NIL => Segments.DestroyFile[errorFile]; ENDCASE; errorFile _ NIL}}; GetStream: PROC [id: CompilerOps.StreamId] RETURNS [s: Streams.Handle] = { SELECT id FROM source => s _ sourceStream; object => {IF objectStream = NIL THEN ObjectInit[]; s _ objectStream}; log => {IF errorStream = NIL THEN ErrorInit[]; s _ errorStream}; ENDCASE => ERROR; RETURN}; -- compiler sequencing Initialize: PROC = { IF log # NIL THEN Streams.Suspend[log]; IF commandStream # NIL THEN Streams.Suspend[commandStream]; moduleStartTime _ secondsClock.low}; Finalize: PROC [started: BOOLEAN] = { ObjectReset[keep: ~started OR parms.nErrors = 0]; IF sourceStream # NIL THEN {Streams.Destroy[sourceStream]; sourceStream _ NIL}; ErrorReset[]; IF commandStream # NIL THEN Streams.Restart[commandStream]; IF log # NIL THEN Streams.Restart[log]}; CopyFile: PROCEDURE [from, to: Segments.FHandle] = BEGIN OPEN Streams; bufSize: CARDINAL = 20; buffer: POINTER TO PACKED ARRAY [0..bufSize*256*2) OF CHARACTER = Storage.Pages[bufSize]; words: CARDINAL; end, odd: BOOLEAN _ FALSE; scratch, source: Streams.Handle; scratch _ CreateStream[to, Segments.Write]; source _ CreateStream[from, Segments.Read]; UNTIL end DO words _ GetBlock[source, buffer, bufSize*256]; IF (end _ Ended[source]) AND GetIndex[source] MOD 2 # 0 THEN { odd _ TRUE; words _ words - 1}; [] _ PutBlock[scratch, buffer, words]; IF odd THEN PutChar[scratch, buffer[words*2]]; ENDLOOP; Storage.FreePages[buffer]; Segments.SetFileTimes[file: to, create: Segments.GetFileTimes[file: from].create]; source.destroy[source]; scratch.destroy[scratch]; END; WriteClosing: PROC = { OPEN AltoDisplay, CharIO; IF (CursorXY.y _ CursorXY.y+16) > MaxScanLines-64 THEN CursorXY.y _ 64; PutString[log, sourceName]; PutString[log, " -- "L]; IF parms.nErrors # 0 THEN { CursorXY.x _ MIN[MaxBitsPerLine-64, CursorXY.x+16]; 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]}; PutString[log, "on "L]; PutString[log, rootName]; PutString[log, ".errlog"L]} ELSE { PutString[log, "source tokens: "L]; PutNumber[log, parms.sourceTokens, [base:10,zerofill:FALSE,unsigned:TRUE,columns:1]]; PutString[log, ", time: "L]; WriteTime[secondsClock.low-moduleStartTime]; IF ~formatting AND 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.nWarnings # 0 THEN { warnings _ TRUE; NewLine[]; PutDecimal[log, parms.nWarnings]; PutString[log, " warnings on "L]; PutString[log, rootName]; PutString[log, ".errlog"L]}}}; StopCompiler: PROC [toRun: BOOLEAN _ FALSE] = { IF moduleCount > 1 THEN { NewLine[]; CharIO.PutString[log, "Total elapsed time: "L]; WriteTime[secondsClock.low-compilerStartTime]; NewLine[]}; Segments.UnlockFile[logRequest.file]; logRequest.file _ NIL; Streams.Destroy[log]; Segments.UnlockFile[comCmRequest.file]; comCmRequest.file _ NIL; Streams.Destroy[commandStream]; MiniDisplay.Finalize[]; IF fontSeg # NIL THEN { Segments.DeleteSegment[fontSeg]; fontSeg _ NIL; Segments.UnlockFile[fontRequest.file]; fontRequest.file _ NIL}; IF SwitchDefaults['q] AND (~toRun OR errors OR warnings) THEN { -- got here from Debugger CoreSwapDefs.level _ -1; MiscOps.AllocateDebuggerBitmap[MiscOps.BitmapPages]; MiscDefs.CallDebugger[SELECT TRUE FROM errors => "Errors logged"L, warnings => "Warnings logged"L, ENDCASE => "Compilation complete"L]}; IF (errors OR warnings) AND SwitchDefaults['p] THEN { BlankCursor: AltoDisplay.CursorBits = ALL[0]; QueryCursor: AltoDisplay.CursorBits = [ 2000b, 74000b, 140000b, 12767b, 12525b, 53566b, 111113b, 163100b, 0b, 0b, 154000b, 53520b, 62520b, 53360b, 155440b, 140b]; ReadKeys: PROC [p: POINTER TO KeyDefs.KeyBits] = { p^ _ KeyDefs.Keys^; LOOPHOLE[p, POINTER]^ _ 0; -- mouse, keyset p.LeftShift _ p.Ctrl _ p.Spare3 _ up}; savedKeys, newKeys: KeyDefs.KeyBits; RTC: POINTER TO MACHINE DEPENDENT RECORD [high: [0..4096), low: [0..16)] = LOOPHOLE[430B]; savedTime: CARDINAL; state: {off, on1, on2}; ReadKeys[@savedKeys]; AltoDisplay.Cursor^ _ BlankCursor; state _ off; savedTime _ RTC.high; DO IF RTC.high # savedTime THEN { SELECT state FROM off => {AltoDisplay.Cursor^ _ QueryCursor; state _ on1}; on1 => state _ on2; on2 => {AltoDisplay.Cursor^ _ BlankCursor; state _ off}; ENDCASE; savedTime _ RTC.high}; ReadKeys[@newKeys]; IF newKeys # savedKeys THEN EXIT; ENDLOOP}}; transaction: CompilerOps.Transaction; parms: POINTER TO CompilerOps.Transaction = @transaction; SwitchDefaults: PACKED ARRAY CHARACTER ['a..'z] OF BOOLEAN _ InitDefaults; InitDefaults: PACKED ARRAY CHARACTER ['a..'z] OF BOOLEAN = [ --a/k/u b/l/v c/m/w d/n/x e/o/y f/p/z g/q h/r i/s j/t -- TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE]; FindFiles: PROC [fp: Segments.FPHandle, s: STRING] RETURNS [BOOLEAN] = { IF s.length = sourceName.length AND String.EquivalentString[sourceName, s] THEN { sourceFile _ Segments.InsertFile[fp, Segments.Read]; Segments.LockFile[sourceFile]}; IF ~formatting AND s.length = objectName.length AND String.EquivalentString[objectName, s] THEN { objectFile _ Segments.InsertFile[fp, Segments.Write]; Segments.LockFile[objectFile]}; IF formatting AND formatterOverwrite AND s.length = ("Formatter.scratch$."L).length AND String.EquivalentString["Formatter.scratch$."L, s] THEN { scratchFile _ Segments.InsertFile[fp, Segments.Write]; Segments.LockFile[scratchFile]}; IF s.length = rootName.length + (".errlog."L).length THEN { errorName: STRING _ [40]; String.AppendString[errorName, rootName]; String.AppendString[errorName, ".errlog."L]; IF String.EquivalentString[errorName, s] THEN { errorFile _ Segments.InsertFile[fp, Segments.Write]; Segments.LockFile[errorFile]}}; RETURN [sourceFile # NIL AND errorFile # NIL AND (formatting OR objectFile # NIL)]}; errors, warnings: BOOLEAN; formatterOverwrite: BOOLEAN; moduleCount: CARDINAL; compilerStartTime, moduleStartTime: CARDINAL; secondsClock: POINTER TO MACHINE DEPENDENT RECORD [high, low: CARDINAL] = LOOPHOLE[572B]; -- * * * * * * M A I N B O D Y C O D E * * * * * * image: BOOLEAN = (SDDefs.SD[SDDefs.sAddFileRequest] # 0); bitmapFrozen: BOOLEAN _ FALSE; dcbSpace: ARRAY [0..SIZE[AltoDisplay.DCB]+1) OF UNSPECIFIED; dcb, saveDCB: AltoDisplay.DCBHandle; -- cursor management L1: WORD = 147777b; R1: WORD = 177763b; M1: WORD = 177177b; Two: WORD = 147763b; ClearCursor: PROC = INLINE {AltoDisplay.Cursor^ _ ALL[177777b]}; SetCursor: PROC [position: {upper, middle, lower}, row: WORD] = { SELECT position FROM upper => AltoDisplay.Cursor[2] _ AltoDisplay.Cursor[3] _ row; middle => AltoDisplay.Cursor[7] _ AltoDisplay.Cursor[8] _ row; lower => AltoDisplay.Cursor[12] _ AltoDisplay.Cursor[13] _ row; ENDCASE}; UpdateCursor: PROC [pass: CARDINAL] RETURNS [goOn: BOOLEAN _ TRUE] = { ClearCursor[]; IF errors THEN {AltoDisplay.Cursor[5] _ 125252b; AltoDisplay.Cursor[10] _ 052525b}; SELECT pass FROM 1 => SetCursor[middle, M1]; 2 => {SetCursor[upper, L1]; SetCursor[lower, R1]}; 3 => {SetCursor[upper, R1]; SetCursor[middle, M1]; SetCursor[lower, L1]}; 4 => {SetCursor[upper, Two]; SetCursor[lower, Two]}; 5 => {SetCursor[upper, Two]; SetCursor[middle, M1]; SetCursor[lower, Two]}; 6 => {SetCursor[upper, Two]; SetCursor[middle, Two]; SetCursor[lower, Two]} ENDCASE}; saveCursor: AltoDisplay.CursorBits; saveCoordinate: AltoDisplay.Coordinate; -- add cleanup procedure IF image THEN { ImageDefs.AddFileRequest[@comCmRequest]; ImageDefs.AddFileRequest[@logRequest]; ImageDefs.AddFileRequest[@fontRequest]} -- wait for restart ELSE { fp: Segments.FP _ MiscDefs.CommandLineCFA[].fp; comCmRequest.file _ Segments.InsertFile[@fp, Segments.Read]; Segments.LockFile[comCmRequest.file]}; STOP; -- wait for restart (noop unless image) dcb _ @dcbSpace[0]; IF LOOPHOLE[dcb, CARDINAL] MOD 2 # 0 THEN dcb _ dcb + 1; dcb^ _ AltoDisplay.DCB[NIL, high, white, 0, 0, NIL, 0]; saveDCB _ AltoDisplay.DCBchainHead^; AltoDisplay.DCBchainHead^ _ dcb; saveCoordinate _ AltoDisplay.CursorXY^; saveCursor _ AltoDisplay.Cursor^; ClearCursor[]; AltoDisplay.CursorXY^ _ [64,64]; IF fontRequest.file = NIL THEN { fontRequest.file _ Segments.NewFile[fontRequest.name, Segments.Read]; Segments.LockFile[fontRequest.file]}; fontSeg _ IF fontRequest.file # NIL THEN Segments.NewSegment[fontRequest.file, 1, 0, Segments.Read] ELSE NIL; MiniDisplay.Initialize[fontSeg]; START CompilerOps.Sequencer[explicitSwapping, tableSegment]; -- do the compilation SetCommandInput[]; SetTypescript[]; compilerStartTime _ secondsClock.low; moduleCount _ 0; WriteHerald[log, NIL]; errors _ warnings _ formatterOverwrite _ FALSE; WHILE TRUE DO SetRoot: PROC [root, s: STRING] = { root.length _ 0; FOR i: CARDINAL IN [0..s.length) DO IF s[i] = '. THEN EXIT; String.AppendChar[root, s[i]]; ENDLOOP}; args, results: CommandUtil.PairList; switches: STRING; sense: BOOLEAN; BEGIN OPEN CharIO; ClearCursor[]; MiniDisplay.Clear[]; parms.op _ IF formatting THEN format ELSE compile; parms.system _ alto; parms.getStream _ GetStream; parms.startPass _ UpdateCursor; parms.switches _ SwitchDefaults; parms.switches['p] _ FALSE; parms.debugPass _ LAST[CARDINAL]; [sourceName, args, results, switches] _ CommandUtil.Parse[ s: commandStream, opX: 2+("mesa").length, resultX: 2+("bcd").length ! CommandUtil.Failed => GO TO badSyntax]; IF sourceName = NIL AND switches = NIL THEN EXIT; NewLine[]; PutString[log, "Command: "]; CommandUtil.Echo[log, sourceName, args, results, switches]; IF CommandUtil.ListLength[results] > 1 THEN GO TO badSemantics; IF sourceName = NIL THEN GO TO globalSwitches; SetRoot[rootName, IF CommandUtil.ListLength[results] = 1 THEN CommandUtil.GetNth[results, 0] ELSE sourceName]; IF switches # NIL THEN { i: CARDINAL; CompleteFileName: PROC RETURNS [fileName: STRING, bcpl: BOOLEAN] = { OPEN String; root: STRING _ [40]; extension: STRING _ [40]; SetRoot[root, sourceName]; IF root.length = sourceName.length THEN AppendString[extension, "image"L] ELSE FOR j: CARDINAL IN [root.length+1 .. sourceName.length) DO AppendChar[extension, sourceName[j]] ENDLOOP; fileName _ CommandUtil.CopyString[root, 2+extension.length]; fileName _ CommandUtil.SetExtension[fileName, extension]; bcpl _ EquivalentString[extension, "run"L]; RETURN}; WriteCommandFile: PROC [fileName: STRING] = { copy: Streams.Handle; copy _ Streams.CreateStream[ Segments.NewFile["com.cm."L, Segments.Write], Segments.Write]; FOR j: CARDINAL IN [0..fileName.length-1) DO PutChar[copy, fileName[j]] ENDLOOP; IF switches.length > i+1 THEN { PutChar[copy, '/]; FOR j: CARDINAL IN (i..switches.length) DO PutChar[copy, switches[j]] ENDLOOP}; IF Streams.Ended[commandStream] THEN PutChar[copy, CR] ELSE { PutChar[copy, ' ]; UNTIL Streams.Ended[commandStream] DO PutChar[copy, GetChar[commandStream]] ENDLOOP}; Streams.Destroy[copy]}; Run: PROC [fileName: STRING, bcpl: BOOLEAN] = { IF bcpl THEN { p: POINTER = OsStaticDefs.OsStatics.EventVector; EVItem: TYPE = MACHINE DEPENDENT RECORD [ type: [0..7777B], length: [0..17B]]; p^ _ EVItem[6, StringDefs.WordsForBcplString[fileName.length]+1]; StringDefs.MesaToBcplString[fileName, p+1]; ImageDefs.StopMesa[]} ELSE ImageDefs.RunImage[Segments.NewSegment[ file: Segments.NewFile[fileName, Segments.Read], base: 1, pages: 1, access: Segments.Read]]}; i _ 0; sense _ TRUE; WHILE i < switches.length DO c: CHARACTER = switches[i]; SELECT c FROM '-, '~ => sense _ ~sense; 'r, 'R => { fileName: STRING; bcpl: BOOLEAN; [fileName, bcpl] _ CompleteFileName[]; WriteCommandFile[fileName]; StopCompiler[TRUE]; Run[fileName, bcpl ! ANY => ImageDefs.AbortMesa]}; -- never returns 'o, 'O => { [] _ CommandUtil.FreeString[headerComment]; GOTO headerLine}; IN ['a..'z] => {parms.switches[c] _ sense; sense _ TRUE}; IN ['A..'Z] => { parms.switches[c+('a-'A)] _ sense; sense _ TRUE}; '! => {MiscDefs.CallDebugger[NIL]; bitmapFrozen _ TRUE}; IN ['1..'5] => {parms.debugPass _ c-'0; sense _ TRUE}; ENDCASE; i _ i+1; ENDLOOP; switches _ CommandUtil.FreeString[switches]}; parms.sourceId _ sourceName _ CommandUtil.SetExtension[sourceName, "mesa"]; parms.fileMap _ args; IF CommandUtil.ListLength[results] # 0 THEN { IF ~formatting THEN objectName _ CommandUtil.GetNth[list: results, n: 0, delete: TRUE]; results _ CommandUtil.FreePairList[results]} ELSE IF ~formatting THEN objectName _ CommandUtil.CopyString[rootName, 2+("bcd").length]; IF ~formatting THEN objectName _ CommandUtil.SetExtension[objectName, "bcd"]; parms.objectId _ IF formatting THEN NIL ELSE objectName; formatterOverwrite _ parms.switches['t] OR parms.switches['v] OR parms.switches['z]; BEGIN ENABLE ANY => GO TO punt; Segments.EnumerateDirectory[FindFiles]; IF formatting AND formatterOverwrite AND sourceFile # NIL THEN { IF scratchFile = NIL THEN { scratchFile _ Segments.NewFile["Formatter.scratch$."L, Segments.Write]; Segments.LockFile[scratchFile]}; CopyFile[from: sourceFile, to: scratchFile]; objectStream _ Streams.CreateStream[sourceFile, Segments.Write]; objectFile _ sourceFile; Segments.SetFileTimes[objectFile]; sourceFile _ scratchFile; scratchFile _ NIL}; IF sourceFile = NIL THEN GO TO noSource; parms.sourceVersion _ [0, 0, Segments.GetFileTimes[sourceFile].create]; sourceStream _ Streams.CreateStream[sourceFile, Segments.Read]; Segments.UnlockFile[sourceFile]; sourceFile _ NIL; END; IF ~bitmapFrozen THEN { IF ~parms.switches['d] THEN MiscOps.ReleaseDebuggerBitmap[]; bitmapFrozen _ TRUE}; NewLine[]; moduleCount _ moduleCount + 1; MiniDisplay.Append[IF formatting THEN "Formatting: "L ELSE "Compiling: "L]; MiniDisplay.Append[rootName]; BEGIN cs: STRING _ [1]; first: BOOLEAN _ TRUE; cs.length _ 1; FOR c: CHARACTER IN ['a..'z] DO sd: BOOLEAN = IF c = 'p THEN FALSE ELSE InitDefaults[c]; IF parms.switches[c] # sd THEN { IF first THEN {first _ FALSE; MiniDisplay.Append["/"L]}; IF sd THEN MiniDisplay.Append["~"L]; cs[0] _ c; MiniDisplay.Append[cs]}; ENDLOOP; END; Initialize[]; CompilerOps.CompileAction[parms ! CompilerOps.Punt => GO TO punt]; ClearCursor[]; MiniDisplay.Append[" -- "L]; MiniDisplay.Append[IF parms.nErrors=0 THEN "ok"L ELSE "failed"L]; Finalize[TRUE]; WriteClosing[]; EXITS globalSwitches => { objectName _ NIL; results _ CommandUtil.FreePairList[results]; sense _ TRUE; FOR i: CARDINAL IN [0..switches.length) DO c: CHARACTER = switches[i]; SELECT c FROM '-, '~ => sense _ ~sense; '! => {MiscDefs.CallDebugger[NIL]; bitmapFrozen _ TRUE}; 'o, 'O => headerComment _ CommandUtil.FreeString[headerComment]; 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]}; headerLine => { headerComment _ sourceName; sourceName _ NIL; objectName _ NIL; results _ CommandUtil.FreePairList[results]; switches _ CommandUtil.FreeString[switches]}; badSemantics => { objectName _ NIL; results _ CommandUtil.FreePairList[results]; errors _ TRUE; PutString[log, " -- Illegal command"]}; noSource => { Finalize[FALSE]; errors _ TRUE; PutChar[log, CR]; PutString[log, sourceName]; PutString[log, " -- File error"]}; END; sourceName _ CommandUtil.FreeString[sourceName]; IF ~formatting THEN objectName _ CommandUtil.FreeString[objectName]; args _ CommandUtil.FreePairList[args]; NewLine[]; IF (errors OR warnings) AND parms.switches['p] THEN GO TO truncateList; REPEAT badSyntax => { NewLine[]; CharIO.PutString[log, "-- Illegal syntax"]; errors _ TRUE}; truncateList => SwitchDefaults['p] _ TRUE; punt => {ClearCursor[]; Finalize[TRUE]; WriteClosing[]; NewLine[]}; ENDLOOP; StopCompiler[]; AltoDisplay.CursorXY^ _ saveCoordinate; AltoDisplay.Cursor^ _ saveCursor; AltoDisplay.DCBchainHead^ _ saveDCB; ImageDefs.StopMesa[]; END.