MakeDoCmds.Mesa
Last Edited by: Spreitzer, February 18, 1986 5:30:37 pm PST
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: BOOLFALSE] =
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.STREAMFS.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 ANYNIL, msg: ROPENIL] --Commander.CommandProc-- =
BEGIN
AddDF: PROC [doToVerifyGoals, doToOthers: MakeDo.DoToFile] =
BEGIN
dfName: ROPENIL;
dfIn: IO.STREAMNIL;
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: BOOLFALSE;
in: IO.STREAMIO.RIS[cmd.commandLine];
msgout, logfile: IO.STREAMNIL;
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 ANYNIL, msg: ROPENIL] --Commander.CommandProc-- =
BEGIN
args: MakeDo.RefTable ← MakeDo.MakeRefTable[];
in: IO.STREAMIO.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 ANYNIL, msg: ROPENIL] --Commander.CommandProc-- =
BEGIN
in: IO.STREAMIO.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 ANYNIL, msg: ROPENIL] --Commander.CommandProc-- =
BEGIN
in: IO.STREAMIO.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 ANYNIL, msg: ROPENIL] --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.