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 = 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, stamp: MobDefs.VersionStamp, sourceStamp: MobDefs.VersionStamp, dependList: RedBlackTree.Table ]; 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, 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]; installDir: ROPE ~ CommandTool.CurrentWorkingDirectory[]; installed, badInstall: BOOL ฌ FALSE; 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 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 -- ~ { 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; 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 { 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]; 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]]; 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-- ~ { 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-- ~ { 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] => { 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 => { 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"]; }; IF seekC AND resultExists THEN { IF md.mobStamp # MobDefs.NullVersion THEN { 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 { 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] = { 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] = BEGIN time: Time ฌ InnerGetCreated[node]; RETURN [MobStampFromTime[time]]; END; MobStampFromTime: PROC [time: Time] RETURNS [mobStamp: MobDefs.VersionStamp] = 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] = 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] = { 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]}; 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; }; RederiveWork: PROC [md: SourceData] RETURNS [from: From, cmd: ROPE] ~ { NoteDep: PROC [fileName: ROPE] ~ { 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]; }; 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; 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 => { 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]; }; Unknown => cmd ฌ NIL; ENDCASE => ERROR ShouldNotHappen; md.cmd ฌ cmd; RETURN}; AddFinder[["Mimosa and Cinder", SourceFind], front]; UserProfile.CallWhenProfileChanges[OnProfileChange]; END. ผ 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 INVARIANT StampRef in node props date when the information was obtained stamp of the mob stamp of the source file it depends on files (name+version) that this mob object depends on (same type as Support) sourceStamp is the desired stamp encoded in the Mob file mobStamp is the desired stamp encoded in the C file (currently unused) A description of the properties of a Mob file that will support our action. Constants 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. We only know what to do with .Mob and .C2C.C files. Compensate for the cTail; 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. LOOPHOLE only needed for PrincOps 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. 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. Use the version stamp Only data available is the creation time Since createtime is non-null. Check the VersionStamp Chek the Creation Date 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. Fake a version stamp for a source file out of its creation date. A MobStamp from a time Find the version stamp of this Mob file. 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[]. 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!). 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 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. Collect one more dependency into the from set; also reconstructs md.support. This is adding the files to the set on which the output nodes depend on. Temporarily... cmd _ Rope.Cat[cmd, "; rename ", md.shortName, cTail, " _ "]; cmd _ Rope.Cat[cmd, md.shortName, ".C"]; cmd _ Rope.Cat[cmd, "; rename ", md.shortName, cTail, " _ "]; cmd _ Rope.Cat[cmd, md.shortName, ".C"]; Hack, hack -- สฎ–(cedarcode) style•NewlineDelimiter ™code™Kšœ ฯeœ7™BKšœ9™9K™K™?Kšœ1™1KšœA™AKšฯkœ!™$K™—šž ˜ Kšœžœ˜Kšœ žœžœ˜(Kšœ žœ˜,Kšžœžœ5˜=Kšžœžœržœžœ˜—Kšœžœฤ˜ะK˜Kšœžœ ˜ Kšœžœ ˜Kšœžœ|˜‰Kšœžœ$˜0Kšœžœ*˜>Kšœžœ ˜Kšœ žœM˜_Kšœžœ ˜Kšœžœ,žœ ˜DKšœ žœ7˜HKšœ˜—K˜šัbnxœžœž˜"šž˜Kšœžœžœ˜Kšœ˜—šž ™ Kšœ™——K˜Kšžœžœ˜K˜Kšœ žœžœ˜3K•StartOfExpansion&[key: ROPE, default: BOOL _ FALSE]šœžœžœ˜K˜šฯnœ$˜3Kš œ žœ?žœžœ žœžœ˜wK˜—K˜Kšัblnœžœžœ˜Kšกœะksฯsœฃขœ˜K˜Kšžœžœžœ˜K˜š œžœžœ%žœžœ˜Mšœžœ˜K™&—˜K™—˜"K™&—šœ˜K™KK˜—K˜—š œ žœžœžœžœ˜DKšœžœ˜ K˜!K˜"Kšœ˜K˜PšœB˜BK™8Kšœ4™F—Kšœ&žœ˜*Kšœžœžœ˜%Kšœžœžœ˜Kšœžœž˜K˜—K˜Kšœ žœ˜+Kšœ žœ˜/Kšœ žœ ˜K˜š œ žœžœžœžœ˜;K˜ šœ˜KšœK™K——K˜Kšœ žœ)˜9Kšœžœžœ˜$K˜head™ Kšฯbœžœฯc˜˜>Kšœ;˜;šœžœ˜'Kšœ˜K˜ Kšœ˜Kšœ=˜=Kšœ8˜8Kšœ:˜:Kšœ<˜K˜%Kšžœ0žœ˜>Kšžœžœ˜"K˜—Kšœ˜—šžœ˜K™Kšžœ8žœžœžœ$˜pK˜——Kšœ˜—šžœ&žœ˜.Kšœžœ˜Kš žœ8žœžœžœžœJ˜šKšœ˜—Kšœ žœ˜Kšœ$˜$Kšœ.˜.Kš žœžœžœžœžœ˜:Kš žœžœžœžœžœžœD˜nKšžœ˜—K˜š  œžœ˜(KšœF œœžœ™˜Kšœ ˜ Kšœ˜Kšœ/˜/K˜+Kšžœ(žœžœ˜6Kš žœžœžœžœžœžœ˜^Kšœ˜K˜—K˜š œžœžœ#˜LK™@Kšž˜Kšœ#˜#Kšžœ˜ —Kšžœ˜K˜š œžœžœ#˜NK™Kšž˜Kšœ˜Kšžœžœžœ ˜5Kšœ'˜'—Kšžœ˜K˜š  œžœžœ"˜HK˜%Kšžœ ˜K˜K˜—šค œžœžœžœ˜AK™(Kšž˜Kšžœžœ˜Kšœžœ˜3Kšœžœ˜/Kšœ˜šžœžœžœ˜Kšœ˜šœ žœ˜#Kšœ˜Kšœ˜Kšœ!˜!Kšœ@˜@—K˜—Kšžœžœžœ˜)K˜šžœ˜ šžœ˜Kšœ˜Kšœ%˜%KšœBž˜CK˜—šžœžœ˜Kšœ žœ!˜/KšœHžœžœ˜Xšžœžœžœ%˜4šžœ˜Kšœ˜Kšœ%˜%KšœBž˜CK˜—šžœ˜šคœžœžœ#žœ˜PKšœ žœžœ)˜;K˜)Kšœ žœ˜0šžœž˜ Kšžœ˜šžœ˜Kšœžœ ˜'Kšœ˜K˜——Kšžœ˜—Kšœ˜Kšœ#˜#Kšœ1˜1K˜——Kšžœžœžœ˜.K˜——Kšžœ˜ Kšžœ˜—K˜š  œžœžœžœ$ž˜kKšž˜Kšœ'žœ˜-Kšœžœ˜=Kšœžœ˜7šžœž˜šžœž˜Kšœžœ˜Kšœžœ˜šžœ˜ Kšœ"˜"Kšœžœ˜'K˜&——Kšœžœ˜"Kšžœžœžœžœžœžœžœ˜@Kšžœ˜—Kšžœ˜K˜—š   œžœ2žœžœžœ˜\Kšœ žœžœžœžœžœžœžœžœ˜BKš œžœžœžœ žœ˜,Kšœžœ˜Kšœžœ˜Kš œžœžœžœžœ˜šžœžœžœž˜%Kšžœ˜Kšžœ˜—Kšžœžœ˜K˜K˜—š  œžœ˜'Kšœv œ™ขš  œžœžœžœžœžœžœฅœ˜\Kšœžœ˜#K˜Kšœ3˜3Kšœ žœ˜.Kšžœžœžœ˜$Kšžœ˜—K˜Kšœžœ˜ K˜Kšœ%˜%˜K˜+šžœžœ˜#Kšœžœ˜Kšœžœ˜Kšžœ˜K˜—K˜ Kšœžœ˜K˜/K˜—Kšœžœ˜Kš œCžœžœ.žœž œ˜ฑKšžœžœžœžœ˜ šžœžœ˜%šžœ˜Kšœžœ˜Kšœ7žœ žœ˜]K˜——Kšžœžœžœžœ˜ K˜Kšœžœ˜Kšžœ˜—K˜š œžœ  œžœ ˜:Kšœžœ$˜;š  œžœžœžœžœžœžœฅœ˜]Kšœžœ˜#K˜Kšœ žœ˜.Kšžœžœžœ˜Kšžœ˜—šžœž˜Kšœžœ˜ Kšœ žœ˜Kšžœžœ˜—˜K˜+šžœžœ˜#Kšžœ˜K˜—Kšœ0˜0K˜—Kšžœ˜K˜—š  œžœ žœžœฅœ˜UKšœžœ$˜;Kšžœ˜—K˜K™“K™š œžœ)žœžœ˜Fšžœ$žœž˜3šœžœžœžœ˜šžœžœžœž˜.Kšœžœ˜Kšœ˜Kšžœ˜—Kšœ˜—Kšžœžœ˜—K˜K˜—š  œžœ)žœžœ˜Hšžœ#žœž˜2šœžœžœžœ˜šžœžœžœž˜.Kšœžœ˜Kšœ˜Kšžœ˜—Kšœ˜—Kšžœžœ˜—šžœ)žœž™8šœžœžœžœ™šžœžœžœž™.Kšœžœ™Kšœ™Kšžœ™—Kšœ™—Kšžœžœ™—K˜K˜—š  œžœžœžœ˜GKšœDœƒ œ™ิš œžœ žœ˜"Kšœ%œ ™MKšœ'˜'Kšœ žœ˜+šžœžœžœ˜Kšœžœ)˜0˜K™H—K˜—Kšœžœ˜'Kšžœ˜—Kšœžœ˜Kšœ žœžœžœžœžœžœžœžœ˜oKšœ žœ8žœ˜MKšœžœ žœ˜8K˜K˜Kšœ˜Kšœ˜Kšœ˜š žœžœtžœžœž˜ฃKšœ˜Kšœžœ˜Kšœžœžœžœ˜CKšœU˜Ušžœžœžœž˜Kšœžœžœ&˜9K˜šœžœž˜ Kšœ.˜.Kšœ˜Kšžœ ˜—šœžœž˜ Kšœ%˜%Kšœ˜K˜Kšžœ ˜—Kšœ˜Kšžœ˜K˜—Kšžœ˜—K˜Kšœžœ˜Kšœ˜Kšœžœ˜3šžœž˜šœ ˜ Kšœ#คœ˜8Kšœžœ˜ Kšค™šžœ žœ˜Kšœ:˜:K˜—šžœ˜šœ<˜