DIRECTORY Basics, BasicTime, CedarProcess, Commander, CommandTool, FileNames, FileViewerOps, FS, IO, List, MakeDo, MakeDoPrivate, RedBlackTree, ProcessProps, Rope, TimeStamp; MakeDoDownCmds: CEDAR MONITOR IMPORTS CommandTool, IO, MakeDo, MakeDoPrivate, Rope EXPORTS MakeDo, MakeDoPrivate = BEGIN OPEN MakeDo, MakeDoPrivate; NodeRep: PUBLIC TYPE = MakeDoPrivate.NodeRep; CommandRep: PUBLIC TYPE = MakeDoPrivate.CommandRep; Enter: ENTRY PROC [c: Command] = { ENABLE UNWIND => {}; WHILE c.down.locked DO WAIT c.down.change ENDLOOP; c.down.locked _ TRUE; }; MayEnterDownCmd: PUBLIC ENTRY PROC [c: Command] RETURNS [in: BOOL] = { ENABLE UNWIND => {}; in _ NOT c.down.locked; IF in THEN c.down.locked _ TRUE; }; ExitDownCmd: PUBLIC ENTRY PROC [c: Command] = { ENABLE UNWIND => {}; c.down.locked _ FALSE; BROADCAST c.down.change; }; DoIn: PROC [c: Command, p: --INTERNAL-- PROC [Command]] = { Enter[c]; {ENABLE UNWIND => ExitDownCmd[c]; p[c]; }; ExitDownCmd[c]; }; PublicPartsOfCommand: PUBLIC PROC [c: Command] RETURNS [cmd: ROPE, foundData: REF ANY, failed: BOOL, reasonWhyLastDone: ROPE] = { RETURN [ cmd: c.cmd, foundData: c.foundData, failed: c.failed, reasonWhyLastDone: c.reasonWhyLastDone ]; }; EnumerateSources: PUBLIC --ENTRY-- PROC [c: Command, which: CmdDep, to: PROC [n: Node, which: CmdDep, optional: BOOL]] = { Inner: --INTERNAL-- PROC [c: Command] = { InnerEnumerateSources[c, which, to]; }; DoIn[c, Inner]; }; InnerEnumerateSources: PUBLIC --INTERNAL-- PROC [c: Command, which: CmdDep, to: PROC [n: Node, which: CmdDep, optional: BOOL]] = { which _ which; FOR e: Edge _ c.from[which].first, e.cNext WHILE e # NIL DO IF e.c # c THEN ERROR; to[e.n, which, e.optional]; ENDLOOP; which _ which; }; AddConsumption: PUBLIC --ENTRY-- PROC [c: Command, nl: NodeList, which: CmdDep, optional: BOOL] = { Inner: --INTERNAL-- PROC [c: Command] = { InnerAddConsumption[c, nl, which, optional]; }; DoIn[c, Inner]; }; InnerAddConsumption: --INTERNAL-- PROC [c: Command, nl: NodeList, which: CmdDep, optional: BOOL] = { suspect: BOOL _ which = data; FOR nl _ nl, nl.rest WHILE nl # NIL DO n: Node _ nl.first; SELECT which FROM data => { [c.from[data], n.to[data]] _ Link[c, c.from[data], n, n.to[data], optional, suspect]; IF (NOT optional) AND NOT Exists[n] THEN { c.missedSources _ CONS[n, c.missedSources]; }; }; cmd => { [c.from[cmd], n.to[cmd]] _ Link[c, c.from[cmd], n, n.to[cmd], optional, suspect]; }; ENDCASE => ERROR; ENDLOOP; nl _ nl; }; Link: PUBLIC PROC [c: Command, ch: EdgeRingHead, n: Node, nh: EdgeRingHead, optional, suspect: BOOL] RETURNS [chNew, nhNew: EdgeRingHead] = { e: Edge _ NEW [EdgeRep _ [ c: c, n: n, cNext: ch.first, cPrev: NIL, nNext: nh.first, nPrev: NIL, optional: optional, traverseCreated: SELECT suspect FROM TRUE => unknownTime, FALSE => GetCreated[n], ENDCASE => ERROR ]]; ch.first _ nh.first _ e; IF e.cNext # NIL THEN e.cNext.cPrev _ e ELSE ch.last _ e; IF e.nNext # NIL THEN e.nNext.nPrev _ e ELSE nh.last _ e; chNew _ ch; nhNew _ nh; }; RemoveConsumption: PUBLIC --ENTRY-- PROC [c: Command, which: CmdDep] = { Inner: --INTERNAL-- PROC [c: Command] = {InnerRemoveConsumption[c, which]}; DoIn[c, Inner]; }; InnerRemoveConsumption: --INTERNAL-- PROC [c: Command, which: CmdDep] = { ch: EdgeRingHead _ c.from[which]; cNext: Edge; FOR e: Edge _ ch.first, cNext WHILE e # NIL DO n: Node _ e.n; IF e.c # c THEN ERROR; cNext _ e.cNext; e.cNext _ e.cPrev _ NIL; UnlinkToFrom[e, which]; ENDLOOP; c.from[which] _ emptyHead; }; Recurse: --INTERNAL-- PROC [parent: CWork, which: CmdDep, Cont: Continuation] RETURNS [Subgoal] = { OPEN parent; sg: Subgoal _ NEW [SubgoalRep _ [ job: job, toDo: NewWorkTable[], parent: parent, PerFinish: ReturnFromSub, AllDone: Cont ]]; change _ FALSE; FOR e: Edge _ c.from[which].first, e.cNext WHILE e # NIL DO sn: Node _ e.n; sub: NWork _ NEW [WorkRec.node _ [ job: job, depth: depth+1, e: e, subject: node[sn] ]]; InsertWork[sg.toDo, sub]; ENDLOOP; RETURN [sg]; }; ReturnFromSub: PROC [parent, sub: WorkRef] = { created: Time; e: Edge = sub.e; sn: Node = e.n; created _ GetCreated[sn]; IF e.traverseCreated # created THEN { IF parent.job.do THEN e.traverseCreated _ created; parent.change _ TRUE; }; }; PostAmble: PROC [cw: CWork, msg: ROPE] = { IF debugging THEN {OPEN cw; Log[depth, "EWc <- %g %g", IO.rope[c.cmd], IO.rope[msg]]; }; }; CmdWork: PUBLIC --INTERNAL-- PROC [cWork: CWork] RETURNS [Subgoal] = { OPEN cWork; ENABLE UNWIND => c.aborted _ TRUE; previousNNeed: BOOL = NodeNeededInJob[job, possibleNewNeed]; c.aborted _ FALSE; IF debugging THEN Log[depth, "EWc -> %g", IO.rope[c.cmd]]; possibleNewNeed.lastVisit _ job.visit; possibleNewNeed.needed _ TRUE; IF NOT previousNNeed THEN c.suspectNeed _ TRUE; c.dataRecurse _ ShouldRemakeCmd[c, data, job.do]; IF NOT (c.dataRecurse OR c.suspectNeed) THEN { PostAmble[cWork, "not suspected"]; RETURN [NIL]}; dChange _ FALSE; RETURN[FirstEnsureCmdCorrect[cWork]]; }; FirstEnsureCmdCorrect: --INTERNAL-- PROC [parent: WorkRef] RETURNS [Subgoal] = { cWork: CWork = NARROW[parent]; {OPEN cWork; RETURN[ IF ShouldRemakeCmd[c, cmd, job.do] THEN Recurse[cWork, cmd, FinishCmdRecursion] ELSE IF c.dataRecurse THEN Recurse[cWork, data, FinishCmdExecution] ELSE FinishCmdExecution[parent] ]; }}; RestEnsureCmdCorrect: --INTERNAL-- PROC [parent: WorkRef] RETURNS [Subgoal] = { cWork: CWork = NARROW[parent]; {OPEN cWork; RETURN[ IF job.do AND ShouldRemakeCmd[c, cmd, job.do] THEN Recurse[cWork, cmd, FinishCmdRecursion] ELSE IF c.dataRecurse THEN Recurse[cWork, data, FinishCmdExecution] ELSE FinishCmdExecution[parent] ]; }}; FinishCmdRecursion: --INTERNAL-- PROC [parent: WorkRef] RETURNS [Subgoal] = { cWork: CWork = NARROW[parent]; {OPEN cWork; cChange _ parent.change; [] _ ShouldRemakeCmd[c, cmd, job.do]; IF cChange AND job.do THEN { oldCmd: ROPE _ c.cmd; from: From; InnerUnaskOutdated[c]; InnerRemoveConsumption[c, data]; c.missedSources _ NIL; [from, c.cmd] _ c.class.Rederive[c]; IF NOT oldCmd.Equal[c.cmd] THEN dChange _ TRUE; InnerAddConsumption[c, from.mustHave, data, FALSE]; InnerAddConsumption[c, from.optional, data, TRUE]; }; RETURN[RestEnsureCmdCorrect[parent]]; }}; FinishCmdExecution: --INTERNAL-- PROC [parent: WorkRef] RETURNS [Subgoal] = { cWork: CWork = NARROW[parent]; {OPEN cWork; ch: Commander.Handle _ NIL; IF change THEN dChange _ TRUE; [] _ ShouldRemakeCmd[c, data, job.do]; {ClearRemake: PROC [made: Node] = {[] _ ShouldRemakeNode[made, job.do]}; IF job.do THEN EnumerateResults[c, ClearRemake]; }; IF dChange OR c.suspectNeed OR job.assumeAllInconsistent THEN { resultStack: Table = NewRefTable[]; FreeResult: --INTERNAL-- PROC [made: Node] = { ReallySuspectNodeChange[made, unforceNotExist, resultStack]; }; KillResult: --INTERNAL-- PROC [made: Node] = { ReallySuspectNodeChange[made, forceNotExist, resultStack]; }; needsToBeDone, outdated, makesACertainlyModifiable: BOOL; bitch: BOOL _ FALSE; missedResults: NodeList; whyOutdated: ROPE; makesACertainlyModifiable _ MakesACertainlyModifiable[job, c]; IF dChange OR job.assumeAllInconsistent THEN { c.missedSources _ NIL; FOR e: Edge _ c.from[data].first, e.cNext WHILE e # NIL DO sn: Node _ e.n; created: Time _ e.traverseCreated; IF NOT (e.optional OR created#notExistTime) THEN { c.missedSources _ CONS[sn, c.missedSources]; IF JustOutsideCertainlyModifiable[job, makesACertainlyModifiable, sn] THEN bitch _ TRUE; }; ENDLOOP; InnerUnaskOutdated[c]; }; c.canBeDone _ c.missedSources = NIL; c.suspectNeed _ FALSE; [missedResults, outdated, whyOutdated] _ InnerNeedsToBeDone[job, c]; needsToBeDone _ (missedResults#NIL) OR outdated OR job.assumeAllInconsistent; IF needsToBeDone THEN { IF c.canBeDone THEN { IF job.record THEN { firstCVisit: BOOL = job.visit # c.lastVisit; c.lastVisit _ job.visit; IF firstCVisit THEN AddCommand[job, c.cmd]; }; IF job.do THEN { c.reasonWhyLastDone _ SELECT TRUE FROM missedResults#NIL => Rope.Cat["results ", EnglishList[missedResults].el, " missed"], outdated => whyOutdated, job.assumeAllInconsistent => "I was told to assume everything inconsistent", ENDCASE => ERROR; IF ch = NIL THEN ch _ GetCommanderHandle[]; IF debugging THEN Confirm[depth, c.cmd]; IncrementStepCount[job]; c.failed _ CommandTool.DoCommand[c.cmd, ch] = $Failure; c.succeeded _ NOT c.failed; IF c.failed THEN AddFailedCmd[job, c] ELSE EnumerateResults[c, FreeResult]; InnerUnaskOutdated[c]; } ELSE c.succeeded _ c.failed _ FALSE; } ELSE { c.succeeded _ FALSE; c.failed _ makesACertainlyModifiable; }; } ELSE { c.succeeded _ FALSE; c.failed _ makesACertainlyModifiable AND NOT c.canBeDone; }; IF c.failed THEN EnumerateResults[c, KillResult]; IF bitch AND dChange THEN { SIGNAL Warning[IO.PutFR[ "Couldn't %g%g because %g missing or unmakeable.\n", IO.rope[IF needsToBeDone THEN "" ELSE "check consistency of "], IO.rope[c.cmd], IO.rope[EnglishList[c.missedSources].el]]]; }; }; PostAmble[cWork, "end"]; RETURN [NIL]; }}; NeedsToBeDone: PUBLIC --ENTRY-- PROC [job: Job, c: Command, alwaysAsk: BOOL] RETURNS [missedResults: NodeList, outdated: BOOL] = { Inner: --INTERNAL-- PROC [c: Command] = { IF alwaysAsk THEN InnerUnaskOutdated[c]; [missedResults, outdated] _ InnerNeedsToBeDone[job, c]; }; DoIn[c, Inner]; }; InnerNeedsToBeDone: --INTERNAL-- PROC [job: Job, c: Command] RETURNS [missedResults: NodeList, outdated: BOOL, whyOutdated: ROPE] = { PerResult: --INTERNAL-- PROC [made: Node] = { IF NodeNeededInJob[job, made] AND NOT Exists[made] THEN missedResults _ CONS[made, missedResults]; }; missedResults _ NIL; EnumerateResults[c, PerResult]; IF NOT c.outdatedAsked THEN { NeededForMe: PROC [n: Node] RETURNS [BOOL] = { RETURN [NodeNeededInJob[job, n]]}; c.outdatedAsked _ TRUE; c.whyOutdated _ c.class.NotCurrent[c, NeededForMe]; c.outdated _ c.whyOutdated # NIL; }; whyOutdated _ c.whyOutdated; outdated _ c.outdated; }; InnerUnaskOutdated: --INTERNAL-- PROC [c: Command] = { c.outdatedAsked _ FALSE; c.whyOutdated _ "Nobody should ever see this"; }; NodeNeededInJob: --INTERNAL-- PROC [job: Job, n: Node] RETURNS [BOOL] = { ENABLE UNWIND => {}; RETURN [n.lastVisit = job.visit AND n.needed]; }; FoundCertainlyModifiableResult: ERROR = CODE; MakesACertainlyModifiable: --INTERNAL-- PROC [job: Job, c: Command] RETURNS [ans: BOOL] = { TestResult: PROC [n: Node] = { IF CertainlyModifiable[job, n] THEN ERROR FoundCertainlyModifiableResult; }; ans _ FALSE; EnumerateResults[c, TestResult ! FoundCertainlyModifiableResult => {ans _ TRUE; CONTINUE} ]; ans _ ans; }; CertainlyModifiable: PROC [job: Job, n: Node] RETURNS [certainly: BOOL] = { certainly _ IsRootGoal[job, n] OR (job.boundaryKnown AND NodeInTable[n, job.modifiable]); }; JustOutsideCertainlyModifiable: PROC [job: Job, makesACertainlyModifiable: BOOL, n: Node] RETURNS [BOOL] = { IF NOT makesACertainlyModifiable THEN RETURN [FALSE]; IF CertainlyModifiable[job, n] THEN RETURN [FALSE]; RETURN [TRUE]; }; END. .MakeDoDownCmds.Mesa Last Edited by: Spreitzer, September 4, 1985 11:48:58 pm PDT Carl Hauser, April 11, 1985 3:43:34 pm PST LOCKS c.down USING c: Command IF debugging THEN Log[0, "?Outdated[%g]", IO.rope[c.cmd]]; IF debugging THEN Log[0, "Outdated[%g]=%g", IO.rope[c.cmd], IO.bool[c.outdated]]; ส–– "cedar" style˜code™J™˜>šœ œœ˜.Kšœœ˜šœ'œœ˜:K˜Kšœ"˜"šœœ œœ˜2Kšœœ˜,KšœDœ œ˜XK˜—Kšœ˜—Kšœ˜K˜—Kšœ œ˜$Kšœœ˜KšœD˜DKšœœœ œ˜Mšœœ˜šœ œ˜šœ œ˜Kšœ œ˜,K˜Kšœ œ˜+K˜—šœœ˜šœœœ˜&KšœœC˜TKšœ˜KšœL˜LKšœœ˜—Kšœœœ˜+Kšœ œ˜(K˜Kšœ7˜7Kšœœ ˜Kšœ œ˜%Kšœ!˜%Kšœ˜K˜—Kšœœ˜$K˜—šœ˜Kšœœ˜Kšœ%˜%Kšœ˜—K˜—šœ˜Kšœœ˜Kšœ%œœ ˜9Kšœ˜—Kšœ œ!˜1šœœ œ˜šœ œ˜Kšœ4˜4Kšœœœœ˜?Kšœ ˜Kšœ)˜+—K˜—K˜—K˜Kšœœ˜ K˜—K˜š Ÿ œ  œœ#œœ%œ˜‚šŸœ  œœ˜)Kšœ œ˜(Kšœ7˜7Kšœ˜—K˜K˜—K˜š Ÿœ  œœœ%œœ˜…šŸ œ  œœ˜-Kš œœœœœ˜bK˜—Kšœœ˜Kšœ˜šœœœ˜šŸ œœ œœ˜.Kšœ˜"—Kšœœ˜Kšœ œœ™:Kšœ3˜3Kšœœ˜!Kšœ œœœ™QK˜—Kšœ˜K˜K˜—K˜šŸœ  œœ˜6Kšœœ˜Kšœ.˜.K˜—K˜š Ÿœ  œœœœ˜IKšœœ˜Kšœœ ˜.K˜—K˜Kšœ œœ˜-K˜š Ÿœ  œœœœ˜[šŸ œœ˜Kšœœœ ˜IK˜—Kšœœ˜ šœ ˜ Kšœ)œœ˜8Kšœ˜—K˜ K˜—K˜šŸœœœ œ˜KKšœœœ!˜YK˜—K˜š Ÿœœ'œ œœ˜lKš œœœœœ˜5Kšœœœœ˜3Kšœœ˜K˜—K˜Kšœ˜—…—*69๚