SummonerLoadDepsImpl.mesa
Copyright Ó 1986, 1991 by Xerox Corporation. All rights reserved.
Eric Nickell, September 30, 1986 4:22:14 pm PDT
Mike Spreitzer February 9, 1987 2:37:09 pm PST
JKF January 11, 1989 10:20:44 am PST
Last tweaked by Mike Spreitzer on October 26, 1989 11:41:15 am PDT
Willie-s, September 27, 1991 2:10 pm PDT
Michael Plass, September 30, 1991 12:52 pm PDT
DIRECTORY
BasicTime USING [GMT, Period],
FileNames USING [GetShortName],
FS USING [ComponentPositions, Error, ExpandName, FileInfo, StreamOpen],
IO USING [EndOfStream, GetLineRope, GetTokenRope, IDProc, PutFLR, RIS, STREAM],
MakeDo USING [ActionClass, ActionClassRep, ActionDep, AddFinder, ConsistencyChecker, fileClass, FinderProc, From, GetNode, InnerEnumerateSources, InnerGetCreated, Node, notExistTime, PublicPartsOfAction, PublicPartsOfNode, RederiveProc, Time],
Rope USING [Cat, Concat, Fetch, Length, Match, ROPE, Substr],
SummonerLoadDeps USING [],
SymTab USING [Create, EachPairAction, Pairs, Ref, Store],
VersionMap USING [MapAndNameList, MapList, ShortNameToNames],
VersionMapDefaults USING [GetMapList];
SummonerLoadDepsImpl: CEDAR PROGRAM
IMPORTS BasicTime, FileNames, FS, IO, MakeDo, Rope, SymTab, VersionMap, VersionMapDefaults
EXPORTS SummonerLoadDeps
~ BEGIN OPEN SummonerLoadDeps;
ROPE: TYPE = Rope.ROPE;
SummonerLoadData: TYPE ~ RECORD [
summonerInstallFile, summonerInstallRoot: ROPE
];
summonerLoadClass: MakeDo.ActionClass ¬ NEW[MakeDo.ActionClassRep ¬ [
CheckConsistency: CheckSummonerLoadConsistency,
Rederive: RederiveSummonerLoad
]];
SummonerLoadFind: MakeDo.FinderProc = {
[resultName: ROPE, finderData: REF ANY] RETURNS [found: BOOLEAN, sought: MakeDo.Node, makes: MakeDo.NodeList, cmdFrom: MakeDo.NodeList, from: MakeDo.From, cmd: ROPE, class: MakeDo.ActionClass, foundData: REF ANY]
summonerLoadData: REF SummonerLoadData;
summonerInstallName: ROPE;
cp: FS.ComponentPositions;
IF ~ Rope.Match[pattern: "*.summonerLoad", object: resultName, case: FALSE] THEN GOTO Fail; --This is all we know how to build
[resultName, cp,] ¬ FS.ExpandName[name: resultName ! FS.Error => GOTO Fail];
summonerInstallName ¬ WithoutVersion[FS.FileInfo[name: Rope.Substr[base: resultName, len: cp.base.start+cp.base.length].Concat[".summonerInstall"] ! FS.Error => GOTO Fail].fullFName];
foundData ¬ summonerLoadData ¬ NEW[SummonerLoadData ¬ [
summonerInstallFile: summonerInstallName,
summonerInstallRoot: Rope.Substr[base: resultName, start: cp.base.start, len: cp.base.length]
]];
from ¬ DeriveFrom[summonerLoadData];
cmdFrom ¬ LIST[MakeDo.GetNode[someName: summonerInstallName, class: MakeDo.fileClass]];
makes ¬ LIST[sought ¬ MakeDo.GetNode[someName: resultName, class: MakeDo.fileClass]];
cmd ¬ DeriveCmd[summonerLoadData];
class ¬ summonerLoadClass;
found ¬ TRUE;
EXITS Fail => {
found ¬ FALSE;
sought ¬ NIL;
};
};
WithoutVersion: PROC [with: ROPE] RETURNS [without: ROPE] ~ {
cp: FS.ComponentPositions;
[fullFName: without, cp: cp] ¬ FS.ExpandName[name: with];
without ¬ Rope.Substr[base: without, len: cp.ext.start+cp.ext.length];
};
DeriveCmd: PROC [summonerLoadData: REF SummonerLoadData] RETURNS [cmd: ROPE] ~ {
RETURN [Rope.Concat["RederiveSummonerLoad ", summonerLoadData.summonerInstallRoot]];
};
DeriveFrom: PROC [summonerLoadData: REF SummonerLoadData] RETURNS [from: MakeDo.From] ~ {
PutFilesInFromList: SymTab.EachPairAction = {
[key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL]
from.mustHave ¬ CONS[MakeDo.GetNode[someName: key, class: MakeDo.fileClass], from.mustHave];
RETURN [FALSE]
};
Install: PROC [module, file: ROPE] ~ {
[] ¬ SymTab.Store[x: x, key: file, val: NIL];
from.mustHave ← CONS[MakeDo.GetNode[someName: file, class: MakeDo.fileClass], from.mustHave];
};
s: IO.STREAM ¬ FS.StreamOpen[fileName: summonerLoadData.summonerInstallFile];
x: SymTab.Ref ~ SymTab.Create[case: FALSE];
from ¬ [mustHave: LIST[MakeDo.GetNode[someName: FS.ExpandName[name: summonerLoadData.summonerInstallFile].fullFName, class: MakeDo.fileClass]], optional: NIL];
RecurseThroughInstall[file: summonerLoadData.summonerInstallFile, install: Install, run: NIL, other: NIL, recurseVMap: FALSE ! CantFind => {Install[module: module, file: FileNames.GetShortName[path: full]]; RESUME}];
[] ¬ SymTab.Pairs[x: x, action: PutFilesInFromList];
};
ForceConsistencyReturn: ERROR [setConsistent: BOOL, setReason: ROPE] ~ CODE;
CheckSummonerLoadConsistency: MakeDo.ConsistencyChecker = {
[a: MakeDo.Action, result: MakeDo.Node] RETURNS [consistent: BOOL, reason: ROPE]
ingredientFound: BOOL ¬ FALSE;
PerIngredient: PROC [n: MakeDo.Node, which: MakeDo.ActionDep, optional: BOOL] ~ {
nodeTime: BasicTime.GMT ¬ MakeDo.InnerGetCreated[n];
IF nodeTime = MakeDo.notExistTime THEN RETURN;
ingredientFound ¬ TRUE;
IF resultExists AND BasicTime.Period[from: nodeTime, to: resultTime] < 0 THEN ERROR ForceConsistencyReturn[setConsistent: FALSE, setReason: IO.PutFLR[format: "result %g (of %g) predates ingredient %g (of %g)", list: LIST[[rope[resultName]], [time[resultTime]], [rope[MakeDo.PublicPartsOfNode[n: n].name]], [time[nodeTime]]]]];
RETURN};
summonerLoadData: REF SummonerLoadData ~ NARROW[MakeDo.PublicPartsOfAction[a].foundData];
resultTime: MakeDo.Time = result.InnerGetCreated[];
resultName: ROPE = MakeDo.PublicPartsOfNode[n: result].name;
resultExists: BOOL ~ resultTime # MakeDo.notExistTime;
MakeDo.InnerEnumerateSources[a: a, which: data, to: PerIngredient ! ForceConsistencyReturn => {
consistent ¬ setConsistent;
reason ¬ setReason;
GOTO Exit;
}];
IF NOT ingredientFound THEN RETURN [TRUE, "no inputs exist to indicate inconsistency"];
IF NOT resultExists THEN RETURN [FALSE, "some inputs but no output exist"];
RETURN [consistent: TRUE, reason: "result dated later than any existing ingredient"];
EXITS Exit => a ¬ a;
};
RederiveSummonerLoad: MakeDo.RederiveProc = {
[a: MakeDo.Action] RETURNS [from: MakeDo.From, cmd: ROPE]
summonerLoadData: REF SummonerLoadData ~ NARROW[MakeDo.PublicPartsOfAction[a].foundData];
from ¬ DeriveFrom[summonerLoadData];
cmd ¬ DeriveCmd[summonerLoadData];
};
CantFind: PUBLIC SIGNAL [module, full: ROPE] ~ CODE; --Called by RecurseThroughInstall when it has to resort to a version map
RecurseThroughInstall: PUBLIC PROC [file: ROPE, install: PROC [module, file: ROPE], run: PROC [package: ROPE], other: PROC [line: ROPE], checkVMap, recurseVMap: BOOL ¬ TRUE] ~ {
stream: IO.STREAM ~ FS.StreamOpen[fileName: file];
DO
line: ROPE ~ IO.GetLineRope[stream ! IO.EndOfStream => EXIT];
SELECT TRUE FROM
Rope.Match[pattern: "install *", object: line, case: FALSE] => {
s: IO.STREAM ~ IO.RIS[rope: line];
word: ROPE ¬ IO.GetTokenRope[stream: s, breakProc: IO.IDProc].token;
DO
attemptRecurse: BOOL ¬ TRUE;
TryLocalDirectory: PROC [name: ROPE] RETURNS [succeeded: BOOL] ~ {
file ¬ FS.FileInfo[name: name ! FS.Error => {file ¬ NIL; CONTINUE}].fullFName;
RETURN [file#NIL]
};
TryVersionMap: PROC [name: ROPE] RETURNS [succeeded: BOOL] ~ {
IF ~checkVMap THEN RETURN [FALSE]
ELSE {
map: VersionMap.MapList ~ VersionMapDefaults.GetMapList[which: $Source];
manl: VersionMap.MapAndNameList ~ VersionMap.ShortNameToNames[list: map, shortName: name];
FOR each: VersionMap.MapAndNameList ¬ manl, each.rest UNTIL each=NIL DO
file ¬ FS.FileInfo[name: each.first.name ! FS.Error => LOOP].fullFName;
SIGNAL CantFind[word, each.first.name];
attemptRecurse ¬ recurseVMap;
RETURN [TRUE];
ENDLOOP;
RETURN [FALSE];
};
};
file: ROPE ¬ NIL;
word ¬ IO.GetTokenRope[stream: s, breakProc: IO.IDProc ! IO.EndOfStream => EXIT].token;
SELECT TRUE FROM
TryLocalDirectory[Rope.Concat[word, ".require"]] => {};
TryLocalDirectory[Rope.Cat["Load", word, ".command"]] => {};
TryVersionMap[Rope.Concat[word, ".require"]] => {};
TryVersionMap[Rope.Cat["Load", word, ".command"]] => {};
ENDCASE => {
short: ROPE ~ Rope.Concat[word, ".require"];
SIGNAL CantFind[module: word, full: FS.ExpandName[short].fullFName];
};
IF ~ Rope.Fetch[base: word]='- AND install#NIL THEN install[module: word, file: file];
IF file#NIL AND attemptRecurse THEN RecurseThroughInstall[file: file, install: install, run: run, other: other, checkVMap: checkVMap, recurseVMap: recurseVMap];
ENDLOOP;
};
Rope.Match[pattern: "run *", object: line, case: FALSE] => {
s: IO.STREAM ~ IO.RIS[rope: line];
word: ROPE ¬ IO.GetTokenRope[stream: s, breakProc: IO.IDProc].token;
DO
word ¬ IO.GetTokenRope[stream: s, breakProc: IO.IDProc ! IO.EndOfStream => EXIT].token;
IF ~ Rope.Fetch[base: word]='- AND run#NIL THEN run[word];
ENDLOOP;
};
ENDCASE => {
IF line.Length[] > 0 AND other#NIL THEN other[line];
};
ENDLOOP;
};
MakeDo.AddFinder[finder: [name: "SummonerLoad", finderProc: SummonerLoadFind], end: front];
END.