SummonerLoadDepsImpl.mesa
Copyright © 1986 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
DIRECTORY
BasicTime USING [GMT, Period],
FileNames USING [GetShortName],
FS USING [ComponentPositions, Error, ExpandName, FileInfo, StreamOpen],
IO USING [EndOfStream, GetLineRope, GetTokenRope, IDProc, PutFR, 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.Cat["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.STREAMFS.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: BOOLFALSE;
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.PutFR[format: "result %g (of %g) predates ingredient %g (of %g)", v1: [rope[resultName]], v2: [time[resultTime]], v3: [rope[MakeDo.PublicPartsOfNode[n: n].name]], v4: [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: BOOLTRUE] ~ {
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: ROPEIO.GetTokenRope[stream: s, breakProc: IO.IDProc].token;
DO
attemptRecurse: BOOLTRUE;
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: ROPENIL;
word ← IO.GetTokenRope[stream: s, breakProc: IO.IDProc ! IO.EndOfStream => EXIT].token;
SELECT TRUE FROM
TryLocalDirectory[Rope.Cat[word, ".load"]] => {};
TryLocalDirectory[Rope.Cat["Load", word, ".cm"]] => {};
TryVersionMap[Rope.Cat[word, ".load"]] => {};
TryVersionMap[Rope.Cat["Load", word, ".cm"]] => {};
ENDCASE => {
short: ROPE ~ Rope.Cat[word, ".load"];
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: ROPEIO.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.