DIRECTORY Commander, CommandTool, FS, IO, MakeDo, OrderedSymbolTableRef, Rope, TimeStamp, ViewerIO; MakeDoImpl: CEDAR PROGRAM IMPORTS CommandTool, FS, IO, OrderedSymbolTableRef, Rope, ViewerIO EXPORTS MakeDo = BEGIN OPEN MakeDo; Warning: PUBLIC SIGNAL [message: ROPE] = CODE; Error: PUBLIC ERROR [message: ROPE] = CODE; nodes: OrderedSymbolTableRef.Table _ OrderedSymbolTableRef.CreateTable[CompareNodes]; depth: INT _ 0; debugging: BOOLEAN _ TRUE; log, in: IO.STREAM; Log: PUBLIC PROC [fmt: ROPE, v1, v2, v3, v4, v5: IO.Value _ [null[]]] = BEGIN IF NOT debugging THEN RETURN; FOR i: INT IN [0 .. depth) DO log.PutChar['\t] ENDLOOP; log.PutF[fmt, v1, v2, v3, v4, v5]; log.PutChar['\n]; END; Confirm: PROC [action: ROPE] = BEGIN IF NOT debugging THEN RETURN; FOR i: INT IN [0 .. depth) DO log.PutChar['\t] ENDLOOP; log.PutF["Ready to %g ? ", IO.rope[action]]; WHILE in.GetChar[] # '\n DO NULL ENDLOOP; END; GetNode: PUBLIC PROC [name: ROPE] RETURNS [node: Node] = { IF (node _ NARROW[nodes.Lookup[name]]) = NIL THEN nodes.Insert[node _ NEW [NodeRep _ [ name: name, needers: OrderedSymbolTableRef.CreateTable[CompareCommands]]]]}; CompareNodes: --PROC [r1, r2: Item] RETURNS [Comparison]-- PUBLIC OrderedSymbolTableRef.CompareProc = BEGIN GetKey: PROC [ra: REF ANY] RETURNS [r: ROPE] = { r _ WITH ra SELECT FROM n: Node => n.name, x: ROPE => x, ENDCASE => ERROR}; k1: ROPE _ GetKey[r1]; k2: ROPE _ GetKey[r2]; RETURN [k1.Compare[k2]]; END; CompareCommands: OrderedSymbolTableRef.CompareProc --PROC [r1, r2: Item] RETURNS [Comparison]-- = TRUSTED BEGIN k1: INT _ LOOPHOLE[r1]; k2: INT _ LOOPHOLE[r2]; RETURN [IF k1 < k2 THEN less ELSE IF k1 > k2 THEN greater ELSE equal]; END; Needed: PROC [n: Node] RETURNS [b: BOOLEAN] = {b _ n.needers.Size[] > 0}; EnsureNeed: PROC [needed: Node, needer: Command] = {IF needed.needers.Lookup[needer] = NIL THEN needed.needers.Insert[needer]}; EnsureNotNeed: PROC [needed: Node, needer: Command] = {[] _ needed.needers.Delete[needer]}; FileExists: --PROC [result: Node, c: Command] RETURNS [exists: BOOLEAN]-- PUBLIC ExistProc = BEGIN exists _ TRUE; [] _ FS.FileInfo[result.name !FS.Error => {exists _ FALSE; CONTINUE}]; END; ClearAllLinks: PROC = BEGIN Clear: PROC [any: REF ANY] RETURNS [stop: BOOLEAN] = { n: Node _ NARROW[any]; n.producer _ NIL; n.consumers _ NIL; n.derivedCmds _ NIL; n.needers.DeleteAllItems[]; stop _ FALSE}; nodes.EnumerateIncreasing[Clear]; END; finders: LIST OF Finder _ NIL; AddFinder: PUBLIC PROC [finder: Finder, end: End] = BEGIN SELECT end FROM front => finders _ CONS[finder, finders]; back => {fl: LIST OF Finder; IF finders = NIL THEN {finders _ LIST[finder]; RETURN}; FOR fl _ finders, fl.rest WHILE fl.rest # NIL DO NULL ENDLOOP; fl.rest _ LIST[finder]}; ENDCASE => ERROR; END; EnsureNodeProduced: PROC [node: Node] = BEGIN IF node.producer # NIL THEN RETURN; IF EnsureProduced[node.name] = NIL THEN node.producer _ leaf; END; EnsureProduced: PROC [resultName: ROPE] RETURNS [c: Command] = BEGIN FOR fl: LIST OF Finder _ finders, fl.rest WHILE fl # NIL DO found: BOOLEAN; makes, from: NodeList; cmd: ROPE; why: Node; NotCurrent: NotCurrentProc; Rederive: RederiveProc; Exists: ExistProc; foundData: REF ANY; [found, makes, from, cmd, why, NotCurrent, Rederive, Exists, foundData] _ fl.first.finderProc[resultName: resultName, finderData: fl.first.finderData]; IF found THEN { first: BOOLEAN _ TRUE; already: Command _ NIL; FOR ml: NodeList _ makes, ml.rest WHILE ml # NIL DO IF first THEN {already _ ml.first.producer; first _ FALSE} ELSE {IF ml.first.producer # already THEN ERROR Error[IO.PutFR[ "Command %g doesn't precisely cover command %g (e.g., at %g)", IO.refAny[cmd], IO.refAny[IF already # NIL THEN already.cmd ELSE NIL], IO.rope[ml.first.name]]]}; ENDLOOP; IF already # NIL THEN RETURN [already]; c _ NEW [CommandRep _ [cmd: cmd, makes: makes, from: from, dependencySource: why, NotCurrent: NotCurrent, Rederive: Rederive, Exists: Exists, foundData: foundData]]; FOR ml: NodeList _ c.makes, ml.rest WHILE ml # NIL DO IF ml.first.producer # NIL THEN ERROR; ml.first.producer _ c; ENDLOOP; FOR fl: NodeList _ c.from, fl.rest WHILE fl # NIL DO fl.first.consumers _ CONS[c, fl.first.consumers]; ENDLOOP; why.derivedCmds _ CONS[c, why.derivedCmds]; RETURN}; ENDLOOP; c _ NIL; END; root: Command _ NEW [CommandRep _ [cmd: "-- root"]]; leaf: Command _ NEW [CommandRep _ [cmd: "-- leaf", Exists: FileExists]]; Ensure: PUBLIC PROC [what: RopeList, ch: Commander.Handle] = BEGIN ClearAllLinks[]; commanderHandle _ ch; FOR what _ what, what.rest WHILE what # NIL DO c: Command _ EnsureProduced[what.first]; IF c # NIL THEN { FOR ml: NodeList _ c.makes, ml.rest WHILE ml # NIL DO EnsureNeed[ml.first, root]; ENDLOOP; EnsureWork[c, FALSE]; }; ENDLOOP; commanderHandle _ NIL; Log["\n"]; END; commanderHandle: Commander.Handle; EnsureWork: PROC [c: Command, perturbed: BOOLEAN] = BEGIN PostAmble: PROC = {Log["EW <- %g", IO.rope[c.cmd]]; depth _ depth - 1}; oldNeeds: BOOLEAN; IF c = leaf THEN RETURN; IF c.computed AND NOT perturbed THEN RETURN; depth _ depth + 1; Log["EW -> %g ", IO.rope[c.cmd]]; FOR sl: NodeList _ c.from, sl.rest WHILE sl # NIL DO EnsureNodeProduced[sl.first]; EnsureWork[sl.first.producer, FALSE]; ENDLOOP; oldNeeds _ c.needsToBeDone; c.needsToBeDone _ FALSE; FOR ml: NodeList _ c.makes, ml.rest WHILE ml # NIL DO IF Needed[ml.first] AND NOT c.Exists[ml.first, c] THEN c.needsToBeDone _ TRUE; ENDLOOP; IF (NOT c.needsToBeDone) AND c.NotCurrent[c] THEN c.needsToBeDone _ TRUE; c.computed _ TRUE; IF oldNeeds AND NOT c.needsToBeDone THEN ERROR; IF oldNeeds = c.needsToBeDone THEN {PostAmble[]; RETURN}; FOR sl: NodeList _ c.from, sl.rest WHILE sl # NIL DO (IF c.needsToBeDone THEN EnsureNeed ELSE EnsureNotNeed)[sl.first, c]; ENDLOOP; FOR sl: NodeList _ c.from, sl.rest WHILE sl # NIL DO EnsureWork[sl.first.producer, TRUE]; ENDLOOP; IF c.needsToBeDone THEN { ofll: LIST OF NodeList _ NIL; rcl: CommandList _ NIL; Confirm[c.cmd]; doans _ CommandTool.DoCommand[commandLine: c.cmd, parent: commanderHandle]; c.needsToBeDone _ FALSE; FOR sl: NodeList _ c.from, sl.rest WHILE sl # NIL DO EnsureNotNeed[sl.first, c]; ENDLOOP; FOR ml: NodeList _ c.makes, ml.rest WHILE ml # NIL DO FOR cl: CommandList _ ml.first.derivedCmds, cl.rest WHILE cl # NIL DO ofll _ CONS[RederiveCommand[cl.first], ofll]; ENDLOOP; ENDLOOP; FOR rcl _ rcl, rcl.rest WHILE rcl # NIL DO EnsureWork[rcl.first, TRUE] ENDLOOP; FOR ofll _ ofll, ofll.rest WHILE ofll # NIL DO ofl: NodeList _ ofll.first; FOR ofl _ ofl, ofl.rest WHILE ofl # NIL DO EnsureWork[ofl.first.producer, TRUE]; ENDLOOP; ENDLOOP; FOR sl: NodeList _ c.from, sl.rest WHILE sl # NIL DO EnsureWork[sl.first.producer, TRUE]; ENDLOOP; FOR dl: NodeList _ c.makes, dl.rest WHILE dl # NIL DO FOR cl: CommandList _ dl.first.consumers, cl.rest WHILE cl # NIL DO EnsureWork[cl.first, TRUE]; ENDLOOP; ENDLOOP; }; PostAmble[]; END; doans: REF ANY; RederiveCommand: PROC [c: Command] RETURNS [oldFroms: NodeList] = BEGIN oldFroms _ c.from; FOR fl: NodeList _ c.from, fl.rest WHILE fl # NIL DO fl.first.consumers _ RemoveCommand[c, fl.first.consumers]; IF c.needsToBeDone THEN EnsureNotNeed[fl.first, c]; ENDLOOP; c.from _ c.Rederive[c]; FOR fl: NodeList _ c.from, fl.rest WHILE fl # NIL DO fl.first.consumers _ CONS[c, fl.first.consumers]; IF c.needsToBeDone THEN EnsureNeed[fl.first, c]; ENDLOOP; END; RemoveCommand: PROC [c: Command, l: CommandList] RETURNS [ohne: CommandList] = BEGIN last: CommandList _ NIL; ohne _ l; FOR l _ l, l.rest WHILE l # NIL DO IF l.first = c THEN { IF last = NIL THEN ohne _ l.rest ELSE last.rest _ l.rest; RETURN}; last _ l; ENDLOOP; ERROR; END; [in: in, out: log] _ ViewerIO.CreateViewerStreams["MakeDo Log"]; END. $BCDery>MakeDoImpl.Mesa Last Edited by: Spreitzer, March 3, 1984 5:42:36 pm PST IF A is needed & an A does not exist & C makes A THEN C needs to be done IF an A exists & C makes A from B & a B exists & current A was not made from current B THEN C needs to be done IF C needs to be done & C uses B THEN B is needed IF C needs to be done & C uses B & no B exists THEN C cannot be done because of missing B FOR sl: NodeList _ c.from, sl.rest WHILE sl # NIL DO IF NOT sl.first.producer.Exists[sl.first, sl.first.producer] THEN ERROR; ENDLOOP; Κ W– "cedar" style˜Icode™J™7K˜K™HK™K™nK™K™1K™K™YK™KšΟk œœœ;˜cK˜šΠbx œœ˜Kšœœœ'˜BKšœ ˜—K˜Kšœœ˜K˜Kš Πblœœœ œœ˜.K˜Kš Ÿœœœ œœ˜+K˜KšœU˜UK˜Kšœœ˜Kšœ œœ˜Kšœ œœ˜K˜š Οnœœœœœ˜GKš˜Kšœœ œœ˜Kš œœœœœ˜7K˜"K˜Kšœ˜—K˜š œœ œ˜Kš˜Kšœœ œœ˜Kš œœœœœ˜7Kšœœ˜,Kšœœœœ˜)Kšœ˜—K˜š  œœœœœ˜:šœ œ˜,šœœ ˜)Kšœ ˜ Kšœ@˜@———K˜š  œΟc,œœ$˜eKš˜š  œœœœœœ˜0šœœœ˜K˜Kšœœ˜ Kšœœ˜——Kšœœ˜Kšœœ˜Kšœ˜Kšœ˜—K˜š œ$‘,œ˜iKš˜Kšœœœ˜Kšœœœ˜Kšœœ œœœ œ œ˜FKšœ˜—K˜Kš œœ œœ˜IK˜š  œœ"˜2Kšœœ!œœ ˜L—K˜š  œœ"˜5Kšœ%˜%—K˜š  œ‘=œœ ˜\Kš˜Kšœ œ˜Kš œœœœœ˜FKšœ˜—K˜š  œœ˜Kš˜š  œœœœœœ˜6Kšœ œ˜Kšœ œ˜Kšœœ˜Kšœœ˜K˜Kšœœ˜—K˜!Kšœ˜—K˜Kšœ œœ œ˜K˜š  œœœ˜3Kš˜šœ˜Kšœœ˜)šœ œœ˜Kš œ œœ œ œ˜7Kš œœ œœœœ˜>Kšœ œ ˜—Kšœœ˜—šœ˜K˜——š œœ˜'Kš˜Kšœœœœ˜#Kšœœœ˜=Kšœ˜—K˜š œœœœ˜>Kš˜š œœœœœ˜;Kšœœ˜K˜Kšœœ˜ K˜ Kšœ˜Kšœ˜K˜Kšœ œœ˜Kšœ—˜—šœœ˜Kšœœœ˜Kšœœ˜šœœœ˜3šœ˜Kšœ'œ˜1šœœ˜$šœœœ˜Kšœ>˜>Kšœ ˜Kš œœ œœ œœ˜6Kšœ˜———Kšœ˜—Kšœ œœœ ˜'šœœ˜Kšœ˜—šœ!œœ˜5Kšœœœœ˜&Kšœ˜Kšœ˜—šœ œœ˜4Kšœœ˜1Kšœ˜—Kšœœ˜+Kšœ˜—Kšœ˜—Kšœœ˜Kšœ˜—K˜Kšœœ!˜4Kšœœ5˜HK˜š œœœ)˜