-- file Interface.Mesa -- last modified by Sandman, Jan 15, 1980 2:07 PM DIRECTORY AltoDisplay: FROM "altodisplay" USING [DCB, DCBHandle, DCBchainHead, MaxBitsPerLine, MaxScanLines], AltoFileDefs: FROM "altofiledefs" USING [FP], CharIO: FROM "chario" USING [ CR, NumberFormat, PutChar, PutDecimal, PutLine, PutNumber, PutString], CompilerOps: FROM "compilerops" USING [TableId, Transaction, Compile, NoSource, Punt, Sequencer], DirectoryDefs: FROM "directorydefs" USING [EnumerateDirectory], ImageDefs: FROM "imagedefs" USING [ CleanupItem, CleanupMask, CleanupProcedure, FileRequest, AddCleanupProcedure, AddFileRequest, AbortMesa, ImageTime, RunImage, StopMesa], InlineDefs: FROM "inlinedefs" USING [DIVMOD], KeyDefs: FROM "keydefs" USING [Keys, KeyBits], MiscDefs: FROM "miscdefs" USING [CallDebugger, CommandLineCFA], OsStaticDefs: FROM "osstaticdefs" USING [OsStatics], SDDefs: FROM "sddefs" USING [sAddFileRequest, SD], SegmentDefs: FROM "segmentdefs" USING [ FileHandle, FileSegmentHandle, DefaultVersion, DestroyFile, InsertFile, LockFile, NewFile, NewFileSegment, UnlockFile], StreamDefs: FROM "streamdefs" USING [ StreamHandle, StreamObject, Append, Read, Write, CloseDiskStream, CreateByteStream, JumpToFA, OpenDiskStream], StringDefs: FROM "stringdefs" USING [ AppendChar, AppendString, EquivalentString, MesaToBcplString, WordsForBcplString], SystemDefs: FROM "systemdefs" USING [ AllocateHeapNode, AllocateHeapString, FreeHeapString, FreeHeapNode], TimeDefs: FROM "timedefs" USING [DefaultTime, AppendDayTime, UnpackDT]; Interface: PROGRAM [ explicitSwapping: BOOLEAN, tableSegment: ARRAY CompilerOps.TableId OF SegmentDefs.FileSegmentHandle] IMPORTS CharIO, CompilerOps, DirectoryDefs, ImageDefs, InlineDefs, MiscDefs, SegmentDefs, StreamDefs, StringDefs, SystemDefs, TimeDefs EXPORTS CompilerOps = BEGIN OPEN StreamDefs; -- command line input control commandStream: StreamHandle; comCmRequest: ImageDefs.FileRequest _ [ name: "Com.Cm.", file: NIL, access: Read, link: ]; SetCommandInput: PROCEDURE = BEGIN c: CHARACTER; commandStream _ CreateByteStream[comCmRequest.file, Read]; IF ~image THEN JumpToFA[commandStream, @(MiscDefs.CommandLineCFA[]).fa] ELSE BEGIN [] _ SkipStreamBlanks[]; UNTIL commandStream.endof[commandStream] OR (c_commandStream.get[commandStream]) = ' OR c = CharIO.CR DO NULL ENDLOOP; END; END; SkipStreamBlanks: PROCEDURE RETURNS [c: CHARACTER] = BEGIN OPEN CharIO; UNTIL commandStream.endof[commandStream] DO c _ commandStream.get[commandStream]; IF c # ' AND c # CR THEN EXIT; ENDLOOP; END; CommandLineID: PROCEDURE [s: STRING] = BEGIN OPEN CharIO; c: CHARACTER; s.length _ 0; c _ SkipStreamBlanks[]; UNTIL commandStream.endof[commandStream] OR c = ' OR c = CR DO StringDefs.AppendChar[s, c]; c _ commandStream.get[commandStream]; ENDLOOP; END; -- special output stream control log: StreamHandle; logName: STRING = "Compiler.Log."; logRequest: ImageDefs.FileRequest _ [ name: logName, file: NIL, access: Write+Append, link: ]; SetTypescript: PROCEDURE = BEGIN OPEN SegmentDefs; IF logRequest.file = NIL THEN logRequest.file _ NewFile[logName, Write+Append, DefaultVersion]; log _ CreateByteStream[logRequest.file, Write+Append]; END; NewLine: PROCEDURE = BEGIN CharIO.PutChar[log, CharIO.CR] END; errorStream: StreamHandle; ErrorPut: PROCEDURE [s: StreamHandle, c: CHARACTER] = BEGIN OPEN SegmentDefs; errorName: STRING; IF errorStream = NIL THEN BEGIN errorName _ SystemDefs.AllocateHeapString[rootName.length + (".errlog"L).length]; StringDefs.AppendString[errorName, rootName]; StringDefs.AppendString[errorName, ".errlog"L]; errorStream _ CreateByteStream[ IF errorFile=NIL THEN SegmentDefs.NewFile[errorName, Write+Append, SegmentDefs.DefaultVersion] ELSE errorFile, Write+Append]; WriteHerald[errorStream, errorName]; errorStream.put[errorStream, CharIO.CR]; SystemDefs.FreeHeapString[errorName]; END; errorStream.put[errorStream, c]; END; ErrorDestroy: PROCEDURE [s: StreamHandle] = BEGIN SELECT TRUE FROM errorStream # NIL => errorStream.destroy[errorStream]; errorFile # NIL => SegmentDefs.DestroyFile[errorFile]; ENDCASE; SystemDefs.FreeHeapNode[s]; END; WriteHerald: PROCEDURE [s: StreamHandle, id: STRING] = BEGIN OPEN TimeDefs, CharIO; time: STRING _ [20]; PutString [s, "Alto/Mesa Compiler 6.0c of "L]; time.length _ 0; AppendDayTime[time, UnpackDT[ImageDefs.ImageTime[]]]; PutLine[s, time]; IF id # NIL THEN BEGIN PutString[s, id]; PutString[s, " -- "L] END; time.length _ 0; AppendDayTime[time, UnpackDT[DefaultTime]]; PutLine[s, time]; END; WriteTime: PROCEDURE [sec: CARDINAL] = BEGIN OPEN CharIO; hr, min: CARDINAL; f: NumberFormat _ [base:10, unsigned:TRUE, zerofill:FALSE, columns:1]; W: PROCEDURE [t: CARDINAL] = BEGIN IF t # 0 OR f.zerofill THEN BEGIN PutNumber[log, t, f]; PutChar[log, ':]; f _ [base:10, unsigned:TRUE, zerofill:TRUE, columns:2]; END; END; [min, sec] _ InlineDefs.DIVMOD[sec, 60]; [hr, min] _ InlineDefs.DIVMOD[min, 60]; W[hr]; W[min]; PutNumber[log, sec, f]; END; -- cleanup of files/streams compilerCleanupItem: ImageDefs.CleanupItem _ [ proc: CompilerCleanup, mask: ImageDefs.CleanupMask[InLd] + ImageDefs.CleanupMask[OutLd], link: ]; CompilerCleanup: ImageDefs.CleanupProcedure = BEGIN SELECT why FROM OutLd => IF errorStream # NIL THEN CloseDiskStream[errorStream]; InLd => IF errorStream # NIL THEN OpenDiskStream[errorStream]; ENDCASE; END; -- table storage management tableRequest: ImageDefs.FileRequest _ [ name: "Swatee.", file: NIL, access: Read+Write+Append, link: ]; -- compiler sequencing Initialize: PROCEDURE = BEGIN IF log # NIL THEN CloseDiskStream[log]; IF commandStream # NIL THEN CloseDiskStream[commandStream]; moduleStartTime _ secondsClock.low; END; Finalize: PROCEDURE = BEGIN SELECT TRUE FROM parms.nErrors = 0 => IF parms.object.stream # NIL THEN parms.object.stream.destroy[parms.object.stream]; ENDCASE => BEGIN IF parms.object.stream # NIL THEN BEGIN objectFile _ WITH s: parms.object.stream SELECT FROM Disk => objectFile _ s.file, ENDCASE => ERROR; SegmentDefs.LockFile[objectFile]; parms.object.stream.destroy[parms.object.stream]; SegmentDefs.UnlockFile[objectFile]; END; IF objectFile # NIL THEN BEGIN IF oldObjectFile THEN SegmentDefs.UnlockFile[objectFile]; SegmentDefs.DestroyFile[objectFile]; END; END; IF parms.source.stream # NIL THEN parms.source.stream.destroy[parms.source.stream]; IF parms.error.stream # NIL THEN parms.error.stream.destroy[parms.error.stream]; IF commandStream # NIL THEN OpenDiskStream[commandStream]; IF log # NIL THEN OpenDiskStream[log]; END; WriteClosing: PROCEDURE = BEGIN OPEN CharIO; IF (cursorLoc.y _ cursorLoc.y+16) > AltoDisplay.MaxScanLines-64 THEN cursorLoc.y _ 64; PutString[log, sourceName]; PutString[log, " -- "L]; IF parms.nErrors # 0 THEN BEGIN cursorLoc.x _ MIN[AltoDisplay.MaxBitsPerLine-64, cursorLoc.x+16]; errors _ TRUE; PutString[log, "aborted, "L]; PutDecimal[log, parms.nErrors]; PutString[log, " errors "L]; IF parms.nWarnings # 0 THEN BEGIN warnings _ TRUE; PutString[log, "and "L]; PutDecimal[log, parms.nWarnings]; PutString[log, " warnings "L]; END; PutString[log, "on "L]; PutString[log, rootName]; PutString[log, ".errlog"L]; END ELSE BEGIN 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 parms.objectBytes # 0 THEN BEGIN 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]; END; IF parms.nWarnings # 0 THEN BEGIN warnings _ TRUE; NewLine[]; PutDecimal[log, parms.nWarnings]; PutString[log, " warnings on "L]; PutString[log, rootName]; PutString[log, ".errlog"L]; END; END; END; StopCompiler: PROCEDURE = BEGIN IF moduleCount > 1 THEN BEGIN OPEN CharIO; NewLine[]; PutString[log, "Total elapsed time: "L]; WriteTime[secondsClock.low-compilerStartTime]; NewLine[]; END; log.destroy[log]; IF (errors OR warnings) AND SwitchDefaults['p] THEN BEGIN CursorBits: TYPE = ARRAY [0..16) OF WORD; Cursor: POINTER TO CursorBits = LOOPHOLE[431B]; BlankCursor: CursorBits = ALL[0]; QueryCursor: CursorBits = [2000B, 74000B, 140000B, 12767B, 12525B, 53566B, 111113B, 163100B, 0B, 0B, 154000B, 53520B, 62520B, 53360B, 155440B, 140B]; savedCursor: CursorBits = Cursor^; KeyBits: TYPE = ARRAY [0..SIZE[KeyDefs.KeyBits]-1) OF WORD; Keys: POINTER TO KeyBits = LOOPHOLE[KeyDefs.Keys+1]; savedKeys: KeyBits = Keys^; RTC: POINTER TO MACHINE DEPENDENT RECORD [high: [0..4096), low: [0..16)] = LOOPHOLE[430B]; savedTime: CARDINAL; state: {off, on1, on2}; Cursor^ _ BlankCursor; state _ off; savedTime _ RTC.high; DO IF RTC.high # savedTime THEN BEGIN SELECT state FROM off => BEGIN Cursor^ _ QueryCursor; state _ on1 END; on1 => state _ on2; on2 => BEGIN Cursor^ _ BlankCursor; state _ off END; ENDCASE; savedTime _ RTC.high; END; IF Keys^ # savedKeys THEN EXIT; ENDLOOP; Cursor^ _ savedCursor; END; END; transaction: CompilerOps.Transaction; parms: POINTER TO CompilerOps.Transaction = @transaction; SwitchDefaults: 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, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE]; sourceName: STRING _ [40]; objectName: STRING _ [40]; rootName: STRING _ [40]; sourceFile: SegmentDefs.FileHandle; errorFile: SegmentDefs.FileHandle; objectFile: SegmentDefs.FileHandle; oldObjectFile: BOOLEAN; FindFiles: PROCEDURE [fp: POINTER TO AltoFileDefs.FP, s: STRING] RETURNS [BOOLEAN] = BEGIN IF s.length = sourceName.length AND StringDefs.EquivalentString[sourceName, s] THEN sourceFile _ SegmentDefs.InsertFile[fp, Read]; IF s.length = objectName.length AND StringDefs.EquivalentString[objectName, s] THEN BEGIN objectFile _ SegmentDefs.InsertFile[fp, Write+Append]; SegmentDefs.LockFile[objectFile]; oldObjectFile _ TRUE; END; IF s.length = rootName.length + (".errlog."L).length THEN BEGIN errorName: STRING _ [40]; StringDefs.AppendString[errorName, rootName]; StringDefs.AppendString[errorName, ".errlog."L]; IF StringDefs.EquivalentString[errorName, s] THEN errorFile _ SegmentDefs.InsertFile[fp, Write+Append]; END; RETURN [sourceFile # NIL AND errorFile # NIL AND objectFile # NIL] END; errors, warnings: 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); dcbSpace: ARRAY [0..SIZE[AltoDisplay.DCB]+1) OF UNSPECIFIED; dcb, saveDCB: AltoDisplay.DCBHandle; CursorXY: TYPE = MACHINE DEPENDENT RECORD [x,y: CARDINAL]; cursorLoc: POINTER TO CursorXY = LOOPHOLE[426B]; saveCursorXY: CursorXY; -- add cleanup procedure ImageDefs.AddCleanupProcedure[@compilerCleanupItem]; IF image THEN BEGIN ImageDefs.AddFileRequest[@comCmRequest]; ImageDefs.AddFileRequest[@logRequest]; ImageDefs.AddFileRequest[@tableRequest]; STOP; -- wait for restart END ELSE BEGIN fp: AltoFileDefs.FP _ MiscDefs.CommandLineCFA[].fp; comCmRequest.file _ SegmentDefs.InsertFile[@fp, Read]; END; dcb _ @dcbSpace[0]; IF LOOPHOLE[dcb, CARDINAL] MOD 2 # 0 THEN dcb _ dcb + 1; dcb^ _ AltoDisplay.DCB[NIL, high, black, 0, 0, NIL, 0]; saveDCB _ AltoDisplay.DCBchainHead^; AltoDisplay.DCBchainHead^ _ dcb; saveCursorXY _ cursorLoc^; cursorLoc^ _ [64,64]; errorStream _ NIL; IF tableRequest.file = NIL THEN tableRequest.file _ SegmentDefs.NewFile[ "Swatee.", Read+Write+Append, SegmentDefs.DefaultVersion]; START CompilerOps.Sequencer[ explicitSwapping, tableRequest.file, tableSegment]; compilerStartTime _ secondsClock.low; moduleCount _ 0; -- do the compilation SetCommandInput[]; SetTypescript[]; WriteHerald[log, NIL]; errors _ warnings _ FALSE; DO OPEN CharIO; BEGIN i, sourceLength: CARDINAL; c: CHARACTER; sense, sourceExtension: BOOLEAN; CompleteFileName: PROCEDURE RETURNS [fileName: STRING, bcpl: BOOLEAN] = BEGIN OPEN StringDefs; j: CARDINAL; extension: STRING _ [40]; fileName _ SystemDefs.AllocateHeapString[40]; AppendString[fileName, rootName]; IF ~sourceExtension THEN AppendString[extension, "image"L] ELSE FOR j IN [rootName.length+1 .. sourceLength) DO AppendChar[extension, sourceName[j]] ENDLOOP; bcpl _ EquivalentString[extension, "run"L]; AppendChar[fileName, '.]; AppendString[fileName, extension]; RETURN END; WriteCommandFile: PROCEDURE [fileName: STRING] = BEGIN j: CARDINAL; copy: StreamHandle; copy _ CreateByteStream[ SegmentDefs.NewFile[ "com.cm."L, Write+Append, SegmentDefs.DefaultVersion], Write+Append]; FOR j IN [0..fileName.length) DO copy.put[copy, fileName[j]] ENDLOOP; IF sourceName.length > i+1 THEN BEGIN copy.put[copy, '/]; FOR j IN (i..sourceName.length) DO copy.put[copy, sourceName[j]] ENDLOOP; END; IF commandStream = NIL OR commandStream.endof[commandStream] THEN copy.put[copy, CR] ELSE BEGIN copy.put[copy, ' ]; UNTIL commandStream.endof[commandStream] DO copy.put[copy, commandStream.get[commandStream]] ENDLOOP; END; IF commandStream # NIL THEN commandStream.destroy[commandStream]; copy.destroy[copy]; RETURN END; Run: PROCEDURE [fileName: STRING, bcpl: BOOLEAN] = BEGIN IF bcpl THEN BEGIN 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[]; END ELSE BEGIN OPEN SegmentDefs; ImageDefs.RunImage[NewFileSegment[ file: NewFile[fileName, Read, DefaultVersion], base: 1, pages: 1, access: Read]]; END; END; parms.switches _ SwitchDefaults; parms.switches['p] _ FALSE; parms.debugPass _ LAST[CARDINAL]; CommandLineID[sourceName]; IF sourceName.length = 0 THEN EXIT; NewLine[]; PutString[log, "Compile: "]; PutString[log, sourceName]; IF sourceName[0] = 04C THEN GO TO debugger; -- ^D => debug rootName.length _ 0; sourceExtension _ FALSE; FOR i IN [0..sourceName.length) DO c _ sourceName[i]; SELECT c FROM '. => sourceExtension _ TRUE; '/ => GO TO Switches; ENDCASE; IF ~sourceExtension THEN StringDefs.AppendChar[rootName, c]; REPEAT Switches => BEGIN sourceLength _ i; i _ i+1; sense _ TRUE; WHILE i < sourceName.length DO SELECT (c _ sourceName[i]) FROM '-, '~ => sense _ ~sense; 'r, 'R => BEGIN fileName: STRING; bcpl: BOOLEAN; [fileName, bcpl] _ CompleteFileName[]; WriteCommandFile[fileName]; StopCompiler[]; Run[fileName, bcpl ! ANY => ImageDefs.AbortMesa]; -- never returns END; 'c, 'C => BEGIN sense _ TRUE; FOR i IN [0..sourceLength) DO SELECT (c _ sourceName[i]) FROM '-, '~ => sense _ ~sense; IN ['a..'z] => BEGIN SwitchDefaults[c] _ sense; EXIT END; IN ['A..'Z] => BEGIN SwitchDefaults[c+('a-'A)] _ sense; EXIT END; ENDCASE => EXIT; ENDLOOP; GO TO skip END; IN ['a..'z] => BEGIN parms.switches[c] _ sense; sense _ TRUE END; IN ['A..'Z] => BEGIN parms.switches[c+('a-'A)] _ sense; sense _ TRUE END; IN ['1..'5] => BEGIN parms.debugPass _ c-'0; sense _ TRUE END; ENDCASE; i _ i+1; ENDLOOP; END; FINISHED => sourceLength _ sourceName.length; ENDLOOP; NewLine[]; sourceName.length _ sourceLength; IF ~sourceExtension THEN StringDefs.AppendString[sourceName, ".mesa"]; IF sourceName[sourceName.length-1] # '. THEN StringDefs.AppendChar[sourceName, '.]; parms.source _ [name: sourceName, stream: NIL]; parms.error.name _ NIL; errorStream _ NIL; parms.error.stream _ SystemDefs.AllocateHeapNode[SIZE[Other StreamObject]]; parms.error.stream^ _ [NULL, NULL, NULL, ErrorPut, NULL, ErrorDestroy, NIL, Other[,]]; objectName.length _ 0; StringDefs.AppendString[objectName, rootName]; StringDefs.AppendString[objectName, ".bcd."]; parms.object _ [name: objectName, stream: NIL]; BEGIN OPEN SegmentDefs; ENABLE ANY => CONTINUE; sourceFile _ errorFile _ objectFile _ NIL; oldObjectFile _ FALSE; DirectoryDefs.EnumerateDirectory[FindFiles]; IF sourceFile # NIL THEN parms.source.stream _ CreateByteStream[sourceFile, Read]; END; moduleCount _ moduleCount + 1; Initialize[]; CompilerOps.Compile[parms ! CompilerOps.NoSource => GO TO noSource; CompilerOps.Punt => GO TO punt]; Finalize[]; WriteClosing[]; EXITS skip => NULL; noSource => BEGIN Finalize[]; errors _ TRUE; PutString[log, sourceName]; PutString[log, " -- File error"]; END; debugger => MiscDefs.CallDebugger[NIL]; END; NewLine[]; IF (errors OR warnings) AND parms.switches['p] THEN GO TO truncateList; REPEAT truncateList => SwitchDefaults['p] _ TRUE; punt => BEGIN Finalize[]; WriteClosing[]; NewLine[] END; ENDLOOP; StopCompiler[]; cursorLoc^ _ saveCursorXY; AltoDisplay.DCBchainHead^ _ saveDCB; ImageDefs.StopMesa[]; END.