MimosaAndCinderDeps.Mesa
Copyright Ó 1988, 1991 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 October 26, 1989 3:45:18 pm PDT
JKF January 11, 1989 10:22:44 am PST
DIRECTORY
Basics USING [Comparison],
BasicTime USING [GMT, Period, ToNSTime],
CommandTool USING [CurrentWorkingDirectory],
FS USING [ComponentPositions, Error, ExpandName, StreamOpen],
IO USING [BreakProc, Close, EndOf, GetTokenRope, IDProc, noWhereStream, PutChar, PutF, PutFR, PutRope, rope, RopeFromROS, ROS, SkipWhitespace, STREAM],
MakeDo USING [Action, ActionClass, ActionClassRep, AddFinder, fileClass, From, GetNode, GetProp, InnerGetCreated, Node, NodeList, notExistTime, PublicPartsOfAction, PublicPartsOfNode, SetProp, Time, Warning],
MakeDoParsing,
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],
PBasics USING [IsBound],
RedBlackTree USING [Compare, Create, DestroyTable, EnumerateIncreasing, Insert, Lookup, Table],
RefTab USING [Fetch],
Rope USING [Cat, Concat, Equal, EqualSubstrs, Length, ROPE, Substr],
UserProfile USING [CallWhenProfileChanges, ProfileChangedProc, Boolean],
SimpleStreams;
MimosaAndCinderDeps: CEDAR MONITOR
IMPORTS
BasicTime, CommandTool, FS, IO, MakeDo, MakeDoParsing, MakeDoPrivate, MakeDoPorting, Mobery, MobListerUtils, PBasics, RedBlackTree, RefTab, Rope, UserProfile
, SimpleStreams =
INVARIANT
StampRef in node props
BEGIN OPEN MakeDo;
realSysout: IO.STREAM ~ SimpleStreams.Create[].out;
sysout: IO.STREAM;
OnProfileChange: UserProfile.ProfileChangedProc ~ {
sysout ¬ IF UserProfile.Boolean[key: "MimosaAndCinderDeps.Talk", default: FALSE] THEN realSysout ELSE IO.noWhereStream;
};
GotoSyntaxError: ERROR = CODE;
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: RedBlackTree.Table
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: RedBlackTree.Table,
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 = {Unknown, Mesa, Config};
ResultType: TYPE = {Unknown, MobAndC, MobOnly};
ResultPiece: TYPE ~ {Mod, C};
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 ~ CommandTool.CurrentWorkingDirectory[];
installed, badInstall: BOOL ¬ FALSE;
Constants
cinderDefaultSwitch: ROPE ¬ " -l -m "; -- used to be /l - bj
mimosaDefaultSwitch: ROPE ¬ " -l -c ";
cTail: ROPE = ".c2c.c";
cTailLength: CARDINAL = cTail.Length[];
mobExt: ROPE = "mob";
mobTail: ROPE = Rope.Cat[".", 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
]];
GetSupportKey: PROC [data: REF ANY] RETURNS [Node] --RedBlackTree.GetKey-- = {
s: Support = NARROW[data];
RETURN[s.node]};
CompareSupport: PROC [k, data: REF ANY] RETURNS [Basics.Comparison] --RedBlackTree.Compare-- = {
k1: INT = LOOPHOLE[k];
k2: INT = LOOPHOLE[GetSupportKey[data]];
RETURN [SELECT k1 FROM
<k2 => less,
=k2 => equal,
>k2 => greater,
ENDCASE => ERROR ShouldNotHappen];
};
ClearCaches: PROC [ac: ActionClass] ~ {
Mobery.FlushCache[];
MakeDoParsing.ClearCache[];
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 ¬ baseName.Cat[mobTail], fileClass];
cNode ¬ GetNode[cName ¬ baseName.Concat[cTail], fileClass];
foundData ¬ md ¬ NEW [SourceDataRep ¬ [
mobName: mobName,
cName: cName,
shortName: shortName,
supports: RedBlackTree.Create[GetSupportKey, CompareSupport],
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[mobName.Cat[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 ¬ PBasics.IsBound[LOOPHOLE[Mobery.StampAndNameFromFile]];
moblisteries ¬ PBasics.IsBound[LOOPHOLE[MobListerUtils.PrintVersion]] AND PBasics.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 [data: REF ANY] RETURNS [stop: BOOL ¬ FALSE] --RedBlackTree.EachNode-- ~ {
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[data];
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.PutF[
" 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.PutF[
" 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, "A lie to avoid retrying over and over again"]
ELSE RETURN [FALSE, "C2C file cannot be generated from a DEFINITIONS Mesa File"];
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.PutFR["switches file created later than result %g", [rope[resultName]]]];
};
consistent ¬ TRUE;
reason ¬ "all version stamps match";
md.supports.EnumerateIncreasing[CheckSupport];
IF NOT supportFound THEN RETURN [TRUE, "no inputs exist"];
IF NOT resultExists THEN RETURN [FALSE, IO.PutFR["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;
IF sr = NIL THEN node.SetProp[
prop: $MobData,
val: sr ¬ NEW [CachedMobDataRep ¬ [
created: notExistTime,
stamp: MobDefs.NullVersion,
sourceStamp: MobDefs.NullVersion,
dependList: RedBlackTree.Create[GetSupportKey, CompareSupport]]]
];
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 ¬ RedBlackTree.Create[GetSupportKey, CompareSupport];
}
ELSE TRUSTED {
fileName: ROPE ~ node.PublicPartsOfNode[].name;
mob ¬ MobListerUtils.ReadMob[fileName ! MobListerUtils.MobErr => {mob ¬ NIL; CONTINUE}];
IF mob = NIL OR mob.versionIdent # MobDefs.VersionID
THEN {
sr.stamp ¬ MobDefs.NullVersion;
sr.sourceStamp ¬ MobDefs.NullVersion;
sr.dependList ¬ RedBlackTree.Create[GetSupportKey, CompareSupport];
}
ELSE {
InsertInDependList: PROC [name: ROPE, version: MobDefs.VersionStamp] = TRUSTED {
extName: ROPE = FS.ExpandName[name.Cat[mobTail]].fullFName;
node: Node = GetNode[extName, fileClass];
s: Support ¬ NARROW[sr.dependList.Lookup[node]];
IF s # NIL
THEN s.version ¬ version
ELSE {
s ¬ NEW [SupportRep ¬ [node, version]];
sr.dependList.Insert[s, node];
};
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 [data: REF ANY] RETURNS [stop: BOOL ¬ FALSE] = --RedBlackTree.EachNode-- {
mobSupport: Support = NARROW[data];
node: Node = mobSupport.node;
version: MobDefs.VersionStamp ~ mobSupport.version;
s: Support = NARROW[md.supports.Lookup[node]];
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;
sr.dependList.EnumerateIncreasing[NoteSupport];
};
md.cReadable ¬ TRUE;
[stamp: stamp, name: name] ¬ Mobery.StampAndNameFromFile[md.cName! FS.Error => {md.cReadable ¬ FALSE; sysout.PutF["C file %g not readable (1)\n", IO.rope[md.cName]]; CONTINUE}];
IF NOT md.cReadable THEN RETURN;
IF NOT Rope.Equal[name, md.shortName]
THEN {
md.cReadable ¬ FALSE;
sysout.PutF["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 [data: REF ANY] RETURNS [stop: BOOL ¬ FALSE] --RedBlackTree.EachNode-- ~ {
mobSupport: Support = NARROW[data];
node: Node = mobSupport.node;
s: Support = NARROW[md.supports.Lookup[node]];
IF s = NIL 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;
};
sr.dependList.EnumerateIncreasing[CheckSupport];
};
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!).
NoteMesa: PROC [pe: MakeDoParsing.ParseEntry, consume: PROC[ROPE]] ~ {
WITH pe.parseData.Fetch[$Directory].val SELECT FROM
list: LIST OF ROPE => {
FOR list ¬ list, list.rest WHILE list # NIL DO
name: ROPE ~ list.first;
consume[name.Cat[".mob"]];
ENDLOOP;
};
ENDCASE => NULL;
};
NoteConfig: PROC [pe: MakeDoParsing.ParseEntry, consume: PROC[ROPE]] ~ {
WITH pe.parseData.Fetch[$Requests].val SELECT FROM
list: LIST OF ROPE => {
FOR list ¬ list, list.rest WHILE list # NIL DO
name: ROPE ~ list.first;
consume[name.Cat[".mob"]];
ENDLOOP;
};
ENDCASE => NULL;
WITH pe.parseData.Fetch[$StaticRequests].val SELECT FROM
list: LIST OF ROPE => {
FOR list ← list, list.rest WHILE list # NIL DO
name: ROPE ~ list.first;
consume[name];
ENDLOOP;
};
ENDCASE => NULL;
};
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.Lookup[n]];
IF s = NIL THEN {
s ¬ NEW [SupportRep ¬ [n, MobDefs.NullVersion]];
md.supports.Insert[s, n];
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;
IterateList: TYPE ~ LIST OF RECORD [node: Node, class: ATOM, proc: PROC[MakeDoParsing.ParseEntry, PROC[ROPE]]];
dbxDebug: BOOL = UserProfile.Boolean[key: "MakeDo.dbxDebug", default: FALSE];
from ¬ [mustHave: NIL, optional: LIST[md.switchesNode]];
md.supports.DestroyTable[];
md.sourceNode ¬ md.mesaNode;
md.sourceType ¬ Unknown;
md.resultType ¬ Unknown;
FOR list: IterateList ¬ LIST[ [md.mesaNode, $Mesa, NoteMesa], [md.cedarNode, $Mesa, NoteMesa], [md.configNode, $Config, NoteConfig]],
list.rest WHILE list # NIL DO
node: Node ~ list.first.node;
class: ATOM ~ list.first.class;
proc: PROC[MakeDoParsing.ParseEntry, PROC[ROPE]] ~ list.first.proc;
pe: MakeDoParsing.ParseEntry ¬ MakeDoParsing.GetParseEntry[node: node, class: class];
IF pe # NIL THEN {
type: ATOM ~ NARROW[pe.parseData.Fetch[$SourceType].val];
md.sourceNode ¬ node;
md.sourceType ¬ SELECT type FROM
$CedarProg, $CedarMonitor, $CedarDefs => Mesa,
$Config => Config,
ENDCASE => Unknown;
md.resultType ¬ SELECT type FROM
$CedarProg, $CedarMonitor => MobAndC,
$CedarDefs => MobOnly,
$Config => MobAndC,
ENDCASE => Unknown;
proc[pe, NoteDep];
EXIT;
};
ENDLOOP;
md.supportsInvalid ¬ TRUE;
UpdateSupport[md];
from.mustHave ¬ CONS[md.sourceNode, from.mustHave];
SELECT md.sourceType FROM
Mesa => {
switches ¬ GetSwitches[md.mobName, mimosaDefaultSwitch];
cmd ¬ NIL;
Temporarily...
IF dbxDebug THEN {
cmd ¬ Rope.Cat["Mimosa -a ", switches, " ", md.shortName];
}
ELSE {
cmd ¬ Rope.Cat[cmd, "Mimosa ", switches, " ", md.shortName];
};
SELECT md.resultType FROM
Unknown, MobAndC => {
cmd ← Rope.Cat[cmd, "; rename ", md.shortName, cTail, " ← "];
cmd ← Rope.Cat[cmd, md.shortName, ".C"];
NULL;
};
MobOnly => {
cmd ¬ Rope.Cat[cmd, "; Delete ", md.shortName, cTail];
cmd ¬ Rope.Cat[cmd, "; Delete ", md.shortName, ".O"];
};
ENDCASE => ERROR;
};
Config => {
switches ¬ GetSwitches[md.mobName, cinderDefaultSwitch];
cmd ¬ NIL;
cmd ¬ Rope.Cat[cmd, " Cind ", switches, " ", md.shortName];
cmd ← Rope.Cat[cmd, "; rename ", md.shortName, cTail, " ← "];
cmd ← Rope.Cat[cmd, md.shortName, ".C"];
Hack, hack --
};
Unknown => cmd ¬ NIL;
ENDCASE => ERROR ShouldNotHappen;
md.cmd ¬ cmd;
RETURN};
AddFinder[["Mimosa and Cinder", SourceFind], front];
UserProfile.CallWhenProfileChanges[OnProfileChange];
END.