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.