DIRECTORY BasicTime USING [earliestGMT, GMT, Period], FS USING [ComponentPositions, Error, EnumerateForNames, ExpandName, StreamOpen], IO USING [Close, EndOf, EndOfStream, Error, GetCedarTokenRope, GetLineRope, PutFR, rope, SkipWhitespace, STREAM, TokenKind], MakeDo USING [Action, ActionClass, ActionClassRep, ActionDep, AddFinder, fileClass, From, GetNode, InnerEnumerateSources, InnerGetCreated, Node, NodeList, notExistTime, PublicPartsOfAction, PublicPartsOfNode, Time], Rope USING [Cat, Concat, Equal, InlineFetch, Length, ROPE, SkipTo, Substr]; SiroccoDeps: CEDAR PROGRAM IMPORTS BasicTime, FS, IO, MakeDo, Rope ~ { Action: TYPE ~ MakeDo.Action; ActionClass: TYPE ~ MakeDo.ActionClass; ActionDep: TYPE ~ MakeDo.ActionDep; From: TYPE ~ MakeDo.From; Node: TYPE ~ MakeDo.Node; NodeList: TYPE ~ MakeDo.NodeList; ROPE: TYPE ~ Rope.ROPE; Time: TYPE ~ MakeDo.Time; CourierProgramList: TYPE ~ LIST OF CourierProgram; CourierProgram: TYPE ~ REF CourierProgramObject; CourierProgramObject: TYPE ~ RECORD [ dependsUpon: ReferencedProgramList, filename: ROPE, found: BOOL, interface: ROPE, program: ROPE, pid: ROPE, resultPrefix: ROPE, sourceNode: Node, switchFile: ROPE, switchesNode: Node, vid: ROPE ]; DependsParse: TYPE ~ { name, leftparen, pid, rightparen, version, vid }; ProgramParse: TYPE ~ { name, colon, program, pid, version, vid }; ReferencedProgramList: TYPE ~ LIST OF ReferencedProgram; ReferencedProgram: TYPE ~ REF ReferencedProgramObject; ReferencedProgramObject: TYPE ~ RECORD [ name: ROPE, pid: ROPE, valid: BOOL, vid: ROPE ]; SiroccoAction: TYPE ~ CourierProgram; COMMA: ROPE ~ ","; DEPENDS: ROPE ~ "DEPENDS"; EQUAL: ROPE ~ "="; SEMI: ROPE ~ ";"; siroccoClass: ActionClass _ NEW [MakeDo.ActionClassRep _ [ CheckConsistency: CheckConsistency, Rederive: Rederive ]]; CheckConsistency: PROC [a: Action, result: Node] RETURNS [consistent: BOOL, reason: ROPE] --MakeDo.ConsistencyChecker-- = BEGIN resultTime: Time = result.InnerGetCreated[]; resultName: ROPE = result.PublicPartsOfNode[].name; resultExists: BOOL ~ resultTime # MakeDo.notExistTime; someIngredientsExist: BOOL; missingIngredient, latestIngredientNode: Node; latestIngredientTime: Time; [someIngredientsExist, missingIngredient, latestIngredientNode, latestIngredientTime] _ FindLatestIngredient[a]; IF NOT someIngredientsExist THEN RETURN [TRUE, "no ingredients exist to indicate inconsistency"]; IF NOT resultExists THEN RETURN [FALSE, "some inputs but no outputs exist"]; IF latestIngredientTime.Period[resultTime] < 0 THEN RETURN [ FALSE, IO.PutFR[ "result %g (of %g) predates ingredient %g (of %g)", [rope[resultName]], [time[resultTime]], [rope[latestIngredientNode.PublicPartsOfNode[].name]], [time[latestIngredientTime]] ]]; RETURN [TRUE, "result dated later than any existing ingredient"]; END; FindLatestIngredient: PROC [a: Action] RETURNS [someIngredientsExist: BOOL _ FALSE, missingIngredient, latestIngredientNode: Node _ NIL, latestIngredientTime: Time _ BasicTime.earliestGMT] = { PerSource: PROC [n: Node, which: ActionDep, optional: BOOL] = { fromTime: BasicTime.GMT _ MakeDo.InnerGetCreated[n]; IF fromTime = MakeDo.notExistTime THEN {IF NOT optional THEN missingIngredient _ n} ELSE {someIngredientsExist _ TRUE; IF latestIngredientTime.Period[fromTime] > 0 THEN { latestIngredientTime _ fromTime; latestIngredientNode _ n; }; }; }; MakeDo.InnerEnumerateSources[a, data, PerSource]; RETURN}; Rederive: PROC [a: Action] RETURNS [from: From, cmd: ROPE] ~ { spec: CourierProgram _ NARROW[a.PublicPartsOfAction[].foundData]; from _ DeriveFrom[spec]; cmd _ DeriveCmd[spec]; }; Basename: PROC [in: ROPE] RETURNS [out: ROPE] ~ { parts: FS.ComponentPositions; tmp: ROPE; [tmp, parts, ] _ FS.ExpandName[in]; out _ Rope.Substr[base: tmp, start: parts.base.start, len: parts.base.length]; }; CourierBasename: PROC [in: ROPE] RETURNS [out: ROPE] ~ { i: NAT; j: NAT _ 0; length: NAT ~ Rope.Length[in]; WHILE (j # length) DO i _ j; j _ Rope.SkipTo[in, (i+1), "Pp"]; ENDLOOP; out _ Rope.Substr[base: in, start: 0, len: i]; }; DeriveCmd: PROC [spec: CourierProgram] RETURNS [cmd: ROPE] ~ { formatOne: ROPE _ IO.PutFR["%g%g%g", IO.rope["Sirocco %g;"], IO.rope["TiogaMesa %g; Sleep 1;"], IO.rope["TiogaMesa %gInit; Sleep 1;"] ]; formatTwo: ROPE _ IO.PutFR["%g%g%g%g%g", IO.rope["%g"], -- first half IO.rope["TiogaMesa %gAux; Sleep 1;"], IO.rope["TiogaMesa %gAuxImpl; Sleep 1; "], IO.rope["TiogaMesa %gClientImpl; Sleep 1; "], IO.rope["TiogaMesa %gServerImpl; Sleep 1; "] ]; cmd _ IO.PutFR[formatOne, IO.rope[Basename[spec.filename]], IO.rope[spec.interface], IO.rope[spec.interface] ]; cmd _ IO.PutFR[formatTwo, IO.rope[cmd], IO.rope[spec.interface], IO.rope[spec.interface], IO.rope[spec.interface], IO.rope[spec.interface] ]; }; DeriveFrom: PROC [spec: CourierProgram] RETURNS [from: From] ~ { from _ [mustHave: LIST[spec.sourceNode], optional: NIL]; FOR each: ReferencedProgramList _ spec.dependsUpon, each.rest WHILE (each # NIL) DO interface: ROPE ~ Rope.Cat[each.first.name, "P", each.first.pid, "V", each.first.vid]; table: ROPE ~ Rope.Cat[interface, ".Tables"]; from.mustHave _ CONS [ MakeDo.GetNode[table, MakeDo.fileClass], from.mustHave]; ENDLOOP; }; GetDependsUpon: PROC [spec: IO.STREAM] RETURNS [list: ReferencedProgramList _ NIL] ~ { ENABLE { IO.EndOfStream => { GOTO ParseError; }; IO.Error => { GOTO ParseError; }; }; shiftBox: ARRAY DependsParse OF ROPE _ ALL[NIL]; skip: INT; token: ROPE; tokenKind: IO.TokenKind; list _ CONS [NEW [ReferencedProgramObject], list]; DO [tokenKind, token, skip] _ IO.GetCedarTokenRope[spec]; SELECT tokenKind FROM tokenID => { IF ( Rope.Equal[token, DEPENDS] ) THEN { EXIT; }; }; tokenSINGLE, tokenDECIMAL, tokenOCTAL, tokenHEX, tokenREAL, tokenROPE, tokenCHAR, tokenATOM, tokenDOUBLE, tokenCOMMENT => { NULL; }; tokenERROR, tokenEOF => { RETURN [NIL]; }; ENDCASE; ENDLOOP; DO [tokenKind, token, skip] _ IO.GetCedarTokenRope[spec]; SELECT tokenKind FROM tokenID, tokenDECIMAL, tokenSINGLE => { IF ( Rope.Equal[token, COMMA] ) THEN { list.first.valid _ TRUE; list.first.name _ shiftBox[name]; list.first.pid _ shiftBox[pid]; list.first.vid _ shiftBox[vid]; list _ CONS [NEW [ReferencedProgramObject], list]; }; IF ( Rope.Equal[token, SEMI] ) THEN { list.first.valid _ TRUE; list.first.name _ shiftBox[name]; list.first.pid _ shiftBox[pid]; list.first.vid _ shiftBox[vid]; EXIT; }; FOR i: DependsParse IN [name .. version] DO shiftBox[i] _ shiftBox[SUCC[i]]; ENDLOOP; shiftBox[vid] _ token; }; tokenOCTAL, tokenHEX, tokenREAL, tokenROPE, tokenCHAR, tokenATOM, tokenDOUBLE, tokenCOMMENT => { NULL; }; tokenERROR, tokenEOF => { list.first.valid _ FALSE; }; ENDCASE; ENDLOOP; IF (list.first.valid = FALSE) THEN list _ list.rest; RETURN [list]; EXITS ParseError => { RETURN [NIL]; }; }; GetSwitches: PROC [resultPrefix: ROPE] RETURNS [switches: ROPE] ~ { ss: IO.STREAM _ NIL; ss _ FS.StreamOpen[Rope.Cat[resultPrefix, ".SiroccoSwitches"] ! FS.Error => CONTINUE ]; IF (ss = NIL) THEN RETURN [NIL]; [] _ ss.SkipWhitespace[]; IF (ss.EndOf[]) THEN RETURN [NIL]; switches _ ss.GetLineRope[]; IO.Close[ss]; }; GuessForSpec: PROC [in: ROPE] RETURNS [list: CourierProgramList _ NIL] ~ { ParseEachSpec: PROC [fullFName: ROPE] RETURNS [continue: BOOL _ TRUE] ~ { ENABLE { IO.EndOfStream => { GOTO ParseError; }; IO.Error => { GOTO ParseError; }; }; shiftBox: ARRAY ProgramParse OF ROPE _ ALL[NIL]; skip: INT; spec: IO.STREAM _ NIL; token: ROPE; tokenKind: IO.TokenKind; spec _ FS.StreamOpen[fullFName ! FS.Error => CONTINUE ]; IF (spec = NIL) THEN RETURN [TRUE]; list _ CONS [NEW [CourierProgramObject], list]; DO [tokenKind, token, skip] _ IO.GetCedarTokenRope[spec]; SELECT tokenKind FROM tokenID, tokenDECIMAL, tokenSINGLE => { IF ( Rope.Equal[token, EQUAL] ) THEN { list.first.found _ TRUE; EXIT; }; FOR i: ProgramParse IN [name .. version] DO shiftBox[i] _ shiftBox[SUCC[i]]; ENDLOOP; shiftBox[vid] _ token; }; tokenOCTAL, tokenHEX, tokenREAL, tokenROPE, tokenCHAR, tokenATOM, tokenDOUBLE, tokenCOMMENT => { NULL; }; tokenERROR, tokenEOF => { list.first.found _ FALSE; }; ENDCASE; ENDLOOP; list.first.filename _ fullFName; list.first.program _ shiftBox[name]; list.first.pid _ shiftBox[pid]; list.first.vid _ shiftBox[vid]; list.first.interface _ Rope.Cat[list.first.program, "P", list.first.pid, "V", list.first.vid]; IF (list.first.found = TRUE) THEN list.first.dependsUpon _ GetDependsUpon[spec]; IO.Close[spec]; RETURN [TRUE]; EXITS ParseError => { list _ list.rest; RETURN [TRUE]; }; }; FS.EnumerateForNames[in, ParseEachSpec]; }; Heuristic: PROC [interfaceName: ROPE] RETURNS [specDetails: CourierProgram _ NIL] ~ { FOR j: INT DECREASING IN (0 .. interfaceName.Length[]) DO SELECT interfaceName.InlineFetch[j] FROM IN ['0 .. '9], 'V => NULL; 'P => { filename: ROPE ~ interfaceName.Substr[len: j].Concat["*.cr"]; list: CourierProgramList ~ GuessForSpec[filename]; FOR each: CourierProgramList _ list, each.rest WHILE (each # NIL) DO specDetails _ each.first; IF specDetails.interface.Equal[interfaceName, FALSE] THEN RETURN; ENDLOOP; specDetails _ NIL; }; ENDCASE => EXIT; ENDLOOP; RETURN; }; SiroccoFind: PROC [resultName: ROPE, finderData: REF ANY] RETURNS [found: BOOLEAN, sought: Node, makes, cmdFrom: NodeList, from: From, cmd: ROPE, class: ActionClass, foundData: REF ANY] ~ { discoveredSuffix: ROPE; programLength: INT _ 0--only to prevent compiler warnings about uninitialized--; interfaceName: ROPE; spec: CourierProgram; resultCP: FS.ComponentPositions; resultFull: ROPE; resultShort: ROPE; basenameLength: INT; specDetails: CourierProgram; EndsIn: PROC [word: ROPE, suffix: ROPE] RETURNS [ans: BOOL] ~ { suffixLength: INT ~ suffix.Length[]; wordLength: INT ~ word.Length[]; tail: ROPE; IF (suffixLength > wordLength) THEN RETURN [FALSE]; tail _ Rope.Substr[base: word, start: (wordLength - suffixLength), len: suffixLength]; IF (ans _ Rope.Equal[s1: suffix, s2: tail, case: FALSE]) THEN { programLength _ (wordLength - suffixLength); discoveredSuffix _ suffix; }; }; Tail: PROC [suffix: ROPE] RETURNS [node: Node] ~ { node _ MakeDo.GetNode[Rope.Cat[specDetails.resultPrefix, suffix], MakeDo.fileClass]; IF (Rope.Equal[suffix, discoveredSuffix]) THEN sought _ node; }; sought _ NIL; found _ TRUE; [resultFull, resultCP, ] _ FS.ExpandName[resultName ! FS.Error => {found _ FALSE; CONTINUE} ]; IF (NOT found) THEN RETURN; basenameLength _ (resultCP.ext.start + resultCP.ext.length) - resultCP.base.start; resultShort _ Rope.Substr[base: resultFull, start: resultCP.base.start, len: basenameLength]; found _ EndsIn[resultShort, ".Tables"] OR EndsIn[resultShort, ".Mesa"] OR EndsIn[resultShort, "Init.Mesa"] OR EndsIn[resultShort, "Aux.Mesa"] OR EndsIn[resultShort, "AuxImpl.Mesa"] OR EndsIn[resultShort, "ClientImpl.Mesa"] OR EndsIn[resultShort, "ServerImpl.Mesa"]; IF (NOT found) THEN RETURN; interfaceName _ Rope.Substr[base: resultShort, start: 0, len: programLength]; specDetails _ Heuristic[interfaceName]; IF (specDetails = NIL) THEN { found _ FALSE; RETURN; }; specDetails.resultPrefix _ Rope.Substr[base: resultFull, start: 0, len: resultCP.base.start]; specDetails.resultPrefix _ Rope.Concat[specDetails.resultPrefix, specDetails.interface]; specDetails.switchFile _ Rope.Cat[specDetails.resultPrefix, ".SiroccoSwitches"]; cmdFrom _ LIST[ specDetails.sourceNode _ MakeDo.GetNode[specDetails.filename, MakeDo.fileClass], specDetails.switchesNode _ MakeDo.GetNode[specDetails.switchFile, MakeDo.fileClass] ]; foundData _ spec _ specDetails; cmd _ DeriveCmd[spec]; makes _ LIST[ Tail[".Tables"], Tail[".Mesa"], Tail["Init.Mesa"], Tail["Aux.Mesa"], Tail["AuxImpl.Mesa"], Tail["ClientImpl.Mesa"], Tail["ServerImpl.Mesa"] ]; IF (sought = NIL) THEN ERROR; from _ DeriveFrom[spec]; class _ siroccoClass; }; MakeDo.AddFinder[["Sirocco", SiroccoFind], back]; }. €SiroccoDeps.Mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Bill Jackson (bj) September 18, 1986 10:09:49 am PDT Mike Spreitzer July 29, 1986 4:44:51 pm PDT Last tweaked by Mike Spreitzer on April 26, 1990 9:18:13 am PDT Copied Types Types Constants Global State Procs Worker Procs IO.rope[GetSwitches[spec.resultPrefix]], Global State (EndsIn side effects) Κμ˜code™Kšœ Οmœ1™Kšœžœ$˜AK˜K˜K˜K˜K˜——šœ ™ K˜š Ÿœžœžœžœžœ˜1Kšœžœ˜Kšœžœ˜ K˜Kšœžœ˜#KšœN˜NK˜K˜—š Ÿœžœžœžœžœ˜8Kšœžœ˜Kšœžœ˜ Kšœžœ˜K˜šžœž˜Kšœ˜Kšœ!˜!Kšžœ˜K˜—Kšœ.˜.K˜K˜—šŸ œžœžœžœ˜>šΟb œžœžœ˜$Kšžœ˜Kšžœ ˜"Kšžœ#˜%Kšœ˜—š‘ œžœžœ˜(Kšžœ   ˜Kšžœ#˜%Kšžœ(˜*Kšžœ+˜-Kšžœ*˜,Kšœ˜K˜—šœžœ‘ œ˜Kšžœ&™(Kšžœ˜!Kšžœ˜Kšžœ˜Kšœ˜—šœžœ‘ œ˜Kšžœ ˜ Kšžœ˜Kšžœ˜Kšžœ˜Kšžœ˜Kšœ˜—K˜K˜—šŸ œžœžœ˜@Kšœžœžœ˜8K˜Kšžœ:˜=šžœ žœž˜Kšœ žœG˜VKšœžœ"˜-Kšœžœ;˜OKšžœ˜—Kšœ˜K˜—š Ÿœžœžœžœžœ žœ˜Všžœ˜šžœ˜Kšžœ ˜Kšœ˜—šžœ ˜ Kšžœ ˜Kšœ˜—K˜K˜—Kš œ žœžœžœžœžœ˜0Kšœžœ˜ Kšœžœ˜ Kšœ žœ ˜K˜Kšœžœžœ"˜2K˜šž˜Kšœžœ˜6šžœ ž˜šœ ˜ šžœžœžœ˜(Kšžœ˜Kšœ˜—Kšœ˜—K˜Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ šœ˜Kšžœ˜Kšœ˜—K˜Kšœ ˜ šœ ˜ Kšžœžœ˜ Kšœ˜K˜—Kšžœ˜—Kšžœ˜K˜—šž˜Kšœžœ˜6šžœ ž˜Kšœ˜Kšœ ˜ šœ˜šžœžœžœ˜&Kšœžœ˜Kšœ!˜!Kšœ˜Kšœ˜Kšœžœžœ"˜2Kšœ˜K˜—šžœžœžœ˜%Kšœžœ˜Kšœ!˜!Kšœ˜Kšœ˜Kšžœ˜Kšœ˜K˜—šžœžœžœ˜,Kšœžœ˜ Kšžœ˜K˜—Kšœ˜Kšœ˜—K˜Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ šœ˜Kšžœ˜Kšœ˜—K˜Kšœ ˜ šœ ˜ Kšœžœ˜Kšœ˜K˜—Kšžœ˜—Kšžœ˜K˜Kšžœžœžœ˜4Kšžœ˜—šž˜Kšœžœžœ˜ —Kšœ˜K˜—š Ÿ œžœžœžœ žœ˜CKšœžœžœžœ˜K˜šœžœ6˜=Kšœžœ ž˜Kšœ˜K˜—Kš žœžœžœžœžœ˜ K˜Kšžœžœžœžœ˜"Kšœ˜Kšžœ ˜ K˜K˜—š Ÿ œžœžœžœžœ˜JK˜š Ÿ œžœ žœžœ žœžœ˜Išžœ˜šžœ˜Kšžœ ˜Kšœ˜—šžœ ˜ Kšžœ ˜Kšœ˜—K˜K˜—Kš œ žœžœžœžœžœ˜0Kšœžœ˜ Kšœžœžœžœ˜Kšœžœ˜ Kšœ žœ ˜K˜šœžœ˜Kšœžœ ž˜Kšœ˜K˜—Kš žœ žœžœžœžœ˜#K˜Kšœžœžœ˜/šž˜Kšœžœ˜6šžœ ž˜Kšœ˜Kšœ ˜ šœ˜šžœžœžœ˜&Kšœžœ˜Kšžœ˜Kšœ˜K˜—šžœžœžœ˜,Kšœžœ˜ Kšžœ˜K˜—Kšœ˜Kšœ˜—K˜Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ šœ˜Kšžœ˜Kšœ˜—K˜Kšœ ˜ šœ ˜ Kšœžœ˜Kšœ˜K˜—Kšžœ˜—Kšžœ˜—K˜Kšœ ˜ Kšœ$˜$Kšœ˜Kšœ˜Kšœ^˜^K˜Kšžœžœžœ/˜PK˜Kšžœ ˜Kšžœžœ˜—šž˜šœ˜Kšœ˜Kšžœžœ˜Kšœ˜—Kšœ˜K˜—Kšžœ&˜(Kšœ˜K˜—š Ÿ œžœžœžœ žœ˜Uš žœžœž œžœž˜9šžœž˜(Kšžœžœ˜šœ˜Kšœ žœ/˜=Kšœ2˜2šžœ,žœ žœž˜DKšœ˜Kšžœ,žœžœžœ˜AKšžœ˜—Kšœžœ˜Kšœ˜—Kšžœžœ˜—Kšžœ˜—Kšžœ˜Kšœ˜K˜—šŸ œžœžœžœžœžœ žœ;žœ!žœžœ˜½K˜šœ"™"Kšœžœ˜Kšœžœ 9œ˜P—K˜Kšœžœ˜Kšœ˜Kšœ žœ˜ Kšœ žœ˜Kšœ žœ˜Kšœžœ˜Kšœ˜K˜š Ÿœžœžœ žœžœžœ˜?Kšœžœ˜$Kšœ žœ˜ Kšœžœ˜ K˜Kšžœžœžœžœ˜3KšœV˜Všžœ/žœžœ˜?Kš‘œ˜,Kš‘œ˜Kšœ˜—Kšœ˜K˜—šŸœžœ žœžœ˜2KšœT˜TKšžœ‘œžœ‘ œ˜=Kšœ˜K˜—Kšœ žœ˜ šœžœ˜ K˜—šœžœ˜3Kšœžœžœžœ˜'Kšœ˜K˜—šžœžœžœžœ˜K˜—KšœR˜Ršœ]˜]K˜—šœ&˜&Kšžœ˜Kšžœ!˜#Kšžœ ˜"Kšžœ$˜&Kšžœ'˜)Kšžœ(˜*K˜—šžœžœžœžœ˜K˜—KšœM˜MK˜Kšœ‘ œ˜'K˜šžœžœžœ˜Kšœžœ˜Kšžœ˜K˜—K˜Kšœ]˜]šœX˜XK˜—KšœP˜PK˜šœ žœ˜KšœP˜PKšœS˜SK˜K˜—šœ˜K˜—˜K˜—šœžœ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—Kšžœ žœžœžœ˜K˜K˜Kšœ˜Kšœ˜——K˜Kšœ1˜1K˜Kšœ˜K˜—…—.Ar