<<>> <> <> <> <> <> <> <> <> <<>> 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; <> < {>> <> <> <> <> <<};>> < 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.