-- TableControl.Mesa Edited by Satterthwaite on August 29, 1980 1:33 PM DIRECTORY AltoDisplay: TYPE USING [DCB, DCBHandle, DCBchainHead], AltoFileDefs: TYPE USING [CFA], BcdDefs: TYPE USING [BCD, VersionStamp], CharIO: TYPE USING [CR, SP, PutChar, PutDecimal, PutString], FrameOps: TYPE USING [CodeHandle, MyGlobalFrame], Inline: TYPE USING [LongDiv, LongMult], ImageDefs: TYPE USING [FileRequest, RunImage, StopMesa], MiscDefs: TYPE USING [CommandLineCFA], OsStaticDefs: TYPE USING [OsStatics], SegmentDefs: TYPE USING [ Append, DefaultVersion, DeleteFileSegment, FileError, FileHandle, FileNameError, FileSegmentHandle, GetFileTimes, InsertFile, NewFile, NewFileSegment, Read, SegmentAddress, SwapIn, Unlock, Write], StreamDefs: TYPE USING [ Append, CreateByteStream, JumpToFA, Read, StreamError, StreamHandle, Write], StringDefs: TYPE USING [ AppendChar, AppendString, EquivalentString, MesaToBcplString, WordsForBcplString], TableCommand: TYPE USING [CompileStrings, MakeModule], TimeDefs: TYPE USING [AppendDayTime, DefaultTime, UnpackDT]; TableControl: PROGRAM IMPORTS CharIO, FrameOps, ImageDefs, Inline, MiscDefs, SegmentDefs, StreamDefs, StringDefs, TableCommand, TimeDefs EXPORTS TableCommand = BEGIN OPEN StreamDefs; CR: CHARACTER = CharIO.CR; -- cursor control CursorBits: TYPE = ARRAY [0..16) OF WORD; TheCursor: POINTER TO CursorBits = LOOPHOLE[431B]; savedCursor: CursorBits; TableCursor: CursorBits = [ 177777b, 177777b, 177777b, 160007b, 160007b, 160007b, 160007b, 160007b, 160007b, 160007b, 160007b, 160007b, 160007b, 177777b, 177777b, 177777b]; -- command gathering and logging log: StreamHandle; logName: STRING = "TableCompiler.Log."; logRequest: ImageDefs.FileRequest ← [ name: logName, file: NIL, access: Write+Append, link: ]; commandStream: StreamHandle; comCmRequest: ImageDefs.FileRequest ← [ name: "Com.Cm.", file: NIL, access: Read, link: ]; Rubout: ERROR = CODE; ReadCommand: PROC [name, switches: STRING] RETURNS [BOOLEAN] = { input: STRING ← [80]; i: CARDINAL; activeString: STRING ← name; c: CHARACTER; DO c ← commandStream.get[commandStream ! StreamDefs.StreamError => EXIT]; SELECT c FROM CharIO.SP => IF input.length # 0 THEN EXIT; CR => EXIT; ENDCASE => StringDefs.AppendChar[input, c]; ENDLOOP; i ← name.length ← switches.length ← 0; WHILE i < input.length AND input[i] = CharIO.SP DO i ← i+1 ENDLOOP; --parse command-- FOR i IN [i..input.length) DO SELECT (c←input[i]) FROM '/ => activeString ← switches; CharIO.SP, CR => EXIT; ENDCASE => StringDefs.AppendChar[activeString,c]; ENDLOOP; FOR i IN [0..switches.length) DO -- convert all to lower case IF (c←switches[i]) IN ['A..'Z] THEN switches[i] ← c + ('a-'A); ENDLOOP; RETURN [name.length # 0 OR switches.length # 0]}; DefaultFileName: PROC [name, defaultExtension: STRING] = { FOR i: CARDINAL IN [0..name.length) DO IF name[i] = '. THEN RETURN ENDLOOP; StringDefs.AppendString[name, defaultExtension]}; input: {strings, binary}; -- compiling strings compact: BOOLEAN; dStar: BOOLEAN; sourceName: STRING ← [40]; rootName: STRING ← [40]; interfaceName: STRING ← [40]; formatName: STRING ← [40]; bcdName: STRING ← [40]; GetCommand: PROC = { file: STRING ← [40]; sw: STRING ← [10]; i: CARDINAL; c: CHARACTER; done: BOOLEAN ← FALSE; sense: BOOLEAN; GetSwitch: PROC RETURNS [c: CHARACTER] = { sense ← TRUE; WHILE i < sw.length DO c ← sw[i]; i ← i + 1; IF c = '- OR c = '~ THEN sense ← ~sense ELSE EXIT; ENDLOOP; RETURN}; sourceName.length ← bcdName.length ← interfaceName.length ← formatName.length ← 0; dStar ← FALSE; file.length ← 0; IF ~ReadCommand[file, sw] OR file.length = 0 THEN RETURN; DefaultFileName[file, ".mesa"L]; IF ExtensionIs[file, ".mesa"L] THEN {input ← strings; compact ← TRUE} ELSE input ← binary; i ← 0; WHILE i < sw.length DO SELECT (c←GetSwitch[]) FROM 'a => dStar ← sense; 'c => compact ← sense; 'm => input ← binary; 's => {input ← strings; compact ← FALSE}; 't => {input ← strings; compact ← TRUE}; 'g => done ← TRUE; 'r => { FOR j: CARDINAL IN [i..sw.length) DO sw[j-i] ← sw[j] ENDLOOP; sw.length ← sw.length - i; DefaultFileName[file, ".image"L]; Run[file, sw ! UNWIND => NULL; ANY => GO TO barf]}; ENDCASE => GO TO barf; REPEAT barf => ERROR Rubout; ENDLOOP; StringDefs.AppendString[sourceName, file]; WHILE ~done AND ReadCommand[file, sw] DO i ← 0; WHILE i < sw.length DO SELECT (c←GetSwitch[]) FROM 'f => { DefaultFileName[file, ".format"L]; formatName.length ← 0; StringDefs.AppendString[formatName, file]}; 'i => { DefaultFileName[file, ".bcd"L]; interfaceName.length ← 0; StringDefs.AppendString[interfaceName, file]}; 'o => { DefaultFileName[file, ".bcd"L]; bcdName.length ← 0; StringDefs.AppendString[bcdName, file]}; 'g => done ← TRUE; ENDCASE => ERROR Rubout; ENDLOOP; ENDLOOP}; Run: PROC [name, otherSwitches: STRING] = { OPEN SegmentDefs; c: CHARACTER; i: CARDINAL; copy: StreamDefs.StreamHandle; copy ← StreamDefs.CreateByteStream[comCmRequest.file, Write+Append]; FOR i IN [0..name.length) DO copy.put[copy, name[i]] ENDLOOP; IF otherSwitches.length # 0 THEN { copy.put[copy, '/]; FOR i IN [0..otherSwitches.length) DO copy.put[copy, otherSwitches[i]] ENDLOOP}; copy.put[copy, ' ]; DO c ← commandStream.get[commandStream ! StreamDefs.StreamError => GO TO done]; copy.put[copy, c]; REPEAT done => commandStream.destroy[commandStream]; ENDLOOP; copy.destroy[copy]; IF ExtensionIs[name, ".run"L] THEN { p: POINTER = OsStaticDefs.OsStatics.EventVector; EVItem: TYPE = MACHINE DEPENDENT RECORD [ type: [0..7777B], length: [0..17B]]; p↑ ← EVItem[6, StringDefs.WordsForBcplString[name.length]+1]; StringDefs.MesaToBcplString[name, p+1]; ImageDefs.StopMesa[]} ELSE ImageDefs.RunImage[ NewFileSegment[NewFile[name, Read, DefaultVersion], 1, 1, Read]]}; ExtensionIs: PROC [name, ext: STRING] RETURNS [BOOLEAN] = { t: STRING ← [40]; IF name.length <= ext.length THEN RETURN[FALSE]; FOR i: CARDINAL IN [name.length-ext.length .. name.length) DO StringDefs.AppendChar[t,name[i]] ENDLOOP; RETURN [StringDefs.EquivalentString[t,ext]]}; RepeatCommand: PROC [s: StreamHandle] = { OPEN CharIO; PutChar[s, CR]; SELECT input FROM strings => { PutString[s, "Compiling "L]; PutString[s, sourceName]; PutString[s, ", exporting "L]; PutString[s, rootName]; PutString[s, " to "L]; PutString[s, interfaceName]; IF bcdName.length # 0 THEN {PutString[s, ", BCD to "L]; PutString[s, bcdName]}; PutChar[s, CR]; PutString[s, "Record format on "L]; PutString[s, formatName]}; binary => { PutString[s, "Processing "L]; PutString[s, sourceName]; PutString[s, ", exporting "L]; PutString[s, rootName]; PutString[s, " to "L]; PutString[s, interfaceName]; IF bcdName.length # 0 THEN {PutString[s, ", BCD to "L]; PutString[s, bcdName]}}; ENDCASE; PutChar[s, CR]}; CreateTime: PUBLIC PROC [s: StreamDefs.StreamHandle] RETURNS [time: LONG INTEGER] = { RETURN [WITH s: s SELECT FROM Disk => SegmentDefs.GetFileTimes[s.file].create, ENDCASE => 0]}; MyBcdVersion: PUBLIC PROC RETURNS [version: BcdDefs.VersionStamp] = { OPEN SegmentDefs; cseg: FileSegmentHandle = FrameOps.CodeHandle[FrameOps.MyGlobalFrame[]]; bcdseg: FileSegmentHandle = NewFileSegment[cseg.file, 1, 1, Read]; bcd: POINTER TO BcdDefs.BCD; SwapIn[bcdseg]; bcd ← SegmentAddress[bcdseg]; version ← bcd.version; Unlock[bcdseg]; DeleteFileSegment[bcdseg]; RETURN}; WriteHerald: PROC [stream: StreamHandle, name: STRING] = { OPEN TimeDefs, CharIO; version: BcdDefs.VersionStamp = MyBcdVersion[]; t: STRING ← [20]; PutString[stream, "Alto/Mesa TableCompiler 6.0C of "L]; AppendDayTime[t, UnpackDT[version.time]]; t.length ← t.length - 3; PutString[stream, t]; PutChar[stream, CR]; t.length ← 0; AppendDayTime[t,UnpackDT[DefaultTime]]; t.length ← t.length - 3; IF name # NIL THEN {PutString[stream, name]; PutString[stream, " -- "L]}; PutString[stream, t]; PutChar[stream, CR]}; -- timing procedures timer: POINTER TO CARDINAL = LOOPHOLE[430B]; TimeNow: PROC RETURNS [CARDINAL] = INLINE {RETURN [timer↑]}; TimeSince: PROC [start: CARDINAL] RETURNS [CARDINAL] = { OPEN Inline; RETURN [(LongDiv[LongMult[timer↑-start, 2*39], 1000]+1)/2]}; -- initialization dcbSpace: ARRAY [0..SIZE[AltoDisplay.DCB]+1) OF UNSPECIFIED; dcb, saveDCB: AltoDisplay.DCBHandle; 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; -- find the command stream BEGIN OPEN StreamDefs; cfa: POINTER TO AltoFileDefs.CFA = MiscDefs.CommandLineCFA[]; comCmRequest.file ← SegmentDefs.InsertFile[@cfa.fp, Read]; commandStream ← CreateByteStream[comCmRequest.file, Read]; StreamDefs.JumpToFA[commandStream, @cfa.fa]; END; -- find the log stream BEGIN OPEN SegmentDefs; s: STRING ← [40]; IF logRequest.file = NIL THEN logRequest.file ← NewFile[logName, Write+Append, DefaultVersion]; log ← CreateByteStream[logRequest.file, Write+Append]; END; WriteHerald[log, NIL]; -- main loop DO BEGIN ENABLE { SegmentDefs.FileNameError => { OPEN CharIO; PutString[log, "Can't open "]; PutString[log, name]; PutChar[log, CR]; GO TO FileFault}; SegmentDefs.FileError => { OPEN CharIO; PutString[log, "File problem"]; PutChar[log, CR]; GO TO FileFault}}; startTime: CARDINAL; GetCommand[ ! Rubout => GOTO Abort]; IF sourceName.length = 0 THEN EXIT; startTime ← TimeNow[]; rootName.length ← 0; FOR i: CARDINAL IN [0..sourceName.length) DO IF sourceName[i] = '. THEN EXIT; StringDefs.AppendChar[rootName, sourceName[i]]; ENDLOOP; IF interfaceName.length = 0 THEN StringDefs.AppendString[interfaceName, "SELF"]; IF formatName.length = 0 THEN { StringDefs.AppendString[formatName, rootName]; StringDefs.AppendString[formatName, "Format."]}; RepeatCommand[log]; IF bcdName.length = 0 THEN { StringDefs.AppendString[bcdName, rootName]; StringDefs.AppendString[bcdName, ".bcd"]}; savedCursor ← TheCursor↑; TheCursor↑ ← TableCursor; SELECT input FROM strings => { OPEN CharIO; nChars, nStrings: CARDINAL; [nStrings, nChars] ← TableCommand.CompileStrings[ inputFile: sourceName, interfaceId: interfaceName, formatId: formatName, moduleId: bcdName, compact: compact, altoCode: ~dStar]; PutString[log, "Strings: "]; CharIO.PutDecimal[log, nStrings]; PutString[log, ", characters: "]; CharIO.PutDecimal[log, nChars]; PutChar[log, CR]}; binary => TableCommand.MakeModule[ inputFile: sourceName, interfaceId: interfaceName, moduleId: bcdName, altocode: ~dStar]; ENDCASE; CharIO.PutChar[log, CR]; TheCursor↑ ← savedCursor; EXITS FileFault => NULL; Abort => CharIO.PutChar[log, '?]; END; ENDLOOP; IF log # NIL THEN log.destroy[log]; AltoDisplay.DCBchainHead↑ ← saveDCB; ImageDefs.StopMesa[]; END.