MimosaAndCinderDeps.Mesa
Copyright Ó 1988, 1991, 1992 by Xerox Corporation. All rights reserved.
Eduardo Pelegri-Llopart, December 12, 1989 1:00:30 pm PST
After ConfigAndMesaDeps.mesa
Deals with Mimosa and Cinder. Output files are .mob and .c2c.c
Bill Jackson (bj) January 16, 1989 1:33:06 pm PST
Last tweaked by Mike Spreitzer on December 18, 1990 7:35 am PST
JKF January 11, 1989 10:22:44 am PST
Willie-s, September 27, 1991 2:44 pm PDT
Michael Plass, November 27, 1991 10:34 am PST
Doug Wyatt, March 11, 1992 1:45 pm PST
DIRECTORY
Atom,
Basics USING [IsBound],
BasicTime USING [GMT, Period, ToNSTime],
FileNames USING [CurrentWorkingDirectory],
FS USING [ComponentPositions, Error, ExpandName, StreamOpen],
IO,
MakeDo USING [Action, ActionClass, ActionClassRep, AddFinder, fileClass, From, GetNode, GetProp, InnerGetCreated, Node, NodeList, notExistTime, PublicPartsOfAction, PublicPartsOfNode, SetProp, Time, Warning],
MakeDoParsers,
MakeDoPrivate USING [MDInstall],
MakeDoPorting USING [logPath],
MobDefs USING [Base, FTHandle, FTIndex, FTNull, FTRecord, FTSelf, MobBase, NameRecord, NameString, NullVersion, VersionID, VersionStamp],
Mobery USING [FlushCache, StampAndNameFromFile],
MobListerUtils USING [FreeMob, MobErr, PrintVersion, ReadMob],
RefTab,
Rope,
SimpleFeedback,
UserProfile USING [CallWhenProfileChanges, ProfileChangedProc, Boolean];
MimosaAndCinderDeps: CEDAR MONITOR
IMPORTS Atom, Basics, BasicTime, FileNames, FS, IO, MakeDo, MakeDoParsers, MakeDoPrivate, MakeDoPorting, Mobery, MobListerUtils, RefTab, Rope, SimpleFeedback, UserProfile =
INVARIANT
StampRef in node props
BEGIN OPEN MakeDo, MDPs:MakeDoParsers;
ShouldNotHappen: ERROR = CODE;
ROPE: TYPE = Rope.ROPE;
CachedMobData: TYPE = REF CachedMobDataRep; CachedMobDataRep: TYPE = RECORD [
created: BasicTime.GMT,
date when the information was obtained
stamp: MobDefs.VersionStamp,
stamp of the mob
sourceStamp: MobDefs.VersionStamp,
stamp of the source file it depends on
dependList: RefTab.Ref
files (name+version) that this mob object depends on (same type as Support)
];
SourceData: TYPE = REF SourceDataRep; SourceDataRep: TYPE = RECORD [
mobName, cName, shortName: ROPE,
sourceType: SourceType ¬ Unknown,
resultType: ResultType ¬ Unknown,
supports: RefTab.Ref,
mesaNode, cedarNode, configNode, sourceNode, switchesNode, mobNode, cNode: Node,
sourceStamp, mobStamp: MobDefs.VersionStamp ¬ MobDefs.NullVersion,
sourceStamp is the desired stamp encoded in the Mob file
mobStamp is the desired stamp encoded in the C file (currently unused)
mobCreateTime, cCreateTime: BasicTime.GMT,
mobReadable, cReadable: BOOL ¬ FALSE,
supportsInvalid: BOOL ¬ FALSE,
cmd: ROPE ¬ NIL
];
SourceType: TYPE = MDPs.SourceType[Unknown .. Config];
ResultType: TYPE = MDPs.ResultType[Unknown .. MobOnly];
Support: TYPE = REF SupportRep; SupportRep: TYPE = RECORD [
node: Node,
version: MobDefs.VersionStamp];
A description of the properties of a Mob file that will support our action.
installDir: ROPE ~ FileNames.CurrentWorkingDirectory[];
installed, badInstall: BOOL ¬ FALSE;
dolog: BOOL ¬ FALSE;
myRouterName: ATOM ~ Atom.MakeAtom["MakeDo.MimosaAndCinderDeps"];
Constants
cinderDefaultSwitch: ROPE ¬ " -m~g "; -- used to be /l - bj
mimosaDefaultSwitch: ROPE ¬ " -kc ";
cTail: ROPE = ".c2c.c";
cTailLength: CARDINAL = cTail.Length[];
mobExt: ROPE = "mob";
mobTail: ROPE = Rope.Concat[".", mobExt];
mesaTail: ROPE = ".mesa";
cedarTail: ROPE = ".cedar";
configTail: ROPE = ".config";
switchesTail: ROPE = ".switches";
MimosaAndCinderClass: ActionClass ¬ NEW [ActionClassRep ¬ [
CheckConsistency: CheckConsistency,
Rederive: RederiveSource,
EnumHiddenDeps: EnumHiddenDeps,
ClearCaches: ClearCaches
]];
ClearCaches: PROC [ac: ActionClass] ~ {
Mobery.FlushCache[];
MDPs.FlushCache[];
installed ¬ badInstall ¬ FALSE;
};
SourceFind: PROC [resultName: ROPE, finderData: REF ANY] RETURNS [found: BOOLEAN, sought: Node, makes, cmdFrom: NodeList, from: From, cmd: ROPE, class: ActionClass, foundData: REF ANY] -- FinderProc -- ~ {
A FinderProc looks for an action that will make an object with name resultName. It returns an indication of whether it found it, a pointer to the node describing the object, and a list of the nodes produced by the action. cmdFrom is a list of the determiners, while from is a list of all the nodes needed by the action to be runnable, discriminating between mandatory and optional nodes. FoundData is a record holding all the useful information that may be needed later.
The action found by this finder is "MimosaAndCinder", selecting which one is to be used is done every time RederiveWork is called.
mobExpanded, baseName, shortName, mobName, cName: ROPE;
mobCP: FS.ComponentPositions;
mobNode, cNode: Node;
isMob, isC2C: BOOL ¬ FALSE;
md: SourceData;
found ¬ TRUE;
IF badInstall THEN {found ¬ FALSE; RETURN};
[mobExpanded, mobCP, ] ¬ FS.ExpandName[resultName !FS.Error => {found ¬ FALSE; CONTINUE}];
IF NOT found THEN RETURN;
isMob ¬ mobExpanded.EqualSubstrs[start1: mobCP.ext.start, len1: mobCP.ext.length, s2: mobExt, case: FALSE];
IF mobCP.ext.start + mobCP.ext.length >= cTailLength
THEN {
isC2C ¬ mobExpanded.EqualSubstrs[start1: mobCP.ext.start+mobCP.ext.length-cTailLength, len1: cTailLength, s2: cTail, case: FALSE];
} ELSE {
isC2C ¬ FALSE;
};
IF NOT (found ¬ isMob OR isC2C) THEN RETURN;
We only know what to do with .Mob and .C2C.C files.
IF NOT installed THEN InstallMe[];
found ¬ NOT badInstall;
IF NOT found THEN RETURN;
baseName ¬ mobExpanded.Substr[start: 0, len: mobCP.base.start + mobCP.base.length];
shortName ¬ mobExpanded.Substr[start: mobCP.base.start, len: mobCP.base.length];
IF isC2C THEN {
Compensate for the cTail;
baseName ¬ Rope.Substr[baseName, 0, baseName.Length[]-(cTailLength-2)];
shortName ¬ Rope.Substr[shortName, 0, shortName.Length[]-(cTailLength-2)];
};
mobNode ¬ GetNode[mobName ¬ Rope.Concat[baseName, mobTail], fileClass];
cNode ¬ GetNode[cName ¬ Rope.Concat[baseName, cTail], fileClass];
foundData ¬ md ¬ NEW [SourceDataRep ¬ [
mobName: mobName,
cName: cName,
shortName: shortName,
supports: RefTab.Create[],
mesaNode: GetNode[baseName.Concat[mesaTail], fileClass],
cedarNode: GetNode[baseName.Concat[cedarTail], fileClass],
configNode: GetNode[baseName.Concat[configTail], fileClass],
cNode: cNode,
sourceNode: NIL,
switchesNode: GetNode[mobName.Concat[switchesTail], fileClass],
mobNode: mobNode,
mobCreateTime: MakeDo.notExistTime,
cCreateTime: MakeDo.notExistTime
]];
cmdFrom ¬ LIST[md.cedarNode, md.mesaNode, md.configNode, md.switchesNode];
sought ¬ IF isC2C THEN md.cNode ELSE md.mobNode;
class ¬ MimosaAndCinderClass;
[from, cmd] ¬ RederiveWork[md];
makes ¬ LIST[md.cNode, md.mobNode];
this is a superset of the truth, but it works if we are careful elsewhere.
We have to do this because actions, and Makes, are fixed.
RETURN};
GetSwitches: PROC [mobName: ROPE, default: ROPE ¬ NIL] RETURNS [switches: ROPE] =
BEGIN
ss: IO.STREAM ¬ NIL;
ss ¬ FS.StreamOpen[Rope.Concat[mobName, switchesTail] !FS.Error => CONTINUE];
IF ss = NIL THEN RETURN [default];
[] ¬ ss.SkipWhitespace[];
IF ss.EndOf[] THEN { ss.Close[]; RETURN [default] } ;
switches ¬ ss.GetTokenRope[IO.IDProc].token;
ss.Close[];
END;
SupportIsLoaded: PROC [] RETURNS [BOOL] ~ INLINE {
moberies: BOOL;
moblisteries: BOOL;
moberies ¬ Basics.IsBound[LOOPHOLE[Mobery.StampAndNameFromFile]];
moblisteries ¬ Basics.IsBound[LOOPHOLE[MobListerUtils.PrintVersion]] AND Basics.IsBound[LOOPHOLE[MobListerUtils.ReadMob]];
LOOPHOLE only needed for PrincOps
RETURN [moberies AND moblisteries];
};
InstallMe: PROC ~ {
foundFile, failed: BOOL;
IF SupportIsLoaded[] THEN {
installed ¬ TRUE;
RETURN;
};
[foundFile, failed] ¬ MakeDoPrivate.MDInstall[installDir, "MimosaAndCinderDepsSupport"];
badInstall ¬ failed OR NOT foundFile;
installed ¬ TRUE;
IF NOT foundFile THEN Warning[Rope.Cat["Couldn't install MimosaAndCinder support because couldn't find ", installDir, "MimosaAndCinderDepsSupport.Install (see ",
MakeDoPorting.logPath, "MimosaAndCinderDepsSupport.InstallLog); proceeding without knowledge of MimosaAndCinder"]]
ELSE IF failed THEN Warning[Rope.Cat["Couldn't install MimosaAndCinder support because of error in install file (", installDir, "MimosaAndCinderDepsSupport.Install) (see ", MakeDoPorting.logPath, "MimosaAndCinderDepsSupport.InstallLog); proceeding without knowledge of MimosaAndCinder"]];
RETURN};
CheckConsistency: PROC [a: Action, result: Node] RETURNS [consistent: BOOL, reason: ROPE] --ConsistencyChecker-- ~ {
Is an action a consistent with a current result? The action is derived from the current determiners and result is in Makes of the action.
md: SourceData = NARROW[a.PublicPartsOfAction[].foundData];
switchesCreate: BasicTime.GMT = InnerGetCreated[md.switchesNode];
resultName: ROPE ~ result.PublicPartsOfNode[].name;
resultCreateTime: Time = InnerGetCreated[result];
resultExists: BOOL ~ resultCreateTime # MakeDo.notExistTime;
curMobStamp: MobDefs.VersionStamp; -- Stamp from the current Mob file of the action --
supportFound: BOOL ¬ FALSE;
seekMob: BOOL ~ result = md.mobNode;
seekC: BOOL ~ result = md.cNode;
CheckSupport: PROC [key, val: REF ANY] RETURNS [stop: BOOL ¬ FALSE] --RefTab.EachPairAction-- ~ {
What to check depends on what we have available.
for .MOBs, look inside and get the version stamp,
for other lesser files, we currently have to rely on their creation date.
s: Support = NARROW[val];
thisTime: Time = InnerGetCreated[s.node];
thisMobStamp: MobDefs.VersionStamp = CurMobStamp[s.node];
thisName: Rope.ROPE ~ s.node.PublicPartsOfNode[].name;
extension, fullName: Rope.ROPE;
cp: FS.ComponentPositions;
[fullFName: fullName, cp: cp] ¬
FS.ExpandName[thisName ! FS.Error => { ERROR ShouldNotHappen}];
extension ¬ Rope.Substr[fullName, cp.ext.start, cp.ext.length];
SELECT TRUE FROM
Rope.Equal[s1: extension, s2: mobExt, case: FALSE] => {
Use the version stamp
IF thisMobStamp = MobDefs.NullVersion THEN RETURN [FALSE];
supportFound ¬ TRUE;
IF NOT resultExists THEN RETURN [supportFound];
IF thisMobStamp # s.version THEN {
out: IO.STREAM ¬ IO.ROS[];
out.PutRope["last used version "];
TRUSTED {MobListerUtils.PrintVersion[s.version, out, FALSE]};
out.PutF1[
" of %g, but current version is ",
[rope[thisName]]
];
TRUSTED {MobListerUtils.PrintVersion[thisMobStamp, out, FALSE]};
consistent ¬ FALSE;
reason ¬ out.RopeFromROS[];
RETURN [TRUE];
}
ELSE RETURN [NOT resultExists];
};
ENDCASE => {
Only data available is the creation time
IF thisTime = MakeDo.notExistTime THEN RETURN [FALSE];
supportFound ¬ TRUE;
IF NOT resultExists THEN RETURN [supportFound];
IF BasicTime.Period[thisTime, resultCreateTime] < 0 THEN {
out: IO.STREAM ¬ IO.ROS[];
out.PutRope["File created in "];
TRUSTED {MobListerUtils.PrintVersion[MobStampFromTime[resultCreateTime], out, TRUE]};
out.PutF1[
" but %g was created in ",
[rope[thisName]]
];
TRUSTED {MobListerUtils.PrintVersion[MobStampFromTime[thisTime], out, TRUE]};
consistent ¬ FALSE;
reason ¬ out.RopeFromROS[];
RETURN [TRUE];
}
ELSE RETURN [NOT resultExists];
};
};
UpdateSupport[md];
SELECT md.sourceType FROM
Mesa, Config => NULL;
Unknown => RETURN [TRUE, "No source is known for this result"];
ENDCASE => ERROR ShouldNotHappen;
IF md.resultType = MobOnly AND seekC THEN
IF md.cCreateTime = MakeDo.notExistTime
THEN RETURN [TRUE, "no amount of recompilation will derive a .c2c.c file from a .mesa interface"]
ELSE RETURN [FALSE, "C2C file should not exist for a .mesa interface"];
SELECT TRUE FROM
seekC => IF resultExists AND NOT md.cReadable THEN RETURN [FALSE, "c not readable"];
seekMob => IF resultExists AND NOT md.mobReadable THEN RETURN [FALSE, "mob not readable"];
ENDCASE => ERROR ShouldNotHappen;
{curSourceStamp: MobDefs.VersionStamp ~ CurSourceStamp[md.sourceNode];
IF curSourceStamp # MobDefs.NullVersion THEN {
supportFound ¬ TRUE;
IF md.mobReadable AND resultExists AND curSourceStamp # md.sourceStamp THEN {
out: IO.STREAM ¬ IO.ROS[];
out.PutRope["last used source "];
TRUSTED {MobListerUtils.PrintVersion[md.sourceStamp, out, TRUE]};
out.PutRope[", but current source is "];
TRUSTED {MobListerUtils.PrintVersion[curSourceStamp, out, TRUE]};
RETURN [FALSE, out.RopeFromROS[]];
};
};
};
curMobStamp ¬ CurMobStamp[md.mobNode];
IF seekMob AND resultExists THEN {
IF curMobStamp = MobDefs.NullVersion THEN RETURN [FALSE, "New compiler version"];
Since createtime is non-null.
};
IF seekC AND resultExists THEN {
IF md.mobStamp # MobDefs.NullVersion
THEN {
Check the VersionStamp
IF curMobStamp # md.mobStamp THEN {
out: IO.STREAM ¬ IO.ROS[];
out.PutRope["last used mob "];
TRUSTED {MobListerUtils.PrintVersion[md.mobStamp, out, TRUE]};
out.PutRope[", but current mob is "];
TRUSTED {MobListerUtils.PrintVersion[curMobStamp, out, TRUE]};
RETURN [FALSE, out.RopeFromROS[]];
};
}
ELSE {
Chek the Creation Date
IF BasicTime.Period[md.cCreateTime, md.mobCreateTime] > 0 THEN RETURN [FALSE, "C2C is older than MobFile file"];
}
};
IF switchesCreate # MakeDo.notExistTime THEN {
supportFound ¬ TRUE;
IF BasicTime.Period[resultCreateTime, switchesCreate] > 0 THEN RETURN [FALSE, IO.PutFR1["switches file created later than result %g", [rope[resultName]]]];
};
consistent ¬ TRUE;
reason ¬ "all version stamps match";
[] ¬ md.supports.Pairs[CheckSupport];
IF NOT supportFound THEN RETURN [TRUE, "no inputs exist"];
IF NOT resultExists THEN RETURN [FALSE, IO.PutFR1["some inputs exist, but not output %g", [rope[resultName]]]];
RETURN};
UpdateSupport: PROC [md: SourceData] = {
Update the information that may have changed since last time. If the mobCreateTime is the same as before and supportsInvalid is FALSE, then no need to.
oldMob: Time = md.mobCreateTime;
oldC: Time = md.cCreateTime;
md.mobCreateTime ¬ InnerGetCreated[md.mobNode];
md.cCreateTime ¬ InnerGetCreated[md.cNode];
IF md.mobCreateTime = MakeDo.notExistTime THEN RETURN;
IF md.mobCreateTime = oldMob AND md.cCreateTime = oldC AND NOT md.supportsInvalid THEN RETURN;
MakeSupports[md];
};
CurSourceStamp: PROC [node: Node] RETURNS [mobStamp: MobDefs.VersionStamp] =
Fake a version stamp for a source file out of its creation date.
BEGIN
time: Time ¬ InnerGetCreated[node];
RETURN [MobStampFromTime[time]];
END;
MobStampFromTime: PROC [time: Time] RETURNS [mobStamp: MobDefs.VersionStamp] =
A MobStamp from a time
BEGIN
mobStamp ¬ MobDefs.NullVersion;
IF time = MakeDo.notExistTime THEN RETURN [mobStamp];
mobStamp[0] ¬ BasicTime.ToNSTime[time];
END;
CurMobStamp: PROC [node: Node] RETURNS [stamp: MobDefs.VersionStamp] ~ {
sr: CachedMobData ¬ CurMobData[node];
RETURN [sr.stamp];
};
CurMobData: ENTRY PROC [node: Node] RETURNS [sr: CachedMobData] =
Find the version stamp of this Mob file.
BEGIN
ENABLE UNWIND => {};
sr: CachedMobData ¬ NARROW[node.GetProp[$MobData]];
created: BasicTime.GMT ¬ InnerGetCreated[node];
mob: MobDefs.MobBase ¬ NIL;
IF sr = NIL THEN node.SetProp[
prop: $MobData,
val: sr ¬ NEW [CachedMobDataRep ¬ [
created: notExistTime,
stamp: MobDefs.NullVersion,
sourceStamp: MobDefs.NullVersion,
dependList: RefTab.Create[]]]
];
IF created = sr.created THEN RETURN [sr];
sr.created ¬ created;
IF created = MakeDo.notExistTime
THEN {
sr.stamp ¬ MobDefs.NullVersion;
sr.sourceStamp ¬ MobDefs.NullVersion;
sr.dependList ¬ RefTab.Create[];
}
ELSE TRUSTED {
fileName: ROPE ~ node.PublicPartsOfNode[].name;
mob ¬ MobListerUtils.ReadMob[fileName ! MobListerUtils.MobErr => CONTINUE];
IF mob = NIL OR mob.versionIdent # MobDefs.VersionID
THEN {
sr.stamp ¬ MobDefs.NullVersion;
sr.sourceStamp ¬ MobDefs.NullVersion;
sr.dependList ¬ RefTab.Create[];
}
ELSE {
InsertInDependList: PROC [name: ROPE, version: MobDefs.VersionStamp] = TRUSTED {
extName: ROPE = FS.ExpandName[Rope.Concat[name, mobTail]].fullFName;
node: Node = GetNode[extName, fileClass];
s: Support ¬ NARROW[sr.dependList.Fetch[node].val];
IF s # NIL
THEN s.version ¬ version
ELSE {
s ¬ NEW [SupportRep ¬ [node, version]];
IF NOT sr.dependList.Insert[node, s] THEN ERROR;
};
RETURN};
sr.stamp ¬ mob.version;
sr.sourceStamp ¬ mob.sourceVersion;
EnumerateFiles[mob: mob, to: InsertInDependList];
};
IF mob # NIL THEN MobListerUtils.FreeMob[mob];
};
RETURN [sr];
END;
EnumerateFiles: PROC [mob: MobDefs.MobBase, to: PROC [name: ROPE, version: MobDefs.VersionStamp]] = TRUSTED
BEGIN
fti: MobDefs.FTIndex ¬ MobDefs.FTIndex.FIRST;
ssb: MobDefs.NameString = LOOPHOLE[mob + mob.ssOffset.units];
ftb: MobDefs.Base = LOOPHOLE[mob + mob.ftOffset.units];
UNTIL fti = mob.ftLimit DO
SELECT fti FROM
MobDefs.FTNull => NULL;
MobDefs.FTSelf => NULL;
ENDCASE => {
ftr: MobDefs.FTHandle = @ftb[fti];
name: ROPE = NameToRope[ftr.name, ssb];
to[name: name, version: ftr.version]};
fti ¬ fti + MobDefs.FTRecord.SIZE;
IF LOOPHOLE[fti, CARD] > LOOPHOLE[mob.ftLimit, CARD] THEN ERROR;
ENDLOOP;
END;
NameToRope: PROC [n: MobDefs.NameRecord, ssb: MobDefs.NameString] RETURNS [ROPE] = TRUSTED {
CharSeq: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF CHAR];
ss: LONG POINTER TO CharSeq = LOOPHOLE[ssb];
index: CARDINAL = n+4;
len: CARDINAL = ss[index]-0C;
ros: IO.STREAM = IO.ROS[];
FOR i: NAT IN [index+1..index+len] DO
IO.PutChar[ros, ss[i]];
ENDLOOP;
RETURN [IO.RopeFromROS[ros]];
};
MakeSupports: PROC [md: SourceData] = {
Extract information (Stamps and Create times) from the Mobs that currently exist. It does not change the contents of md.support, which is done in RederiveWork[].
NoteSupport: PROC [key, val: REF ANY] RETURNS [stop: BOOL ¬ FALSE] = --RefTab.EachPairAction-- {
mobSupport: Support = NARROW[val];
node: Node = mobSupport.node;
version: MobDefs.VersionStamp ~ mobSupport.version;
s: Support = NARROW[md.supports.Fetch[node].val];
IF s # NIL THEN s.version ¬ version;
RETURN};
stamp: MobDefs.VersionStamp;
name: ROPE;
md.sourceStamp ¬ MobDefs.NullVersion;
{
sr: CachedMobData ¬ CurMobData[md.mobNode];
IF sr.created = notExistTime THEN {
md.mobReadable ¬ FALSE;
md.cReadable ¬ FALSE;
RETURN;
};
md.sourceStamp ¬ sr.sourceStamp;
md.mobReadable ¬ TRUE;
IF sr.dependList.Pairs[NoteSupport] THEN ERROR;
};
md.cReadable ¬ TRUE;
[stamp: stamp, name: name] ¬ Mobery.StampAndNameFromFile[md.cName! FS.Error => {md.cReadable ¬ FALSE; Log["C file %g not readable (1)\n", [rope[md.cName]] ]; CONTINUE}];
IF NOT md.cReadable THEN RETURN;
IF NOT Rope.Equal[name, md.shortName]
THEN {
md.cReadable ¬ FALSE;
Log["name %g is different from expected %g\n", IO.rope[name], IO.rope[md.shortName]];
};
IF NOT md.cReadable THEN RETURN;
md.mobStamp ¬ stamp;
md.supportsInvalid ¬ FALSE;
RETURN};
EnumHiddenDeps: PROC [a: Action, Consume: PROC [Node]] = {
md: SourceData ~ NARROW[a.PublicPartsOfAction[].foundData];
CheckSupport: PROC [key, val: REF ANY] RETURNS [stop: BOOL ¬ FALSE] --RefTab.EachPairAction-- ~ {
mobSupport: Support = NARROW[val];
node: Node = mobSupport.node;
IF NOT md.supports.Fetch[node].found THEN Consume[node];
RETURN};
SELECT md.sourceType FROM
Mesa => NULL;
Config => RETURN;
ENDCASE => ERROR;
{
sr: CachedMobData ¬ CurMobData[md.mobNode];
IF sr.created = notExistTime THEN {
RETURN;
};
IF sr.dependList.Pairs[CheckSupport] THEN ERROR;
};
RETURN};
RederiveSource: PROC [a: Action] RETURNS [from: From, cmd: ROPE] --RederiveProc-- = {
md: SourceData ~ NARROW[a.PublicPartsOfAction[].foundData];
RETURN RederiveWork[md]};
The next two procs are global because the Cedar compilers do not let me assign non-local procedure values to variables with the same scope (blah!).
RederiveWork: PROC [md: SourceData] RETURNS [from: From, cmd: ROPE] ~ {
RederiveWork determines which of a collection of actions implied by md is currently favored by the state of the system. It returns the action and the list of all the nodes needed for this action to be startable.
NoteDep: PROC [fileName: ROPE] ~ {
Collect one more dependency into the from set; also reconstructs md.support.
n: Node = GetNode[fileName, fileClass];
s: Support ¬ NARROW[md.supports.Fetch[n].val];
IF s = NIL THEN {
s ¬ NEW [SupportRep ¬ [n, MobDefs.NullVersion]];
IF NOT md.supports.Insert[n, s] THEN ERROR;
This is adding the files to the set on which the output nodes depend on.
};
from.mustHave ¬ CONS[n, from.mustHave];
RETURN};
switches: Rope.ROPE;
exists: BOOL;
dbxDebug: BOOL = UserProfile.Boolean[key: "MakeDo.dbxDebug", default: FALSE];
from ¬ [mustHave: NIL, optional: LIST[md.switchesNode]];
md.supports.Erase[];
md.sourceNode ¬ md.mesaNode;
md.sourceType ¬ Mesa;
[exists: exists, resultType: md.resultType] ¬ EnumerateDependancies[md.mesaNode, Mesa, NoteDep];
IF exists THEN NULL
ELSE {
[exists: exists, resultType: md.resultType] ¬ EnumerateDependancies[md.cedarNode, Mesa, NoteDep];
IF exists THEN NULL
ELSE {
[exists: exists, resultType: md.resultType] ¬ EnumerateDependancies[md.configNode, Config, NoteDep];
IF exists THEN {
md.sourceNode ¬ md.configNode;
md.sourceType ¬ Config;
}
ELSE {
md.sourceType ¬ Unknown;
md.resultType ¬ Unknown;
}}};
md.supportsInvalid ¬ TRUE;
UpdateSupport[md];
from.mustHave ¬ CONS[md.sourceNode, from.mustHave];
SELECT md.sourceType FROM
Mesa => {
switches ¬ GetSwitches[md.mobName, mimosaDefaultSwitch];
Temporarily...
cmd ¬ Rope.Cat["Mimosa ", IF dbxDebug THEN "-a " ELSE NIL, switches, " ", md.shortName];
SELECT md.resultType FROM
Unknown, MobAndC => NULL;
MobOnly => cmd ¬ Rope.Cat[cmd, "; Delete ", md.shortName, cTail];
ENDCASE => ERROR;
};
Config => {
switches ¬ GetSwitches[md.mobName, cinderDefaultSwitch];
cmd ¬ Rope.Cat["Cind ", switches, " ", md.shortName];
};
Unknown => cmd ¬ NIL;
ENDCASE => ERROR ShouldNotHappen;
md.cmd ¬ cmd;
RETURN};
EnumerateDependancies: PROC [sourceNode: Node, sourceType: SourceType, consume: PROC [fileName: ROPE]] RETURNS [exists: BOOLEAN, resultType: ResultType ¬ Unknown] ~ {
If sourceNode exists, then callback to consume with all the fileNames that are required to be present by the semantics of sourceType and the contents of sourceNode. Caching is done.
pd: MDPs.ParseData ~ MDPs.GetParseData[sourceNode, sourceType];
IF pd=NIL THEN RETURN [FALSE, Unknown];
MDPs.EnumerateWithSuffix[pd.refdModules, ".mob", consume];
RETURN [TRUE, pd.resultType]};
Log: PROC [fmt: ROPE, v1, v2: IO.Value ¬ [null[]] ] ~ {
IF NOT dolog THEN RETURN;
SimpleFeedback.PutFL[myRouterName, oneLiner, $Log, fmt, LIST[v1, v2]];
RETURN};
OnProfileChange: UserProfile.ProfileChangedProc ~ {
dolog ¬ UserProfile.Boolean[key: "MimosaAndCinderDeps.Talk", default: FALSE];
};
AddFinder[["Mimosa and Cinder", SourceFind], front];
UserProfile.CallWhenProfileChanges[OnProfileChange];
END.