<> <> DIRECTORY Atom, BasicTime, Commander, DFUtilities, FS, IO, IOClasses, MakeDo, Process, RedBlackTree, Rope; MakeDoCmds: CEDAR PROGRAM IMPORTS Atom, Commander, DFUtilities, FS, IO, IOClasses, MakeDo, Process, RedBlackTree, Rope EXPORTS MakeDo = BEGIN ROPE: TYPE = Rope.ROPE; GetObjectOrSwitch: PROC [from: IO.STREAM] RETURNS [asAny: REF ANY] = { SELECT from.PeekChar[] FROM '- => { IF from.GetChar[] # '- THEN ERROR; RETURN[Atom.MakeAtom[from.GetTokenRope[IO.IDProc].token]]; }; ENDCASE => RETURN [GetObject[from]]; }; GetObject: PROC [from: IO.STREAM] RETURNS [node: MakeDo.Node] = { SELECT from.PeekChar[] FROM '( => { className, objectName: ROPE; class: MakeDo.NodeClass; node: MakeDo.Node; IF from.GetChar[] # '( THEN ERROR; className _ from.GetRopeLiteral[]; objectName _ from.GetRopeLiteral[]; [] _ from.SkipWhitespace[]; IF from.GetChar[] # ') THEN { SIGNAL MakeDo.Warning["Syntax error, you fool"]; RETURN [NIL]; }; class _ MakeDo.LookupNodeClass[className]; IF class = NIL THEN { SIGNAL MakeDo.Warning[IO.PutFR[ "no such class as %g", [refAny[className]] ]]; RETURN [NIL]; }; node _ MakeDo.FindNode[objectName, class]; RETURN [node]; }; ENDCASE => { fileName: ROPE _ from.GetTokenRope[IO.IDProc].token; node: MakeDo.Node _ MakeDo.FindNode[fileName, MakeDo.fileClass]; RETURN [node]; }; }; AnalyzeDFFile: PUBLIC PROC [dfName: ROPE, goals: MakeDo.RefTable, modifiable: MakeDo.ModifiabilitySpec, doToVerifyGoals, doToOthers: MakeDo.DoToFile] = { Consume: PROC [item: REF ANY] RETURNS [stop: BOOL _ FALSE] = BEGIN Process.CheckForAbort[]; WITH item SELECT FROM di: REF DFUtilities.DirectoryItem => NULL; fi: REF DFUtilities.FileItem => { cp: FS.ComponentPositions; full, verless: ROPE; [full, cp, ] _ FS.ExpandName[fi.name]; verless _ full.Substr[start: 0, len: cp.ext.start + cp.ext.length]; SELECT (IF fi.verifyRoot THEN doToVerifyGoals ELSE doToOthers) FROM ignore => NULL; makeGoal => NameAdd[verless, TRUE, TRUE]; makeModifiable => NameAdd[verless, FALSE, TRUE]; ENDCASE => ERROR; }; ii: REF DFUtilities.ImportsItem => NULL; ii: REF DFUtilities.IncludeItem => { dfIn: IO.STREAM _ FS.StreamOpen[ii.path1]; DFUtilities.ParseFromStream[in: dfIn, proc: Consume]; dfIn.Close[]}; ci: REF DFUtilities.CommentItem => NULL; wi: REF DFUtilities.WhiteSpaceItem => NULL; ENDCASE => ERROR; END; NameAdd: PROC [name: ROPE, goal, mod: BOOL] = { n: MakeDo.Node _ MakeDo.FindNode[name, MakeDo.fileClass]; NodeAdd[n, goal, mod]; }; NodeAdd: PROC [n: MakeDo.Node, goal, mod: BOOL] = { IF mod THEN MakeDo.EnsureRefInTable[n, modifiable]; IF goal THEN MakeDo.EnsureRefInTable[n, goals]; }; dfIn: IO.STREAM = FS.StreamOpen[dfName]; DFUtilities.ParseFromStream[in: dfIn, proc: Consume]; dfIn.Close[]; }; CmdMakeDo: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- = BEGIN AddDF: PROC [doToVerifyGoals, doToOthers: MakeDo.DoToFile] = BEGIN dfName: ROPE _ NIL; dfIn: IO.STREAM _ NIL; IF doToVerifyGoals=makeModifiable OR doToOthers=makeModifiable THEN specModifiable _ TRUE; [] _ in.SkipWhitespace[]; IF in.EndOf[] THEN {AddMsg["No DF-file name after -whatever"]; RETURN}; dfName _ in.GetTokenRope[IO.IDProc].token; IF dfName.Find["."] < 0 THEN dfName _ dfName.Cat[".DF"]; AnalyzeDFFile[dfName, goals, modifiable, doToVerifyGoals, doToOthers]; END; NodeAdd: PROC [n: MakeDo.Node, goal, mod: BOOL] = { IF mod THEN MakeDo.EnsureRefInTable[n, modifiable]; IF goal THEN MakeDo.EnsureRefInTable[n, goals]; }; AddObject: PROC [goal, mod: BOOL] = { n: MakeDo.Node; IF mod THEN specModifiable _ TRUE; [] _ in.SkipWhitespace[]; IF in.EndOf[] THEN {AddMsg["No object after -mn"]; RETURN}; n _ GetObject[in]; NodeAdd[n, goal, mod]; }; AddMsg: PROC [more: ROPE] = {msgout.PutRope[more]; msgout.PutRope["\n"]}; goals: MakeDo.RefTable _ MakeDo.MakeRefTable[]; modifiable: MakeDo.RefTable _ MakeDo.MakeRefTable[]; specModifiable: BOOL _ FALSE; in: IO.STREAM _ IO.RIS[cmd.commandLine]; msgout, logfile: IO.STREAM _ NIL; logfile _ FS.StreamOpen["MakeDo.log", create]; msgout _ IOClasses.CreateDribbleOutputStream[logfile, cmd.err]; {ENABLE MakeDo.Warning => {AddMsg[message]; RESUME}; FOR i: INT _ in.SkipWhitespace[], in.SkipWhitespace[] WHILE NOT in.EndOf[] DO thing: REF ANY _ GetObjectOrSwitch[in]; IF thing # NIL THEN WITH thing SELECT FROM a: ATOM => SELECT a FROM $gr => AddDF[makeGoal, ignore]; $gm => AddDF[makeGoal, makeGoal]; $dr => AddDF[makeGoal, makeModifiable]; $dm => AddDF[makeGoal, makeGoal]; $md => AddDF[makeModifiable, makeModifiable]; $mn => AddObject[FALSE, TRUE]; $p => MakeDo.SetProcessAllocation[in.GetInt[]]; ENDCASE => AddMsg[IO.PutFR["Bad switch [-%g]", IO.atom[a]]]; ENDCASE => { n: MakeDo.Node _ MakeDo.NarrowToNode[thing]; NodeAdd[n, TRUE, TRUE]; }; Process.CheckForAbort[]; ENDLOOP; IF NOT specModifiable THEN {modifiable.DestroyTable[]; modifiable _ NIL}; SELECT cmd.procData.clientData FROM $MakeDo => { okGoalCount, nonOKGoalCount, nSteps, nFailedSteps: NAT; failedSteps: MakeDo.ActionList; failedGoals: MakeDo.NodeList; [okGoalCount:okGoalCount, nonOKGoalCount:nonOKGoalCount, nSteps:nSteps, failedSteps:failedSteps, nonOKGoalList:failedGoals] _ MakeDo.Ensure[goals, modifiable]; nFailedSteps _ 0; FOR failedSteps _ failedSteps, failedSteps.rest WHILE failedSteps # NIL DO msgout.PutF["%lFailed: %g%l\n", IO.rope["b"], IO.rope[failedSteps.first.PublicPartsOfAction[].cmd], IO.rope["B"]]; nFailedSteps _ nFailedSteps + 1; ENDLOOP; IF nFailedSteps > 0 THEN msgout.PutF["%g failed; %g ok.\n", IO.rope[Quantify[nFailedSteps, "step"]], IO.int[nSteps - nFailedSteps]]; msgout.PutF["%g OK; %g not.\n", IO.rope[Quantify[okGoalCount, "goal"]], IO.int[nonOKGoalCount]]; IF failedGoals # NIL THEN { msgout.PutF["%lNot OK:", IO.rope["b"]]; FOR failedGoals _ failedGoals, failedGoals.rest WHILE failedGoals # NIL DO msgout.PutF[" %g", IO.rope[failedGoals.first.DescribeNode[]]]; ENDLOOP; msgout.PutF["%l\n", IO.rope["B"]]; }; result _ IF nonOKGoalCount # 0 THEN $Failure ELSE $Success; }; $MakeCommandList => { al: MakeDo.ActionList _ MakeDo.GetActions[goals, modifiable]; al _ MakeDo.DestructivelyReverseActionList[al]; msgout.PutRope["Commands:\n"]; FOR al _ al, al.rest WHILE al # NIL DO a: MakeDo.Action = al.first; cmd: ROPE = a.PublicPartsOfAction[].cmd; msgout.PutF["%g\n", [rope[cmd]] ]; ENDLOOP; al _ al; }; ENDCASE => ERROR; }; msgout.Flush[]; logfile.Close[]; END; CmdExplain: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- = BEGIN args: MakeDo.RefTable _ MakeDo.MakeRefTable[]; in: IO.STREAM _ IO.RIS[cmd.commandLine]; FOR i: INT _ in.SkipWhitespace[], in.SkipWhitespace[] WHILE NOT in.EndOf[] DO ENABLE MakeDo.Warning => { cmd.out.PutRope[message]; cmd.out.PutRope["\n"]; RESUME}; n: MakeDo.Node _ GetObject[in]; IF n # NIL THEN MakeDo.EnsureRefInTable[n, args]; ENDLOOP; MakeDo.Explain[cmd, args]; END; CmdProduce: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- = BEGIN in: IO.STREAM _ IO.RIS[cmd.commandLine]; FOR i: INT _ in.SkipWhitespace[], in.SkipWhitespace[] WHILE NOT in.EndOf[] DO ENABLE MakeDo.Warning => { cmd.out.PutRope[message]; cmd.out.PutRope["\n"]; RESUME}; n: MakeDo.Node _ GetObject[in]; IF n # NIL THEN MakeDo.RetryToProduce[n]; ENDLOOP; in.Close[]; END; CmdSuspect: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- = BEGIN in: IO.STREAM _ IO.RIS[cmd.commandLine]; FOR i: INT _ in.SkipWhitespace[], in.SkipWhitespace[] WHILE NOT in.EndOf[] DO ENABLE MakeDo.Warning => { cmd.out.PutRope[message]; cmd.out.PutRope["\n"]; RESUME}; thing: REF ANY _ GetObjectOrSwitch[in]; DoObject: PROC [change, current, producer: BOOL] = { n: MakeDo.Node _ GetObject[in]; Work[n, change, current, producer]; }; Work: PROC [n: MakeDo.Node, change, current, producer: BOOL] = { IF change THEN MakeDo.SuspectNodeChange[n]; IF current THEN MakeDo.UncurrentNode[n]; IF producer THEN MakeDo.UncurrentProducer[n]; }; IF thing # NIL THEN WITH thing SELECT FROM a: ATOM => SELECT a FROM $allCurrent => MakeDo.ForAll[FALSE, TRUE]; $allChange => MakeDo.ForAll[TRUE, FALSE]; $all => MakeDo.ForAll[TRUE, TRUE]; $change => DoObject[TRUE, FALSE, FALSE]; $current => DoObject[FALSE, TRUE, FALSE]; $producer => DoObject[FALSE, FALSE, TRUE]; ENDCASE => cmd.out.PutF["Unrecognized switch -%g\n", [atom[a]]]; ENDCASE => { n: MakeDo.Node _ MakeDo.NarrowToNode[thing]; Work[n, TRUE, TRUE, TRUE]; }; ENDLOOP; in.Close[]; END; CmdDestroy: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- = BEGIN MakeDo.DestroyGraph[]; END; Quantify: PROC [n: NAT, stuff: ROPE] RETURNS [quantity: ROPE] = {quantity _ IO.PutFR["%g %g%g", IO.int[n], IO.rope[stuff], IO.rope[IF n = 1 THEN "" ELSE "s"]]}; Commander.Register[key: "MakeDo", proc: CmdMakeDo, doc: "Ensure that derived files are up to date", clientData: $MakeDo]; Commander.Register[key: "MakeCommandList", proc: CmdMakeDo, doc: "List commands that would bring derived files are up to date", clientData: $MakeCommandList]; Commander.Register[key: "MakeExcuses", proc: CmdExplain, doc: "Explain what MakeDo would do"]; Commander.Register[key: "MakeSuspicion", proc: CmdSuspect, doc: "Suspect everything"]; Commander.Register[key: "MakeEmpty", proc: CmdDestroy, doc: "Delete the entire dependency graph"]; Commander.Register[key: "MakeProducer", proc: CmdProduce, doc: "For leaves, try again to find a producer"]; END.