-- NubControl.Mesa Edited by Sandman on Apr 3, 1979 3:19 PM -- Edited for XMesa by Levin on April 16, 1979 6:11 PM DIRECTORY AltoFileDefs: FROM "altofiledefs" USING [CFA, FA, NullFP], BcdOps: FROM "BcdOps" USING [BcdBase], ControlDefs: FROM "controldefs" USING [ GFT, GlobalFrameHandle, NullGlobalFrame], CoreSwapDefs: FROM "coreswapdefs" USING [CAbort, CantSwap], DisplayDefs: FROM "displaydefs" USING [DisplayControl], ImageDefs: FROM "imagedefs" USING [ AddFileRequest, FileRequest, ImageTime, MakeImage, StopMesa], IODefs: FROM "iodefs" USING [ CR, DEL, LineOverflow, NewLine, NUL, ReadChar, ReadID, ReadNumber, Rubout, SP, WriteChar, WriteOctal, WriteString], LoaderOps: FROM "LoaderOps" USING [ FileNotFound, Load, New, VersionMismatch], MiscDefs: FROM "miscdefs" USING [CallDebugger], ProcessDefs: FROM "processdefs" USING [Aborted], SegmentDefs: FROM "segmentdefs" USING [ LockFile, Read, ReleaseFile, UnlockFile], StreamDefs: FROM "streamdefs" USING [ CreateByteStream, GetFA, JumpToFA, KeyStreams, Read, StreamHandle], StringDefs: FROM "stringdefs" USING [ AppendChar, AppendString, EquivalentString, InvalidNumber, StringBoundsFault], TimeDefs: FROM "timedefs" USING [AppendDayTime, DefaultTime, UnpackDT]; NubControl: PROGRAM IMPORTS CoreSwapDefs, DisplayDefs, ImageDefs, IODefs, LoaderOps, MiscDefs, ProcessDefs, SegmentDefs, StreamDefs, StringDefs, TimeDefs EXPORTS MiscDefs = BEGIN -- System Signals are converted to these to prevent NubCommand -- from catching user generated signals Delete: SIGNAL = CODE; -- nee Rubout StringTooLong: ERROR = CODE; -- nee LineOverflow BadFile: ERROR [badname: STRING] = CODE; -- nee FileNameError BadVersion: SIGNAL [badname: STRING] = CODE; -- nee VersionMismatch BadNumber: ERROR = CODE; -- nee InvalidNumber GlobalFrameHandle: TYPE = ControlDefs.GlobalFrameHandle; NullGlobalFrame: GlobalFrameHandle = ControlDefs.NullGlobalFrame; useCommandLine, skipImage: BOOLEAN ← TRUE; module: STRING ← [40]; defaultframe: GlobalFrameHandle ← NullGlobalFrame; DoCommand: PROCEDURE = BEGIN OPEN ControlDefs; p: PROCESS; f: GlobalFrameHandle; IF skipImage THEN SkipImage[]; f ← IF useCommandLine THEN LoadSystem[] ELSE Command[]; IF f # NullGlobalFrame THEN BEGIN p ← FORK StartModule[LOOPHOLE[f]]; JOIN p; END; RETURN END; StartModule: PROCEDURE [f: PROGRAM] = BEGIN BEGIN ENABLE ProcessDefs.Aborted, CoreSwapDefs.CAbort => CONTINUE; IF ~LOOPHOLE[f, GlobalFrameHandle].started THEN START f ELSE RESTART f; END; RETURN END; Command: PROCEDURE RETURNS [GlobalFrameHandle] = BEGIN OPEN IODefs; nCommand: STRING = "New"L; sCommand: STRING = "Start"L; dCommand: STRING = "Debug"L; qCommand: STRING = "Quit"L; mCommand: STRING = "MakeImage"L; c: CHARACTER; f: GlobalFrameHandle; DO WriteEOL[]; WriteChar['>]; SELECT c←ReadChar[] FROM 'N,'n => BEGIN WriteString[nCommand]; LoadModule[]; END; 'S,'s => BEGIN WriteString[sCommand]; f ← getgframe[]; WriteEOL[]; RETURN[f]; END; 'D,'d => BEGIN WriteString[dCommand]; confirm[]; MiscDefs.CallDebugger["You called?"L]; END; 'M,'m => BEGIN WriteString[mCommand]; ImageDefs.MakeImage[getfilename[".image"L]]; END; 'Q,'q => BEGIN WriteString[qCommand]; confirm[]; ImageDefs.StopMesa[]; END; CR,SP => NULL; ENDCASE => BEGIN WriteChar[c]; WriteString[" Commands are:"L]; WriteChar[' ]; WriteString[nCommand]; WriteChar[' ]; WriteString[sCommand]; WriteChar[' ]; WriteString[dCommand]; WriteChar[' ]; WriteString[mCommand]; WriteChar[' ]; WriteString[qCommand]; END; ENDLOOP; END; LoadModule: PROCEDURE = BEGIN name: STRING ← [40]; ext: STRING ← [10]; switches: STRING ← [10]; i: CARDINAL ← 0; g: GlobalFrameHandle; fn: STRING = " Filename: "L; get: PROCEDURE RETURNS [c: CHARACTER] = BEGIN IF i = module.length THEN RETURN[IODefs.NUL]; c ← module[i]; i ← i + 1; RETURN[c] END; IODefs.WriteString[fn]; IODefs.ReadID[module ! IODefs.Rubout => ERROR Delete; IODefs.LineOverflow => ERROR StringTooLong]; GetToken[get, name, ext, switches]; IF ext.length = 0 THEN ext ← "bcd"; StringDefs.AppendChar[name, '.]; StringDefs.AppendString[name, ext]; InitSwitches[]; ProcessSwitches[switches]; g ← LoadNew[name, framelinks]; IF g # NullGlobalFrame THEN defaultframe ← g; RETURN END; LoadNew: PROCEDURE [name: STRING, framelinks: BOOLEAN] RETURNS [g: GlobalFrameHandle] = BEGIN OPEN LoaderOps; s: STRING = " -- "L; bcd: BcdOps.BcdBase; bcd ← Load[name ! BadFile, UNWIND => NULL; ANY => ERROR BadFile[name]]; g ← New[bcd, framelinks, FALSE ! BadFile, BadVersion, UNWIND => NULL; VersionMismatch => BEGIN SIGNAL BadVersion[name]; RESUME END; FileNotFound => ERROR BadFile[name]; ANY => ERROR BadFile[name]]; IODefs.WriteString[s]; IODefs.WriteOctal[g]; WriteEOL[]; RETURN END; getgframe: PROCEDURE RETURNS [f: GlobalFrameHandle] = BEGIN OPEN ControlDefs, IODefs; gf: STRING = " Global frame: "L; ngf: STRING = " not a global frame!"L; WriteString[gf]; f ← ReadNumber[defaultframe,8 ! LineOverflow => ERROR StringTooLong; Rubout => ERROR Delete; StringDefs.InvalidNumber => ERROR BadNumber]; IF GFT[f.gfi].frame # f THEN BEGIN WriteString[ngf]; SIGNAL CoreSwapDefs.CAbort END; defaultframe ← f; RETURN END; getfilename: PROCEDURE [defaultextension: STRING] RETURNS [STRING] = BEGIN OPEN IODefs; fn: STRING = " Filename: "L; WriteString[fn]; ReadID[module ! Rubout => ERROR Delete; LineOverflow => ERROR StringTooLong]; defaultext[module, defaultextension]; RETURN[module] END; defaultext: PROCEDURE [idstring: STRING, ext: STRING] = BEGIN i: CARDINAL; FOR i IN [0..idstring.length) DO IF idstring[i] = '. THEN EXIT; REPEAT FINISHED => FOR i IN [0..ext.length) DO StringDefs.AppendChar[idstring, ext[i] ! StringDefs.StringBoundsFault => ERROR StringTooLong]; ENDLOOP; ENDLOOP; END; confirm: PROCEDURE = BEGIN OPEN IODefs; c: STRING = " [Confirm] "L; WriteString[c]; DO SELECT ReadChar[] FROM CR => EXIT; DEL => ERROR Delete; ENDCASE => WriteChar['?]; ENDLOOP; WriteChar[CR]; RETURN END; WriteEOL: PROCEDURE = BEGIN OPEN IODefs; IF ~NewLine[] THEN WriteChar[CR]; RETURN END; comcmRequest: short ImageDefs.FileRequest ← [ body: short[fill:, name: "Com.Cm."], file: NIL, access: SegmentDefs.Read, link: ]; Done: SIGNAL = CODE; debug, start, command, framelinks: BOOLEAN; ProcessSwitches: PROCEDURE [s: STRING] = BEGIN i: CARDINAL; inverse: BOOLEAN ← FALSE; FOR i IN [0..s.length) DO SELECT s[i] FROM 'c, 'C => BEGIN inverse ← FALSE; command ← TRUE END; 'd, 'D => BEGIN inverse ← FALSE; debug ← TRUE END; 's, 'S => IF inverse THEN inverse ← start ← FALSE ELSE start ← TRUE; 'l, 'L => BEGIN inverse ← FALSE; framelinks ← FALSE END; '- => inverse ← TRUE; ENDCASE => inverse ← FALSE; ENDLOOP; END; InitSwitches: PROCEDURE = BEGIN command ← debug ← FALSE; framelinks ← start ← TRUE; END; GetToken: PROCEDURE [ get: PROCEDURE RETURNS [CHARACTER], token, ext, switches: STRING] = BEGIN OPEN IODefs; s: STRING; c: CHARACTER; token.length ← ext.length ← switches.length ← 0; s ← token; WHILE (c ← get[]) # NUL DO SELECT c FROM SP, CR => IF token.length # 0 OR ext.length # 0 OR switches.length # 0 THEN RETURN; '. => s ← ext; '/ => s ← switches; ENDCASE => StringDefs.AppendChar[s, c ! StringDefs.StringBoundsFault => ERROR StringTooLong]; ENDLOOP; RETURN END; cfa: AltoFileDefs.CFA; CommandLineCFA: PUBLIC PROCEDURE RETURNS [POINTER TO AltoFileDefs.CFA] = BEGIN RETURN[@cfa] END; CleanUpCommandLine: PROCEDURE = BEGIN SegmentDefs.UnlockFile[comcmRequest.file]; SegmentDefs.ReleaseFile[comcmRequest.file]; comcmRequest.file ← NIL; useCommandLine ← FALSE; RETURN END; LoadSystem: PROCEDURE RETURNS [user: GlobalFrameHandle] = BEGIN BEGIN ENABLE UNWIND => CleanUpCommandLine[]; InitSwitches[]; user ← LoadUser[@cfa.fa ! Done => GOTO done]; IF user # NullGlobalFrame THEN defaultframe ← user; IF debug THEN MiscDefs.CallDebugger["You called?"L]; IF ~start THEN user ← NullGlobalFrame; EXITS done => BEGIN user ← NullGlobalFrame; CleanUpCommandLine[] END; END; RETURN END; LoadUser: PROCEDURE [fa: POINTER TO AltoFileDefs.FA] RETURNS [user: GlobalFrameHandle] = BEGIN OPEN IODefs, StreamDefs; com: StreamHandle; name: STRING ← [40]; ext: STRING ← [10]; switches: STRING ← [10]; get: PROCEDURE RETURNS [c: CHARACTER] = BEGIN IF com.endof[com] THEN RETURN[NUL]; RETURN[com.get[com]]; END; com ← CreateByteStream[comcmRequest.file, Read]; user ← NullGlobalFrame; BEGIN StreamDefs.JumpToFA[com, fa ! ANY => GO TO finished]; GetToken[get, name, ext, switches]; IF name.length = 0 AND switches.length = 0 THEN GO TO finished; StreamDefs.GetFA[com, fa]; com.destroy[com]; ProcessSwitches[switches]; IF name.length # 0 AND ~command THEN BEGIN IF ext.length = 0 THEN ext ← "bcd"L; WriteEOL[]; WriteChar['>]; WriteString[name]; StringDefs.AppendChar[name, '.]; StringDefs.AppendString[name, ext]; user ← LoadNew[name, framelinks]; END; IF command THEN ProcessSwitches[name]; EXITS finished => BEGIN com.destroy[com ! ANY => CONTINUE]; SIGNAL Done; END; END; RETURN END; SkipImage: PROCEDURE = BEGIN OPEN IODefs, StreamDefs; com: StreamHandle; name: STRING ← [40]; ext: STRING ← [10]; switches: STRING ← [10]; get: PROCEDURE RETURNS [c: CHARACTER] = BEGIN IF com.endof[com] THEN RETURN[NUL]; RETURN[com.get[com]]; END; skipImage ← FALSE; IF comcmRequest.file = NIL THEN BEGIN cfa.fp ← AltoFileDefs.NullFP; useCommandLine ← FALSE; RETURN END; cfa.fp ← comcmRequest.file.fp; SegmentDefs.LockFile[comcmRequest.file]; InitSwitches[]; com ← CreateByteStream[comcmRequest.file, Read]; StreamDefs.GetFA[com, @cfa.fa]; GetToken[get, name, ext, switches]; IF StringDefs.EquivalentString[ext, "image"L] THEN StreamDefs.GetFA[com, @cfa.fa]; com.destroy[com]; ProcessSwitches[switches]; IF debug THEN MiscDefs.CallDebugger["You called?"L]; END; WriteHerald: PROCEDURE = BEGIN OPEN TimeDefs; h: STRING = "Alto/Mesa 5.0 [XM] of "L; time: STRING ← [18]; AppendDayTime[time, UnpackDT[ImageDefs.ImageTime[]]]; time.length ← time.length - 3; IODefs.WriteString[h]; IODefs.WriteString[time]; time.length ← 0; AppendDayTime[time, UnpackDT[DefaultTime]]; time.length ← time.length - 3; WriteEOL[]; IODefs.WriteString[time]; END; ErrorName: TYPE = {XXX, file, number, toolong, nodebug, aborted, diffver}; WriteError: PROCEDURE [error: ErrorName] = BEGIN IODefs.WriteString[SELECT error FROM file => "!File: "L, number => "!Number"L, toolong => "!String too long"L, nodebug => "External Debugger not installed, type DEL to abort "L, aborted => "...Aborted..."L, diffver => " referenced in different versions"L, ENDCASE => " XXX"L] END; -- Main body START StreamDefs.KeyStreams; -- Start keyboard process ImageDefs.AddFileRequest[@comcmRequest]; START DisplayDefs.DisplayControl; STOP; RESTART DisplayDefs.DisplayControl; WriteHerald[]; DO OPEN IODefs; -- forever DoCommand[ ! Delete => BEGIN WriteError[XXX]; CONTINUE END; CoreSwapDefs.CAbort => CONTINUE; BadFile --[badname: STRING]-- => BEGIN WriteEOL[]; WriteError[file]; WriteString[badname]; CONTINUE END; BadNumber => BEGIN WriteEOL[]; WriteError[number]; CONTINUE END; StringTooLong => BEGIN WriteEOL[]; WriteError[toolong]; CONTINUE END; CoreSwapDefs.CantSwap => BEGIN WriteEOL[]; WriteError[nodebug]; UNTIL ReadChar[]=DEL DO WriteChar['?] ENDLOOP; WriteError[aborted]; CONTINUE END; BadVersion --[badname: STRING]-- => BEGIN WriteEOL[]; WriteError[file]; WriteString[badname]; WriteError[diffver]; RESUME END; UNWIND =>CONTINUE ]; ENDLOOP; END..