<> <> <> DIRECTORY BasicTime, FS, IO, IOClasses, MakeDo, Rope; RoseDeps: CEDAR PROGRAM IMPORTS BasicTime, FS, IO, IOClasses, MakeDo, Rope = BEGIN ROPE: TYPE = Rope.ROPE; RoseCommand: TYPE = REF RoseCommandRep; RoseCommandRep: TYPE = RECORD [ resultBase, resultShort: ROPE, roseNode, transNode: MakeDo.Node, earliestResultNode, lateIngredientNode: MakeDo.Node _ NIL, earliestResultTime, lateIngredientTime: BasicTime.GMT _ BasicTime.nullGMT, cmd: ROPE _ NIL]; rosemaryClass: MakeDo.CommandClass _ NEW [MakeDo.CommandClassRep _ [ NotCurrent: RoseNotCurrent, Rederive: RederiveRose, UpdateTime: MakeDo.FileTime, Explain: ExplainRose ]]; RoseFind: PROC [resultName: ROPE, finderData: REF ANY] RETURNS [found: BOOLEAN, sought: MakeDo.Node, makes, from, why: MakeDo.NodeList, cmd: ROPE, class: MakeDo.CommandClass, foundData: REF ANY] --MakeDo.FinderProc-- = BEGIN resultCP: FS.ComponentPositions; resultFull, resultBase, resultExt, roseName: ROPE; roseFound: BOOLEAN; roseNode: MakeDo.Node; rc: RoseCommand; [resultFull, resultCP, ] _ FS.ExpandName[resultName]; resultExt _ resultFull.Substr[start: resultCP.ext.start, len: resultCP.ext.length]; roseFound _ resultExt.Equal["RoseSymbols", FALSE] <> OR resultExt.Equal["pass", FALSE] OR resultExt.Equal["RoseLoad", FALSE]; found _ roseFound OR resultExt.Equal["Mesa", FALSE]; IF NOT found THEN RETURN; resultBase _ resultFull.Substr[start: 0, len: resultCP.ext.start-1]; why _ LIST[roseNode _ MakeDo.GetNode[roseName _ resultBase.Cat[".Rose"]]]; found _ MakeDo.Exists[roseNode, MakeDo.FileTime]; IF NOT found THEN RETURN; foundData _ rc _ NEW [RoseCommandRep _ [ resultBase: resultBase, resultShort: resultFull.Substr[start:resultCP.base.start, len:resultCP.base.length], roseNode: roseNode, transNode: MakeDo.GetNode["RoseTranslator.Version"] ]]; makes _ LIST[ <> MakeDo.GetNode[resultBase.Cat[".RoseSymbols"]], MakeDo.GetNode[resultBase.Cat[".pass"]], MakeDo.GetNode[resultBase.Cat[".RoseLoad"]], MakeDo.GetNode[resultBase.Cat[".Mesa"]]]; sought _ IF resultExt.Equal["RoseSymbols", FALSE] THEN makes.first ELSE IF resultExt.Equal["pass", FALSE] THEN makes.rest.first ELSE IF resultExt.Equal["RoseLoad", FALSE] THEN makes.rest.rest.first ELSE IF resultExt.Equal["Mesa", FALSE] THEN makes.rest.rest.rest.first ELSE ERROR; from _ DeriveFrom[rc]; rc.cmd _ cmd _ IO.PutFR["RoseTranslate %g", IO.rope[rc.resultShort]]; class _ rosemaryClass; END; DeriveFrom: PROC [rc: RoseCommand] RETURNS [from: MakeDo.NodeList] = BEGIN NoteModuleRef: PROC [moduleName: ROPE, type: ModuleReferenceType] = { SELECT type FROM Directory, Imports, Open => NULL; Library => from _ CONS[ MakeDo.GetNode[FS.ExpandName[moduleName.Cat[".RoseSymbols"]].fullFName], from]; ENDCASE => ERROR}; from _ LIST[rc.roseNode, rc.transNode]; [] _ EnumerateModuleReferences[fromName: MakeDo.PublicPartsOfNode[rc.roseNode].name, to: NoteModuleRef]; END; IDProc: IO.BreakProc = {RETURN [SELECT char FROM IN [IO.NUL .. IO.SP] => sepr, '; => break, ENDCASE => other]}; RederiveRose: PROC [c: MakeDo.Command] RETURNS [from: MakeDo.NodeList, cmd: ROPE] --MakeDo.RederiveProc-- = { rc: RoseCommand _ NARROW[MakeDo.PublicPartsOfCommand[c].foundData]; from _ DeriveFrom[rc]; cmd _ rc.cmd}; RoseNotCurrent: PROC [c: MakeDo.Command] RETURNS [notCurrent: BOOLEAN] --MakeDo.NotCurrentProc-- = BEGIN fd: REF ANY; makes, from: MakeDo.NodeList; rc: RoseCommand; [foundData: fd, makes: makes, from: from] _ MakeDo.PublicPartsOfCommand[c]; rc _ NARROW[fd]; rc.earliestResultTime _ BasicTime.latestGMT; rc.earliestResultNode _ rc.lateIngredientNode _ NIL; FOR ml: MakeDo.NodeList _ makes, ml.rest WHILE ml # NIL DO thisTime: BasicTime.GMT _ MakeDo.Latest[ml.first]; IF NOT MakeDo.Needed[ml.first] THEN LOOP; IF thisTime # BasicTime.nullGMT AND thisTime.Period[rc.earliestResultTime] > 0 THEN {rc.earliestResultTime _ thisTime; rc.earliestResultNode _ ml.first}; ENDLOOP; IF rc.earliestResultNode = NIL THEN RETURN [FALSE]; FOR fl: MakeDo.NodeList _ from, fl.rest WHILE fl # NIL DO fromTime: BasicTime.GMT _ MakeDo.Latest[fl.first]; IF (fromTime # BasicTime.nullGMT) AND (fromTime.Period[rc.earliestResultTime] < 0) THEN { rc.lateIngredientTime _ fromTime; rc.lateIngredientNode _ fl.first; RETURN [TRUE]}; ENDLOOP; notCurrent _ FALSE; END; ExplainRose: PROC [c: MakeDo.Command, to: IO.STREAM] --MakeDo.ExplainProc-- = BEGIN rc: RoseCommand _ NARROW[MakeDo.PublicPartsOfCommand[c].foundData]; IF rc.earliestResultNode = NIL THEN to.PutRope["\t\tno result files existed yet.\n"] ELSE IF rc.lateIngredientNode = NIL THEN to.PutRope["\t\tall result files were dated later than any ingredient file.\n"] ELSE to.PutF["\t\tresult %g of %g predated ingredient %g of %g.\n", IO.rope[MakeDo.PublicPartsOfNode[rc.earliestResultNode].name], IO.time[rc.earliestResultTime], IO.rope[MakeDo.PublicPartsOfNode[rc.lateIngredientNode].name], IO.time[rc.lateIngredientTime]]; END; ModuleReferenceType: TYPE = {Directory, Open, Imports, Library}; MRKeywords: ARRAY ModuleReferenceType OF ROPE = ["Directory", "Open", "Imports", "Library"]; GotoSyntaxError: ERROR = CODE; Break: IO.BreakProc = {RETURN [SELECT char FROM IN ['a .. 'z], IN ['A .. 'Z], IN ['0 .. '9] => other, IO.SP, IO.CR, IO.TAB, IO.LF, IO.FF => sepr, ENDCASE => break]}; EnumerateModuleReferences: PROC [fromName: ROPE, to: PROC [moduleName: ROPE, type: ModuleReferenceType]] RETURNS [exists: BOOLEAN] = BEGIN NextToken: PROC RETURNS [ROPE] = { [] _ from.SkipWhitespace[]; IF from.PeekChar[] = '$ THEN { IF from.GetChar[] # '$ THEN ERROR; RETURN [IF from.PeekChar[] # '" THEN "$" ELSE from.GetRopeLiteral]; }; RETURN [from.GetTokenRope[Break].token]}; ModuleReferenceKey: PROC [r: ROPE] RETURNS [is: BOOL, mrt: ModuleReferenceType] = { FOR mrt IN ModuleReferenceType DO IF MRKeywords[mrt].Equal[s2: r, case: FALSE] THEN RETURN [TRUE, mrt]; ENDLOOP; is _ FALSE}; ParseRefs: PROC = { next: ROPE; DO still: BOOLEAN; mrt: ModuleReferenceType; [still, mrt] _ ModuleReferenceKey[next _ NextToken[]]; IF NOT still THEN EXIT; next _ EatModuleReferenceBody[mrt]; IF next.Length[] = 0 AND from.EndOf[] THEN EXIT --end of file--; IF NOT next.Equal[";"] THEN ERROR GotoSyntaxError; ENDLOOP; }; EatModuleReferenceBody: PROC [mrt: ModuleReferenceType] RETURNS [next: ROPE] = { DO next _ NextToken[]; to[next, mrt]; next _ NextToken[]; IF next.Equal[";"] THEN RETURN; IF NOT next.Equal[","] THEN ERROR GotoSyntaxError; ENDLOOP}; from: IO.STREAM _ NIL; from _ FS.StreamOpen[fileName: fromName, accessOptions: $read !FS.Error => {from _ NIL; CONTINUE}]; IF NOT (exists _ from # NIL) THEN RETURN; from _ IOClasses.CreateCommentFilterStream[from]; [] _ from.GetIndex[]; ParseRefs[!GotoSyntaxError => BEGIN SIGNAL MakeDo.Warning[IO.PutFR["Syntax error in %g; parse aborted at %g", IO.rope[fromName], IO.int[from.GetIndex[]]]]; CONTINUE END]; from.Close[]; END; MakeDo.AddFinder[[RoseFind], back]; END.