<> <> <> DIRECTORY Ascii USING [CR], CedarInitPrivate USING [], DCSFileTypes USING [tLeaderPage], Directory USING [Lookup], File USING [Capability, GetAttributes, Type, nullCapability], FileStream USING [EndOf, Create], Heap USING [systemMDSZone], Loader USING [Instantiate, Start, Error], LongString USING [AppendString, UpperCase], PrincOps USING [ControlModule, NullControl], Runtime USING [CallDebugger], SpecialTerminal USING [GetProc, PutProc, TurnOff, TurnOn], Stream USING [Delete, GetChar, Handle]; BasicLoader: PROGRAM IMPORTS Directory, File, FileStream, Heap, Loader, LongString, Runtime, SpecialTerminal, Stream EXPORTS CedarInitPrivate = BEGIN getChar: SpecialTerminal.GetProc; putChar: SpecialTerminal.PutProc; ttyDisabled: BOOLEAN _ FALSE; PutChar: PROC [c: CHAR] = { IF ttyDisabled THEN RETURN; putChar[c]; }; PutString: PROC [s: LONG STRING] = { IF ttyDisabled THEN RETURN; FOR i: CARDINAL IN [0..s.length) DO putChar[s[i]]; ENDLOOP; }; PutLine: PROC [s: LONG STRING] = { IF ttyDisabled THEN RETURN; FOR i: CARDINAL IN [0..s.length) DO putChar[s[i]]; ENDLOOP; putChar[Ascii.CR]; }; commandFile: Stream.Handle _ NIL; GetFileAndSwitches: PROC[file: LONG POINTER TO TEXT] RETURNS [callDebug: BOOL _ FALSE, links: BOOL _ TRUE, disableTTY: BOOL _ FALSE] = { switchPos: INT; findString: STRING; GetToken[file]; IF file.length = 0 THEN RETURN; findString _ "/"L; switchPos _ Find[file, LOOPHOLE[LONG[findString]], 0]; IF switchPos >= 0 THEN { <> <> findString _ "-d"L; IF Find[file, LOOPHOLE[LONG[findString]], switchPos] < 0 THEN {findString _ "d"L; IF Find[file, LOOPHOLE[LONG[findString]], switchPos] > 0 THEN callDebug _ TRUE}; findString _ "-l"L; IF Find[file, LOOPHOLE[LONG[findString]], switchPos] < 0 THEN {findString _ "l"L; IF Find[file, LOOPHOLE[LONG[findString]], switchPos] > 0 THEN links _ TRUE}; findString _ "-t"L; IF Find[file, LOOPHOLE[LONG[findString]], switchPos] < 0 THEN {findString _ "t"L; IF Find[file, LOOPHOLE[LONG[findString]], switchPos] > 0 THEN disableTTY _ TRUE}; file.length _ switchPos; }; }; <> <> Find: PROC[s1, s2: LONG POINTER TO TEXT, pos1: INT _ 0] RETURNS[ans: INT _ -1] = { FOR i: NAT IN [pos1..s1.length) DO match: BOOL _ TRUE; FOR j: NAT IN [0..s2.length) DO IF (i+j >= s1.length) OR (LongString.UpperCase[s1[i+j]] # LongString.UpperCase[s2[j]]) THEN {match _ FALSE; EXIT}; ENDLOOP; IF match THEN RETURN[i]; ENDLOOP; }; GetToken: PROC[token: LONG POINTER TO TEXT] = { c: CHARACTER _ ' ; Sep: PROC [c: CHARACTER] RETURNS [BOOL] = {RETURN[SELECT c FROM ' , ',, 11C, 15C, 0C => TRUE, ENDCASE => FALSE]}; token.length _ 0; IF FileStream.EndOf[commandFile] THEN RETURN; WHILE ~FileStream.EndOf[commandFile] AND Sep[c _ Stream.GetChar[commandFile]] DO ENDLOOP; token[token.length] _ c; token.length _ token.length + 1; DO IF FileStream.EndOf[commandFile] THEN EXIT; IF Sep[c _ Stream.GetChar[commandFile]] THEN EXIT; token[token.length] _ c; token.length _ token.length + 1; ENDLOOP; }; RunTestFiles: PROC = { callDebug, links, disableTTY: BOOL; file: STRING = [40]; TryToRun: PROC = { fcap: File.Capability _ File.nullCapability; type: File.Type; prog: PrincOps.ControlModule _ PrincOps.NullControl; loadFailed: BOOLEAN _ FALSE; PutString["Looking for "L]; PutLine[file]; fcap _ Directory.Lookup[fileName: file ! ANY => CONTINUE]; IF fcap = File.nullCapability THEN {PutString["Failed to find file named "L]; PutLine[file]; RETURN} ELSE { unboundImports: BOOLEAN _ FALSE; type _ File.GetAttributes[fcap].type; PutString["Loading "L]; PutLine[file]; [cm: prog, unboundImports: unboundImports] _ Loader.Instantiate[ fcap, IF type=DCSFileTypes.tLeaderPage THEN 1 ELSE 0, links ! Loader.Error => { prefix: STRING = "Error loading "L; code: STRING _ SELECT type FROM invalidBcd => "invalidBcd"L, fileNotFound => "fileNotFound"L, versionMismatch => "versionMismatch"L, loadStateFull => "loadStateFull"L, insufficientVM => "insufficientVM"L, ENDCASE => NIL; -- can't happen msg: STRING _ Heap.systemMDSZone.NEW[StringBody[ prefix.length + file.length + 2 + code.length + (IF message = NIL THEN 0 ELSE message.length + 2)]]; LongString.AppendString[msg, prefix]; LongString.AppendString[msg, file]; LongString.AppendString[msg, ": "L]; LongString.AppendString[msg, code]; IF message ~= NIL THEN { LongString.AppendString[msg, ", "L]; LongString.AppendString[msg, LOOPHOLE[message]]; }; Runtime.CallDebugger[msg]; Heap.systemMDSZone.FREE[@msg]; loadFailed _ TRUE; CONTINUE}; ANY => {loadFailed _ TRUE; CONTINUE} ]; IF NOT loadFailed AND unboundImports THEN PutLine[" ***there are unbound imports***"L]; }; IF callDebug OR loadFailed THEN { s: STRING _ [60]; IF loadFailed THEN LongString.AppendString[s, "BasicLoader just failed to load: "L] ELSE LongString.AppendString[s, "BasicLoader just loaded: "L]; LongString.AppendString[s, file]; Runtime.CallDebugger[s]; }; IF prog # PrincOps.NullControl THEN {PutString["Starting "L]; PutLine[file]; Loader.Start[prog]}; }; DO findString: STRING = ".bcd"L; [callDebug, links, disableTTY] _ GetFileAndSwitches[LOOPHOLE[LONG[file]]]; IF disableTTY THEN {ttyDisabled _ TRUE; SpecialTerminal.TurnOff[]}; IF ttyDisabled THEN disableTTY _ TRUE; IF file.length=0 THEN EXIT; IF Find[LOOPHOLE[LONG[file]], LOOPHOLE[LONG[findString]], 0] < 0 THEN LongString.AppendString[file, findString]; TryToRun[]; ENDLOOP; }; DoLoading: PUBLIC PROC = { commandFileName: STRING = "BasicLoadees.cm"L; commandFile _ FileStream.Create[capability: Directory.Lookup[fileName: commandFileName ! ANY => CONTINUE]]; [get: getChar, put: putChar] _ SpecialTerminal.TurnOn[]; IF commandFile = NIL THEN { PutString["No "L]; PutLine[commandFileName]; ttyDisabled _ TRUE; -- leave message on screen } ELSE {RunTestFiles[]; Stream.Delete[commandFile]}; IF NOT ttyDisabled THEN SpecialTerminal.TurnOff[]; }; END.