InstallImpl.Mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Spreitzer, March 20, 1986 3:05:50 pm PST
DIRECTORY Atom, BasicTime, Commander, CommandTool, FS, HashTable, Install, InstallPrivate, IO, Process, Rope;
InstallImpl:
CEDAR
MONITOR
LOCKS d USING d: Data
IMPORTS Atom, BasicTime, Commander, CommandTool, FS, HashTable, IO, Process, Rope
EXPORTS Install
= BEGIN OPEN Install, InstallPrivate;
LORA: TYPE = LIST OF REF ANY;
FileData: TYPE = RECORD [name: ROPE, created: BasicTime.GMT];
notFound: FileData = [NIL, BasicTime.nullGMT];
data: Data ←
WITH Atom.GetProp[$InstallImplData, $InstallImplData]
SELECT
FROM
x: Data => x,
ENDCASE => NIL;
InstallCmd:
PROC [cmd: Commander.Handle]
RETURNS [result:
REF
ANY ←
NIL, msg:
ROPE ←
NIL]
--Commander.CommandProc-- = {
from: IO.STREAM = IO.RIS[cmd.commandLine];
FOR i:
INT ← from.SkipWhitespace[], from.SkipWhitespace[]
WHILE
NOT from.EndOf[]
DO
subject: ROPE = from.GetTokenRope[IO.IDProc].token;
found: BOOL;
[found, result] ← Install[subject, cmd];
IF NOT found THEN RETURN[$Failure, Rope.Cat["Failed to find load file for ", subject]];
ENDLOOP;
};
UnInstallCmd:
PROC [cmd: Commander.Handle]
RETURNS [result:
REF
ANY ←
NIL, msg:
ROPE ←
NIL]
--Commander.CommandProc-- = {
from: IO.STREAM = IO.RIS[cmd.commandLine];
FOR i:
INT ← from.SkipWhitespace[], from.SkipWhitespace[]
WHILE
NOT from.EndOf[]
DO
subject: ROPE = from.GetTokenRope[IO.IDProc].token;
UnInstall[subject, cmd];
ENDLOOP;
};
Install:
PUBLIC
PROC [subject:
ROPE, parent: Commander.Handle]
RETURNS [foundFile:
BOOL, result:
REF
ANY] = {
status: Status = Acquire[data, subject];
SELECT status.state
FROM
notDone => ERROR;
inProgress => {
finalState: State ← done;
{
ENABLE
UNWIND => SetState[data, status, notDone];
fd: FileData = Find[subject, parent];
foundFile ← fd # notFound;
SELECT foundFile ← fd # notFound
FROM
FALSE => {finalState ← notDone; result ← NIL};
TRUE => {
cp: FS.ComponentPositions;
full, dir: ROPE;
wDir: ROPE = CommandTool.CurrentWorkingDirectory[];
cd: BOOL;
[full, cp] ← FS.ExpandName[fd.name];
dir ← CommandTool.ConvertToSlashFormat[full.Substr[len: cp.base.start]];
cd ← NOT dir.Equal[wDir, FALSE];
IF cd THEN [] ← CommandTool.DoCommand[Rope.Cat["Push ", dir], parent];
result ← status.result ← CommandTool.DoCommand[Rope.Cat["Source ", full], parent];
IF cd THEN [] ← CommandTool.DoCommand["Pop", parent];
};
ENDCASE => ERROR;
};
SetState[data, status, finalState];
};
done => {foundFile ← TRUE; result ← status.result};
ENDCASE => ERROR;
};
UnInstall:
PUBLIC
PROC [subject:
ROPE, parent: Commander.Handle] = {
SetState[data, Acquire[data, subject], notDone];
};
Acquire:
ENTRY
PROC [d: Data, subject:
ROPE]
RETURNS [sought: Status] = {
ENABLE UNWIND => {};
sought ← NARROW[d.statuses.Fetch[subject].value];
IF sought =
NIL
THEN {
sought ← NEW [StatusPrivate ← []];
IF NOT d.statuses.Insert[subject, sought] THEN ERROR;
};
WHILE sought.state = inProgress DO WAIT d.change ENDLOOP;
IF sought.state = notDone THEN sought.state ← inProgress;
};
SetState:
ENTRY
PROC [d: Data, status: Status, state: State] = {
ENABLE UNWIND => {};
status.state ← state;
BROADCAST d.change;
};
Find:
PROC [subject:
ROPE, parent: Commander.Handle]
RETURNS [fd: FileData] = {
subjectDotLoad: ROPE = subject.Concat[".Load"];
loadSubjectCM: ROPE = Rope.Cat["Load", subject, ".cm"];
searchList: LORA ← CONS[CommandTool.CurrentWorkingDirectory[], NARROW[CommandTool.GetProp[parent, $SearchRules]]];
FOR searchList ← searchList, searchList.rest
WHILE searchList #
NIL
DO
wDir: ROPE = NARROW[searchList.first];
dotLoadData: FileData = GetFileData[subjectDotLoad, wDir];
loadCMData: FileData = GetFileData[loadSubjectCM, wDir];
dotLoadExists: BOOL = dotLoadData # notFound;
loadCMExists: BOOL = loadCMData # notFound;
IF dotLoadExists
OR loadCMExists
THEN {
RETURN [
IF NOT dotLoadExists THEN loadCMData ELSE
IF NOT loadCMExists THEN dotLoadData ELSE
IF BasicTime.Period[from: dotLoadData.created, to: loadCMData.created] >= 0 THEN loadCMData ELSE dotLoadData
]
};
ENDLOOP;
fd ← notFound;
};
GetFileData:
PROC [short, wDir:
ROPE]
RETURNS [fd: FileData] = {
fd ← notFound;
[fullFName: fd.name, created: fd.created] ← FS.FileInfo[name: short, wDir: wDir, remoteCheck: FALSE !FS.Error => CONTINUE];
};
Start:
PROC = {
IF data =
NIL
THEN {
data ←
NEW [DataPrivate ← [
statuses: HashTable.Create[equal: HashTable.RopeEqualModCase, hash: HashTable.HashRopeModCase]
]];
TRUSTED {
Process.InitializeCondition[@data.change, Process.SecondsToTicks[60]];
Process.EnableAborts[@data.change];
};
Atom.PutProp[$InstallImplData, $InstallImplData, data];
};
Commander.Register["Install", InstallCmd, "Do load file once"];
Commander.Register["UnInstall", UnInstallCmd, "Forget having done load file"];
};
Start[];
END.