MakeDoCmds.Mesa
Last Edited by: Spreitzer, June 16, 1986 10:59:30 pm PDT
DIRECTORY Atom, BasicTime, Commander, DFUtilities, FS, IO, IOClasses, MakeDo, Process, RedBlackTree, Rope;
MakeDoCmds: CEDAR PROGRAM
IMPORTS Atom, BasicTime, 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[Break].token]];
};
ENDCASE => RETURN [GetObject[from]];
};
Break: PROC [char: CHAR] RETURNS [cc: IO.CharClass] = {
cc ← SELECT char FROM
IN [0C .. ' ] => sepr,
ENDCASE => other;
};
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[Break].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[];
};
DFDontExist: ERROR [fileName: ROPE] = CODE;
CmdMakeDo: PROC [cmd: Commander.Handle] RETURNS [result: REF ANYNIL, msg: ROPENIL] --Commander.CommandProc-- =
BEGIN
ENABLE DFDontExist => {msg ← fileName.Concat[" doesn't exist"]; result ← $Failure; CONTINUE};
AddDF: PROC [doToVerifyGoals, doToOthers: MakeDo.DoToFile] =
BEGIN
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[Break].token;
IF dfName.Find["."] < 0 THEN dfName ← dfName.Cat[".DF"];
[] ← FS.FileInfo[dfName !FS.Error => IF error.group = user THEN DFDontExist[dfName]];
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 -nm"]; 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, logfileStream: IO.STREAMNIL;
logFile: FS.OpenFile;
nArgs: INT ← 0;
rgomd: BOOLFALSE;
dfName: ROPENIL;
logfileStream ← FS.StreamOpen["MakeDo.log", create];
logFile ← FS.OpenFileFromStream[logfileStream];
msgout ← IOClasses.CreateDribbleOutputStream[logfileStream, 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];
nArgs ← nArgs + 1;
IF thing # NIL THEN WITH thing SELECT FROM
a: ATOM => SELECT a FROM
$rg => AddDF[makeGoal, ignore];
$og => AddDF[makeGoal, makeGoal];
$rgom => {AddDF[makeGoal, makeModifiable]; rgomd ← TRUE};
$dr => {AddDF[makeGoal, makeModifiable]; rgomd ← TRUE};
$om => AddDF[makeModifiable, makeModifiable];
$nm => 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;
IF rgomd AND nArgs = 1 AND dfName # NIL THEN {
msgout.PutF["MakingDo package in %g.\n", [rope[dfName]]];
};
[okGoalCount:okGoalCount, nonOKGoalCount:nonOKGoalCount, nSteps:nSteps, failedSteps:failedSteps, nonOKGoalList:failedGoals] ← MakeDo.Ensure[goals, modifiable, cmd];
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;
};
$MakePrediction, $MakeCommandList => {
al: MakeDo.ActionList ← MakeDo.GetActions[
goals,
modifiable,
SELECT cmd.procData.clientData FROM
$MakePrediction => toBeDone,
$MakeCommandList => all,
ENDCASE => ERROR];
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.SetByteCountAndCreatedTime[created: BasicTime.Now[]];
logFile ← FS.nullOpenFile;
logfileStream.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;
Bitch: ERROR [message: ROPE] = CODE;
CmdSuspect: PROC [cmd: Commander.Handle] RETURNS [result: REF ANYNIL, msg: ROPENIL] --Commander.CommandProc-- =
BEGIN ENABLE Bitch => {msg ← message; result ← $Failure; CONTINUE};
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;
[] ← in.SkipWhitespace[];
IF in.EndOf[] THEN Bitch["MakeDo ran off end of command line --- missing object"];
n ← 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, clientData: $MakeDo, doc: "Ensure that derived files are up to date. Syntax is
MakeDo <
arg>*
 <
arg>:
  <object> |

  -nm <object> |
  -rg <DF file name> |
  -og <DF file name> |
  -rgom <DF file name> |
  -dr <DF file name> |
  -om <DF file name> |
  -p <number>
 <object>
:
  <file name>
|
  (
className:<ROPE> objectName:<ROPE>)"];
Commander.Register[key: "MakePrediction", proc: CmdMakeDo, clientData: $MakePrediction, doc: "Estimate what 'MakeDo' would execute. Syntax is
MakeCommandList <arg>*"];
Commander.Register[key: "MakeCommandList", proc: CmdMakeDo, clientData: $MakeCommandList, doc: "List all commands needed to make goals. Syntax is
MakeCommandList <arg>*"];
Commander.Register[key: "MakeExcuses", proc: CmdExplain, doc: "Explain why MakeDo is misbehaving. Syntax is
MakeExcuses <object>*"];
Commander.Register[key: "MakeSuspicion", proc: CmdSuspect, doc: "Suspect cached information is out of synch with reality. Syntax is
MakeSuspicion <arg>*
 <
arg>:
  -change
<
object> --suspect the named file of change
  -current
<object> --forget whether named file is current
  -producer
<object> --suspect that the next execution of the file's producer will be different from the last
  <
object> --all of the above
  -allChange
--suspect every object of change
  -allCurrent
--suspect every object of not being current and every action of behaving differently than last time
  -all
--all of the above"];
Commander.Register[key: "MakeEmpty", proc: CmdDestroy, doc: "Delete the entire dependency graph. No arguments"];
Commander.Register[key: "MakeProducer", proc: CmdProduce, doc: "For leaves, try again to find a producer. Syntax is
MakeProducer <object>*"];
END.