-- MesaNub.Mesa Edited by Sandman on September 12, 1980 8:43 AM
-- Copyright Xerox Corporation 1979, 1980
DIRECTORY
AltoFileDefs USING [CFA, FA],
BcdOps USING [BcdBase],
ControlDefs USING [ControlModule, GlobalFrameHandle, NullGlobalFrame],
DisplayDefs USING [DestroyDisplay, DisplayControl],
ImageDefs USING [AddFileRequest, FileRequest, ImageTime],
IODefs USING [CR, SP, NewLine, WriteChar, WriteLine, WriteOctal, WriteString],
LoaderOps USING [FileNotFound, Load, New, VersionMismatch],
MiscDefs USING [CallDebugger],
MiscOps USING [bypassExec, ReleaseDebuggerBitmap],
NubOps USING [],
SegmentDefs USING [FileHandle, Read, ReleaseFile, UnlockFile],
StreamDefs USING [
CreateByteStream, DestroyKeyHandler, GetFA, JumpToFA, Read, StartKeyHandler,
StreamHandle],
StringDefs USING [AppendChar, AppendString, LowerCase],
Storage USING [Node, CopyString, Free, FreeString],
TimeDefs USING [AppendDayTime, DefaultTime, UnpackDT];
MesaNub: PROGRAM
IMPORTS
DisplayDefs, ImageDefs, IODefs, LoaderOps, MiscDefs, MiscOps, SegmentDefs,
StreamDefs, StringDefs, Storage, TimeDefs
EXPORTS MiscDefs, NubOps =
BEGIN OPEN SegmentDefs;
BadFile: SIGNAL [name: STRING] = CODE;
BadVersion: SIGNAL [name: STRING] = CODE;
cmFile: FileHandle ← NIL;
AddComCmRequest: PUBLIC PROCEDURE =
BEGIN OPEN Storage;
comcmRequest ← Node[SIZE[ImageDefs.FileRequest]];
comcmRequest↑ ←
[name: CopyString["Com.Cm."L], file: NIL, access: Read, link:];
ImageDefs.AddFileRequest[comcmRequest];
IF cmFile # NIL THEN {UnlockFile[cmFile]; ReleaseFile[cmFile]; cmFile ← NIL};
END;
RemoveComCmRequest: PUBLIC PROCEDURE =
BEGIN
cmFile ← comcmRequest.file;
Storage.FreeString[comcmRequest.name];
Storage.Free[comcmRequest];
END;
comcmRequest: POINTER TO ImageDefs.FileRequest;
Done: SIGNAL = CODE;
Switches: TYPE = PACKED ARRAY CHARACTER ['a..'z] OF BOOLEAN;
DefaultSwitches: Switches =
[FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, --'a..'i
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, --'j..'r
TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE]; --'s..'z
switches: Switches;
postAnyway, alreadyBasic, doneHearld: BOOLEAN;
ProcessSwitches: PROCEDURE [s: STRING] =
BEGIN
i: CARDINAL;
c: CHARACTER;
inverse: {this, next, no} ← no;
FOR i IN [0..s.length) DO
SELECT c ← StringDefs.LowerCase[s[i]] FROM
IN ['a..'z] => switches[c] ← inverse # this;
'- => inverse ← next;
ENDCASE;
inverse ← IF inverse = next THEN this ELSE no;
ENDLOOP;
END;
GetToken: PROCEDURE [
com: StreamDefs.StreamHandle, token, ext, switches: STRING] =
BEGIN
s: STRING;
c: CHARACTER;
token.length ← ext.length ← switches.length ← 0;
s ← token;
WHILE ~com.endof[com] DO
SELECT (c ← com.get[com]) FROM
IODefs.SP, IODefs.CR =>
IF token.length # 0 OR ext.length # 0 OR switches.length # 0 THEN
RETURN;
'. => s ← ext;
'/ => s ← switches;
ENDCASE => StringDefs.AppendChar[s, c];
ENDLOOP;
RETURN
END;
cfa: AltoFileDefs.CFA;
CommandLineCFA: PUBLIC PROCEDURE RETURNS [POINTER TO AltoFileDefs.CFA] =
BEGIN RETURN[@cfa] END;
LoadSystems: PUBLIC PROCEDURE [skipImage: BOOLEAN ← FALSE] =
BEGIN
user: ControlDefs.ControlModule;
p: PROCESS;
cfa.fp ← cmFile.fp;
switches ← DefaultSwitches;
IF skipImage THEN SkipImage[@cfa.fa];
DO
switches ← DefaultSwitches;
user ← LoadUser[@cfa.fa ! Done => EXIT];
CheckSwitches[];
IF switches['s] AND user # [frame[ControlDefs.NullGlobalFrame]] THEN
BEGIN p ← FORK StartModule[user]; JOIN p END;
ENDLOOP;
END;
StartModule: PROCEDURE [f: ControlDefs.ControlModule] =
BEGIN
IF f.multiple OR ~f.frame.started THEN
START LOOPHOLE[f, PROGRAM][ ! ABORTED => CONTINUE];
RETURN
END;
LoadUser: PROCEDURE [fa: POINTER TO AltoFileDefs.FA]
RETURNS [user: ControlDefs.ControlModule] =
BEGIN OPEN IODefs, StreamDefs;
com: StreamHandle;
name: STRING ← [40];
ext: STRING ← [10];
switch: STRING ← [5];
com ← CreateByteStream[cmFile, Read];
user ← [frame[ControlDefs.NullGlobalFrame]];
BEGIN
StreamDefs.JumpToFA[com, fa ! ANY => GO TO finished];
GetToken[com, name, ext, switch];
IF name.length = 0 AND switch.length = 0 THEN GO TO finished;
StreamDefs.GetFA[com, fa];
com.destroy[com];
ProcessSwitches[switch];
IF switches['b] THEN ConvertToBasic[];
IF name.length # 0 AND ~switches['c] THEN
BEGIN
IF ext.length = 0 THEN ext ← "bcd"L;
IF ~alreadyBasic OR postAnyway THEN PostName[name];
StringDefs.AppendChar[name, '.];
StringDefs.AppendString[name, ext];
user ← LoadNew[name !
BadVersion => {BadVersionError[name]; RESUME};
BadFile => {BadFileError[name]; GOTO exit}];
IF ~alreadyBasic OR postAnyway THEN PostAddress[user];
END;
IF switches['c] THEN ProcessSwitches[name];
EXITS
exit => NULL;
finished => BEGIN com.destroy[com ! ANY => CONTINUE]; SIGNAL Done; END;
END;
END;
LoadNew: PROCEDURE [name: STRING] RETURNS [ControlDefs.ControlModule] =
BEGIN OPEN LoaderOps;
bcd: BcdOps.BcdBase;
bcd ← Load[name ! BadFile, UNWIND => NULL; ANY => ERROR BadFile[name]];
RETURN[
New[bcd, ~switches['l], FALSE !
BadFile, BadVersion, UNWIND => NULL;
VersionMismatch => {SIGNAL BadVersion[name]; RESUME};
FileNotFound => ERROR BadFile[name];
ANY => ERROR BadFile[name]]];
END;
ConvertToBasic: PUBLIC PROCEDURE =
BEGIN
IF alreadyBasic THEN RETURN;
alreadyBasic ← TRUE;
DisplayDefs.DestroyDisplay[];
StreamDefs.DestroyKeyHandler[];
END;
IsBasic: PUBLIC PROCEDURE RETURNS [BOOLEAN] = BEGIN RETURN[alreadyBasic]; END;
EnableOutput: PUBLIC PROCEDURE = BEGIN postAnyway ← TRUE; END;
PostName: PROCEDURE [name: STRING] =
BEGIN OPEN IODefs;
IF ~doneHearld THEN WriteHerald[];
WriteChar['>];
WriteString[name];
END;
PostAddress: PROCEDURE [user: UNSPECIFIED] =
BEGIN OPEN IODefs; WriteString[" -- "]; WriteOctal[user]; WriteChar[CR]; END;
BadFileError: PROCEDURE [s: STRING] = {
IF alreadyBasic THEN RETURN;
IF ~IODefs.NewLine[] THEN IODefs.WriteChar[IODefs.CR];
IODefs.WriteString["!File: "L];
IODefs.WriteString[s]};
BadVersionError: PROCEDURE [s: STRING] = {
IF alreadyBasic THEN RETURN;
IF ~IODefs.NewLine[] THEN IODefs.WriteChar[IODefs.CR];
IODefs.WriteString["!File: "L];
IODefs.WriteString[s];
IODefs.WriteString[" referenced in different versions"L]};
WriteHerald: PUBLIC PROCEDURE =
BEGIN OPEN TimeDefs;
h: STRING = "Alto/Mesa 6.0 of "L;
time: STRING ← [18];
AppendDayTime[time, UnpackDT[ImageDefs.ImageTime[]]];
time.length ← time.length - 3;
IODefs.WriteString[h];
IODefs.WriteLine[time];
time.length ← 0;
AppendDayTime[time, UnpackDT[DefaultTime]];
time.length ← time.length - 3;
IODefs.WriteLine[time];
doneHearld ← TRUE;
END;
SkipImage: PROCEDURE [fa: POINTER TO AltoFileDefs.FA] =
BEGIN OPEN IODefs, StreamDefs;
com: StreamHandle;
name: STRING ← [40];
ext: STRING ← [10];
switch: STRING ← [5];
com ← CreateByteStream[cmFile, Read];
GetToken[com, name, ext, switch];
GetFA[com, fa];
com.destroy[com];
ProcessSwitches[switch];
CheckSwitches[];
END;
CheckSwitches: PROCEDURE =
BEGIN
IF switches['q] THEN MiscOps.bypassExec ← TRUE;
IF switches['k] THEN MiscOps.ReleaseDebuggerBitmap[];
IF switches['b] THEN ConvertToBasic[];
IF switches['d] THEN MiscDefs.CallDebugger["You Called?"L];
END;
-- Main body
StreamDefs.StartKeyHandler; -- Start keyboard process
AddComCmRequest[];
START DisplayDefs.DisplayControl;
STOP;
RemoveComCmRequest[];
RESTART DisplayDefs.DisplayControl;
postAnyway ← alreadyBasic ← doneHearld ← FALSE;
LoadSystems[TRUE];
END...