VBoot.mesa
Russ Atkinson, January 20, 1982 8:57 pm
McGregor, October 27, 1982 4:01 pm
Dan Swinehart, March 8, 1982 8:16 am
Roy Levin, June 11, 1982 4:53 pm
Warren Teitelman, June 25, 1982 2:16 pm
Last Edited by: Maxwell, January 3, 1983 1:42 pm
DIRECTORY
Buttons,
ConvertUnsafe USING [ToRope],
Directory USING [Error, Lookup],
File USING [Capability, read, Unknown],
MessageWindow USING [Append, Blink, Clear, Confirm],
Rope, --using lots
TemporaryBooting, --using lots
UserProfile USING [Line],
UserTerminal USING [BlinkDisplay],
VBootOps USING [],
ViewerClasses USING [Viewer],
ViewerOps USING [EnumerateViewers, EnumProc],
ViewerTools USING [GetSelectionContents],
Volume; --using lots
VBoot: CEDAR MONITOR IMPORTS Buttons, ConvertUnsafe, Directory, File, MessageWindow,
Rope, TemporaryBooting, UserProfile, UserTerminal, ViewerOps, ViewerTools, Volume
EXPORTS VBootOps
SHARES File
= BEGIN OPEN Rope;
MyData: TYPE = REF MyDataRep;
MyDataRep: TYPE = RECORD
[name: ROPE, volID: Volume.ID, file: BOOLFALSE];
nullSwitches: SwitchesArray ← ALL[FALSE];
Switches: TYPE = REF SwitchesArray;
SwitchesArray: TYPE = PACKED ARRAY [0..36) OF BOOLALL[FALSE];
must be bitwise equivalent to TemporaryBooting.Switches
first 10 elements are switches 0..9
last 26 elements are switches A..Z (or a..z)
GetSwitches: PROC [name: ROPE] RETURNS [Switches] = {
sw: ROPE ← UserProfile.Line[name.Concat["Switches"]];
switches: Switches ← NEW[SwitchesArray ← nullSwitches];
SetSwitches[sw, switches];
RETURN [switches];
};
SetSwitches was broken out as separate procedure so can be called on switches that are typed in.
SetSwitches: PROC [sw: ROPE, switches: Switches] = {
FOR i: INT IN [0..sw.Length[]) DO
c: CHAR ← sw.Fetch[i];
si: CARDINAL ← 0;
SELECT c FROM
IN['0..'9] => switches^[c-'0] ← TRUE;
IN['A..'Z] => switches^[10+(c-'A)] ← TRUE;
IN['a..'z] => switches^[10+(c-'a)] ← TRUE;
ENDCASE;
ENDLOOP;
};
BootProc: Buttons.ButtonProc = TRUSTED {
viewer: ViewerClasses.Viewer ~ NARROW[parent];
data: MyData ← NARROW[clientData];
IF SomethingWorthSaving[] THEN RETURN;
Buttons.SetDisplayStyle[viewer, $BlackOnGrey];
IF data.file THEN BootFromFile[data]
ELSE IF data.volID = Volume.nullID
THEN TemporaryBooting.BootButton[LOOPHOLE[GetSwitches[data.name]^]]
ELSE TemporaryBooting.BootFromVolume[data.volID, LOOPHOLE[GetSwitches[data.name]^]];
Buttons.SetDisplayStyle[viewer, $BlackOnWhite];
};
BasicCedarDorado: Buttons.ButtonProc = {
viewer: ViewerClasses.Viewer ~ NARROW[parent];
IF SomethingWorthSaving[] THEN RETURN;
Buttons.SetDisplayStyle[viewer, $BlackOnGrey];
BootFromFileName["BasicCedarDorado"];
Buttons.SetDisplayStyle[viewer, $BlackOnWhite];
};
SomethingWorthSaving: PROC RETURNS[BOOLEAN] =
BEGIN
dirty: BOOLEANFALSE;
CheckDirty: ViewerOps.EnumProc = {dirty ← v.newVersion OR v.newFile OR dirty};
ViewerOps.EnumerateViewers[CheckDirty];
IF dirty THEN {
MessageWindow.Blink[];
IF ~MessageWindow.Confirm["Confirm discard of edits . . . "] THEN {
MessageWindow.Append["boot aborted."];
RETURN[TRUE]}};
RETURN[FALSE];
END;
BootFromFile: PROC [data: MyData] = BEGIN
BootFromFileName[ViewerTools.GetSelectionContents[]];
END;
BootFromFileName: PUBLIC PROC [file: ROPE] = TRUSTED BEGIN
ENABLE BEGIN
TemporaryBooting.InvalidParameters => {MessageWindow.Append["Not a boot file: ", TRUE]; GOTO putName};
File.Unknown => {MessageWindow.Append["File unknown: ", TRUE]; GOTO putName};
Directory.Error => {MessageWindow.Append["Directory search failed: ", TRUE]; GOTO putName};
END;
cap: File.Capability;
sw: ROPE;
switches: VBoot.Switches;
i: INT;
IF Rope.Length[file]=0 THEN {UserTerminal.BlinkDisplay[]; RETURN};
IF (i ← Rope.Find[file, "/"]) # -1 THEN {sw ← Rope.Substr[base: file, start: i + 1]; file ← Rope.Substr[base: file, len: i]};
IF ~Rope.Equal[Rope.Substr[file, Rope.Length[file]-5,5],".boot",FALSE] THEN
file ← Rope.Cat[file, ".boot"];
cap ← [Directory.Lookup[LOOPHOLE[Rope.Flatten[file]]].fID, File.read];
TemporaryBooting.MakeBootable[cap, 1];
Boot file starts at page 1 for a leader page file
Now issue a message and await confirmation to boot
switches ← GetSwitches["File"];
SetSwitches[sw, switches];
TemporaryBooting.BootFromFile[cap, 1, LOOPHOLE[switches^]];
EXITS putName => MessageWindow.Append[file];
END;
buttonsCreated: BOOLFALSE;
BootButtonsProc: ENTRY Buttons.ButtonProc = BEGIN
IF ~ buttonsCreated THEN BEGIN
viewer: ViewerClasses.Viewer ~ NARROW[parent];
MakeBootButtons[];
buttonsCreated ← TRUE;
END;
END;
MakeBootButtons: PROC = {
name: ROPE;
volID: Volume.ID ← Volume.nullID;
types: Volume.TypeSet ← ALL[TRUE];
data: MyData ;
MessageWindow.Clear[]; -- so can put up buttons faster
data ← NEW[MyDataRep ← [name: "Alto", volID: volID]];
[] ← Buttons.Create[info: [name: "Alto"], proc: BootProc, clientData: data, guarded: TRUE];
data ← NEW[MyDataRep ← [name: "File", volID: volID, file: TRUE]];
[] ← Buttons.Create[info: [name: "File"], proc: BootProc, clientData: data, guarded: TRUE, fork: TRUE];
data ← NEW[MyDataRep ← [name: "Basic", volID: volID, file: TRUE]];
[] ← Buttons.Create[info: [name: "Basic"], proc: BasicCedarDorado, clientData: data, guarded: TRUE, fork: TRUE];
DO
volName: STRING ← [Volume.maxNameLength];
volID ← Volume.GetNext[volID, types];
IF volID = Volume.nullID THEN EXIT;
TRUSTED {Volume.GetLabelString[volID, volName]};
TRUSTED {name ← ConvertUnsafe.ToRope[volName]};
data ← NEW[MyDataRep ← [name: name, volID: volID, file: FALSE]];
[] ← Buttons.Create[info: [name: name], proc: BootProc, clientData: data, guarded: TRUE];
ENDLOOP;
};
[] ← Buttons.Create[info: [name: "Boot"], proc: BootButtonsProc];
END.
June 21, 1982 4:58 pm W. Teitelman. Removed switches field from data. Arranged for switches to be computed at time of boot in order to allow user to have changed his profile and/or logged in as somebody else before booting. Broke BootFromFileName out from BootFromFile so possible to write a program which boots from a specific file. Added ability to specify switches with file name, e.g. basiccedardorado/d