DIRECTORY Atom, Basics, BasicTime, Commander, CommanderOps, FileNames, FS, IO, MakeDo, MakeDoGrossHack, MakeDoParsers, MakeDoPorting, MakeDoPrivate, MobDefs, Mobery, MobListerUtils, PFS, PFSNames, RefTab, Rope, SimpleFeedback, UserProfile; CcDeps: CEDAR MONITOR IMPORTS Atom, Basics, BasicTime, Commander, CommanderOps, FileNames, FS, IO, MakeDo, MakeDoParsers, MakeDoPorting, MakeDoPrivate, Mobery, MobListerUtils, PFS, PFSNames, RefTab, Rope, SimpleFeedback, UserProfile EXPORTS MakeDoGrossHack = BEGIN OPEN MakeDo, MDPs:MakeDoParsers; ShouldNotHappen: ERROR = CODE; ROPE: TYPE = Rope.ROPE; StampTableRef: TYPE = REF StampTableRep; StampTableRep: TYPE = RECORD [ created: BasicTime.GMT, stampTable: Mobery.StampTable, depInfoValid: BOOL ¬ FALSE, stampTableValid: BOOL ¬ FALSE]; SourceData: TYPE = REF SourceDataRep; SourceDataRep: TYPE = RECORD [ switchesPath: PFS.PATH, --absolute oName: ROPE, --absolute, unspecified format baseName: ROPE, --working directory in FS format subName: ROPE, --output subdirectory (eg, sun4/); may be NIL shortName: ROPE, --the part after last directory delim and before .c2c.o sourceType: MDPs.SourceType ¬ Unknown, genesis: Genesis, supports: RefTab.Ref, --node => $T mesaNode, cedarNode, configNode, switchesNode, oNode, cNode: Node ¬ NIL, stampTable: Mobery.StampTable ¬ NIL, oCreateTime: BasicTime.GMT, oReadable: BOOL, useAltSwitches: BOOL, --GROSS HACK! supportsInvalid: BOOL ¬ FALSE, cmd: ROPE ¬ NIL ]; Genesis: TYPE ~ {C, Cedar, Scheme}; installDir: ROPE ~ FileNames.CurrentWorkingDirectory[]; installed, badInstall: BOOL ¬ FALSE; dolog: BOOL ¬ FALSE; myRouterName: ATOM ~ Atom.MakeAtom["MakeDo.CcDeps"]; findAltSwitches: BOOL ¬ FALSE; c2cTail: ROPE = ".c2c"; sxTail: ROPE = ".sx"; c2coTail: ROPE = Rope.Concat[c2cTail, ".o"]; c2coTailLength: INT = c2coTail.Length[]; sxoTail: ROPE = Rope.Concat[sxTail, ".o"]; sxoTailLength: INT = sxoTail.Length[]; c2ccTail: ROPE = Rope.Concat[c2cTail, ".c"]; sxcTail: ROPE = Rope.Concat[sxTail, ".c"]; mobExt: ROPE = "mob"; mobTail: ROPE = Rope.Concat[".", mobExt]; mesaTail: ROPE = ".mesa"; cedarTail: ROPE = ".cedar"; configTail: ROPE = ".config"; schemeTail: ROPE = ".scheme"; clusterTail: ROPE = ".cluster"; switchesTail: ROPE = ".switches"; libTail: ROPE = ".a"; libTailLen: INT ~ libTail.Length[]; oTail: ROPE = ".o"; oTailLen: INT ~ oTail.Length[]; cTail: ROPE = ".c"; DirAndClass: TYPE = RECORD [ dir: ROPE, -- the directory name -- class: ROPE, -- the corresponding machine class -- switches: ROPE, -- the default switches -- altSwitches: ROPE ¬ NIL --the alternate switches => GROSS HACK ]; ClassDir: TYPE ~ RECORD [ dir: ROPE, switches: ROPE]; UserClass: TYPE ~ RECORD[ class: ROPE, classDirs: LIST OF ClassDir]; userClassList: LIST OF UserClass; currentClass: ROPE _ NIL; currentClassDirs: LIST OF ClassDir _ NIL; cg: ROPE ~ "-c -g"; cO: ROPE ~ "-c -O"; cgf: ROPE ~ "-c -g -fsingle"; cOf: ROPE ~ "-c -O -fsingle"; cO2f: ROPE ~ "-c -O2 -fsingle"; cO3f: ROPE ~ "-c -O3 -fsingle"; knownLocalDirs: LIST OF DirAndClass ¬ LIST[ DirAndClass[dir: "sun3", class: "sun3", switches: cgf], DirAndClass[dir: "sun4-debug", class: "sun4", switches: cgf], DirAndClass[dir: "sun4", class: "sun4", switches: cO2f, altSwitches: cgf], DirAndClass[dir: "sun4-o3", class: "sun4", switches: cO3f, altSwitches: cO2f], DirAndClass[dir: "sun4o3", class: "sun4", switches: cO3f, altSwitches: cO2f], DirAndClass[dir: "29k", class: "amd29000", switches: cgf], DirAndClass[dir: "sun4-profiled", class: "sun4", switches: "-c -p -fsingle"], DirAndClass[dir: "sun4-gprof", class: "sparc", switches: "-c -pg -fsingle"], DirAndClass[dir: "rs6000", class: "rs6000", switches: cgf], DirAndClass[dir: "rs6000o", class: "rs6000", switches: cOf], DirAndClass[dir: "rs6000-o", class: "rs6000", switches: cOf], DirAndClass[dir: "mipsl", class: "mipsl", switches: cg], DirAndClass[dir: "mipsl-o", class: "mipsl", switches: cO], DirAndClass[dir: "mips", class: "mips", switches: cg], DirAndClass[dir: "mips-o", class: "mips", switches: cO] ]; -- if in these directories, we issue this -mach -- CcClass: ActionClass ¬ NEW [ActionClassRep ¬ [ CheckConsistency: CheckConsistency, Rederive: RederiveSource, ClearCaches: ClearCaches ]]; ClearCaches: PROC [ac: ActionClass] ~ { MDPs.FlushCache[]; installed ¬ badInstall ¬ FALSE; }; SetOLevel: PUBLIC PROC [high: BOOL] ~ {findAltSwitches ¬ NOT high}; SourceFind: PROC [resultName: ROPE, finderData: REF ANY] RETURNS [found: BOOLEAN, sought: Node, makes, cmdFrom: NodeList, from: From, cmd: ROPE, class: ActionClass, foundData: REF ANY] -- FinderProc -- ~ { shortName: ROPE; -- the part after last directory delim and before .c2c.o middleName: ROPE; --either .c2c, .sx, or null subName: ROPE ¬ NIL; --output subdirectory (eg, sun4/); may be NIL localDir: PFS.PATH; --output subdirectory (eg, sun4/); may be null baseDir: PFS.PATH; --full expanded name, up to, but not including, the sun3 directory part baseName, oName, cName, switchesName: ROPE; oExpanded: PFS.PATH; oSteps: INTEGER; oNode, cNode: Node; genesis: Genesis; md: SourceData; resNameLen: INT ~ resultName.Length[]; found ¬ NOT badInstall; IF NOT found THEN RETURN; found ¬ resNameLen > oTailLen AND resultName.EqualSubstrs[start1: resNameLen-oTailLen, s2: oTail, case: FALSE]; IF NOT found THEN RETURN; IF NOT installed THEN InstallMe[]; found ¬ NOT badInstall; IF NOT found THEN RETURN; oExpanded ¬ PFS.AbsoluteName[PFS.PathFromRope[resultName !PFS.Error => {found ¬ FALSE; CONTINUE}]]; IF NOT found THEN RETURN; oSteps ¬ oExpanded.ComponentCount[]; IF resNameLen >= c2coTailLength AND resultName.EqualSubstrs[start1: resNameLen - c2coTailLength, s2: c2coTail, case: FALSE] THEN {genesis ¬ Cedar; middleName ¬ c2cTail} ELSE IF resNameLen >= sxoTailLength AND resultName.EqualSubstrs[start1: resNameLen - sxoTailLength, s2: sxoTail, case: FALSE] THEN {genesis ¬ Scheme; middleName ¬ sxTail} ELSE {genesis ¬ C; middleName ¬ NIL}; IF oSteps > 1 AND genesis#Scheme THEN { localDir ¬ oExpanded.SubName[oSteps-2, 1, FALSE, TRUE]; subName ¬ PFS.RopeFromPath[localDir]; IF RemoteMachClassAndSwitches[subName, knownLocalDirs, findAltSwitches].mach = NIL THEN {localDir ¬ oExpanded.SubName[oSteps-2, 0]; subName ¬ NIL}; } ELSE localDir ¬ oExpanded.SubName[0, 0]; baseDir ¬ oExpanded.SubName[0, oSteps-1-localDir.ComponentCount[], TRUE, TRUE]; {shortComp: PFSNames.Component ¬ oExpanded.ShortName[]; shortComp.name.len ¬ shortComp.name.len - middleName.Length[] - oTailLen; shortName ¬ shortComp.ComponentRope[]}; {bpn: ROPE ~ PFS.RopeFromPath[baseDir]; oName ¬ bpn.Cat[subName, shortName, middleName, oTail]; baseName ¬ FS.ExpandName[bpn].fullFName}; cName ¬ baseName.Cat[shortName, middleName, cTail]; switchesName ¬ oName.Concat[switchesTail]; oNode ¬ GetNode[oName, fileClass]; cNode ¬ GetNode[cName, fileClass]; foundData ¬ md ¬ NEW [SourceDataRep ¬ [ switchesPath: PFS.PathFromRope[switchesName], oName: oName, baseName: baseName, subName: subName, shortName: shortName, genesis: genesis, supports: RefTab.Create[], switchesNode: GetNode[switchesName, fileClass], oNode: oNode, cNode: cNode, oReadable: genesis#Cedar, oCreateTime: MakeDo.notExistTime, useAltSwitches: findAltSwitches ]]; SELECT genesis FROM C => cmdFrom ¬ LIST[md.cNode, md.switchesNode]; Cedar => { md.mesaNode ¬ GetNode[Rope.Cat[baseName, shortName, mesaTail], fileClass]; md.cedarNode ¬ GetNode[Rope.Cat[baseName, shortName, cedarTail], fileClass]; md.configNode ¬ GetNode[Rope.Cat[baseName, shortName, configTail], fileClass]; cmdFrom ¬ LIST[md.cedarNode, md.mesaNode, md.configNode, md.switchesNode]}; Scheme => { md.mesaNode ¬ GetNode[Rope.Cat[baseName, shortName, schemeTail], fileClass]; md.configNode ¬ GetNode[Rope.Cat[baseName, shortName, clusterTail], fileClass]; cmdFrom ¬ LIST[md.mesaNode, md.configNode]}; ENDCASE => ERROR; sought ¬ md.oNode; class ¬ CcClass; [from, cmd] ¬ RederiveWork[md]; makes ¬ LIST[md.oNode]; RETURN}; GetSwitches: PROC [sp: PFS.PATH, defaultMsw: ROPE] RETURNS [switches: ROPE ¬ NIL] = { ss: IO.STREAM ¬ NIL; ss ¬ PFS.StreamOpen[sp !PFS.Error => CONTINUE]; IF ss # NIL THEN { [] ¬ ss.SkipWhitespace[]; IF NOT ss.EndOf[] THEN switches ¬ IO.GetLineRope[ss]; ss.Close[]}; IF switches.Length = 0 THEN switches ¬ IO.PutFR1["-mSw \"%q\"", [rope[defaultMsw]] ] ELSE IF switches.Fetch[0] = '; THEN switches ¬ IO.PutFR["-mSw \"%q\" %g", [rope[defaultMsw]], [rope[switches.Substr[1]]] ] ELSE switches ¬ IO.PutFR1["-mSw \"%q\"", [rope[switches]] ]; RETURN}; SupportIsLoaded: PROC [] RETURNS [BOOL] ~ { moberies, moblisteries, pfs: BOOL; moberies ¬ Basics.IsBound[LOOPHOLE[Mobery.ReadStampTable]] AND Basics.IsBound[LOOPHOLE[Mobery.StampTableSubset]]; moblisteries ¬ Basics.IsBound[LOOPHOLE[MobListerUtils.PrintVersion]]; pfs ¬ Basics.IsBound[LOOPHOLE[PFS.PathFromRope]] AND Basics.IsBound[LOOPHOLE[PFS.AbsoluteName]]; RETURN [moberies AND moblisteries AND pfs]; }; InstallMe: PROC ~ { foundFile, failed: BOOL; IF SupportIsLoaded[] THEN { installed ¬ TRUE; RETURN; }; [foundFile, failed] ¬ MakeDoPrivate.MDInstall[installDir, "CcDepsSupport"]; badInstall ¬ failed OR NOT foundFile; installed ¬ TRUE; IF NOT foundFile THEN Warning[Rope.Cat["Couldn't install CcDeps support because couldn't find ", installDir, "CcDepsSupport.Install (see ", MakeDoPorting.logPath, "CcDepsSupport.InstallLog); proceeding without knowledge of Cc"]] ELSE IF failed THEN Warning[Rope.Cat["Couldn't install CcDeps support because of error in install file (", installDir, "CcDepsSupport.Install) (see ", MakeDoPorting.logPath, "CcDepsSupport.InstallLog); proceeding without knowledge of Cc"]]; RETURN}; CheckConsistency: PROC [a: Action, result: Node] RETURNS [consistent: BOOL, reason: ROPE] --ConsistencyChecker-- = BEGIN md: SourceData = NARROW[a.PublicPartsOfAction[].foundData]; switchesCreate: BasicTime.GMT = InnerGetCreated[md.switchesNode]; curCTime: Time = InnerGetCreated[md.cNode] ; -- Creation time of the C node -- resultExists: BOOL; supportFound: BOOL ¬ FALSE; CheckSupport: PROC [key, val: REF ANY] RETURNS [stop: BOOL ¬ FALSE] --RefTab.EachPairAction-- ~ { sn: Node = MakeDo.NarrowToNode[key]; thisTime: Time = InnerGetCreated[sn]; thisName: ROPE ~ sn.PublicPartsOfNode[].name; thisIsLib: BOOL ~ IsLibName[thisName]; thisStampTable: Mobery.StampTable; IF thisTime = MakeDo.notExistTime THEN RETURN [FALSE]; supportFound ¬ TRUE; IF NOT resultExists THEN RETURN [supportFound]; IF BasicTime.Period[thisTime, md.oCreateTime] < 0 THEN { consistent ¬ FALSE; reason ¬ IO.PutFR[".o file created at %g but %g was created at %g", [time[md.oCreateTime]], [rope[thisName]], [time[thisTime]] ]; RETURN [TRUE]; }; IF thisIsLib OR md.genesis#Cedar THEN RETURN [FALSE]; }; Log["check consistency for %g\n", IO.rope[md.oName]]; UpdateSupport[md]; resultExists ¬ md.oCreateTime # MakeDo.notExistTime; SELECT md.sourceType FROM Mesa, Config, PlainC, Scheme, Cluster => NULL; Unknown => RETURN [TRUE, "No source is known for this result"]; ENDCASE => ERROR ShouldNotHappen; IF resultExists AND NOT md.oReadable THEN RETURN [FALSE, ".o file not readable"]; IF switchesCreate # MakeDo.notExistTime THEN { supportFound ¬ TRUE; IF resultExists AND BasicTime.Period[md.oCreateTime, switchesCreate] > 0 THEN RETURN [FALSE, "switches file created later than result"]}; consistent ¬ TRUE; reason ¬ "all version stamps match"; [] ¬ md.supports.Pairs[CheckSupport]; IF NOT supportFound THEN RETURN [TRUE, "no inputs exist to indicate inconsistency"]; IF NOT resultExists THEN RETURN [FALSE, "some inputs but no result exists"]; END; UpdateSupport: PROC [md: SourceData] = { oldO: Time = md.oCreateTime; length: INT; [md.oCreateTime, length] ¬ InnerGetInfo[md.oNode]; IF length=0 THEN md.oCreateTime ¬ MakeDo.notExistTime; IF md.oCreateTime = MakeDo.notExistTime THEN RETURN; IF oldO = md.oCreateTime AND NOT md.supportsInvalid THEN RETURN; IF md.genesis=Cedar THEN { md.stampTable ¬ CurStampTab[node: md.oNode]; md.oReadable ¬ md.stampTable # NIL; }; md.supportsInvalid ¬ FALSE; }; CurStampTab: ENTRY PROC [node: Node] RETURNS [stampTable: Mobery.StampTable] ~ { ENABLE UNWIND => {}; sr: StampTableRef ¬ NARROW[node.GetProp[$StampTable]]; created: BasicTime.GMT ¬ InnerGetCreated[node]; fileName: ROPE ~ node.PublicPartsOfNode[].name; GetIt: PROC [] RETURNS [stampTable: Mobery.StampTable] ~ INLINE { Log["ReadStampTable for %g\n", IO.rope[fileName]]; stampTable ¬ Mobery.ReadStampTable[fileName !FS.Error => {stampTable ¬ NIL; CONTINUE}]; Log[".. %g\n", IO.rope[IF stampTable = NIL THEN "F" ELSE "S"]]; RETURN [stampTable]; }; IF sr = NIL THEN node.SetProp[ prop: $StampTable, val: sr ¬ NEW [StampTableRep ¬ [ created: notExistTime, stampTable: NIL]] ]; IF created = MakeDo.notExistTime THEN { sr.stampTable ¬ NIL; sr.stampTableValid ¬ sr.depInfoValid ¬ TRUE; RETURN [stampTable: sr.stampTable]; -- cached value -- }; IF created = sr.created THEN { IF NOT sr.stampTableValid THEN { sr.stampTableValid ¬ TRUE; sr.stampTable ¬ GetIt[]; }; RETURN [stampTable: sr.stampTable]; -- cached value -- }; sr.created ¬ created; sr.stampTableValid ¬ TRUE; sr.depInfoValid ¬ FALSE; sr.stampTable ¬ GetIt[]; stampTable ¬ sr.stampTable; RETURN [stampTable: stampTable] }; RederiveSource: PROC [a: Action] RETURNS [from: From, cmd: ROPE] --RederiveProc-- = { md: SourceData ~ NARROW[a.PublicPartsOfAction[].foundData]; RETURN RederiveWork[md]}; RemoteMachClassAndSwitches: PROC [subName: ROPE, known: LIST OF DirAndClass, useAlt: BOOL] RETURNS [mach: ROPE, switches: ROPE] ~ { dir: ROPE; IF subName = NIL THEN RETURN [NIL, NIL]; dir ¬ Rope.Substr[subName, 0, subName.Length[]-1]; IF currentClass # NIL THEN { FOR uList: LIST OF ClassDir ¬ currentClassDirs, uList.rest WHILE uList # NIL DO this: ClassDir ~ uList.first; IF Rope.Equal[this.dir, dir, FALSE] THEN RETURN[mach: currentClass, switches: this.switches]; ENDLOOP; RETURN[NIL, NIL]; }; FOR list: LIST OF DirAndClass ¬ known, list.rest WHILE list # NIL DO pair: DirAndClass = list.first; IF Rope.Equal[pair.dir, dir, FALSE] THEN RETURN [mach: pair.class, switches: IF useAlt AND pair.altSwitches#NIL THEN pair.altSwitches ELSE pair.switches]; ENDLOOP; RETURN [NIL, NIL] }; RederiveWork: PROC [md: SourceData] RETURNS [from: From, cmd: ROPE] ~ { NoteDep: PROC [fileName: ROPE] ~ { n: Node; p: PFS.PATH; fn: ROPE; p ¬ PFS.PathFromRope[fileName !PFS.Error => {MakeDo.Warning[IO.PutFLR["PFS.Error[%g, %g] while processing dependency on %g of %g", LIST[[atom[error.code]], [rope[error.explanation]], [rope[fileName]], [rope[md.oName]]] ]]; GOTO Skip}]; p ¬ PFS.AbsoluteName[p]; fn ¬ PFS.RopeFromPath[p]; n ¬ GetNode[fn, fileClass]; [] ¬ md.supports.Insert[n, $T]; from.mustHave ¬ CONS[n, from.mustHave]; RETURN; EXITS Skip => NULL}; userSwitches: ROPE; mimosaSwitches: ROPE; dirSw: ROPE = IF md.subName # NIL THEN Rope.Concat[" -dir ", md.subName] ELSE NIL; machClass: ROPE; uSwitches: ROPE; midSwitches: ROPE; machClassSw: ROPE; [mach: machClass, switches: uSwitches] ¬ RemoteMachClassAndSwitches[md.subName, knownLocalDirs, md.useAltSwitches]; machClassSw ¬ IF machClass # NIL THEN Rope.Concat[" -class ", machClass] ELSE NIL; md.supports.Erase[]; SELECT md.genesis FROM Cedar => { from ¬ [mustHave: LIST[md.cNode], optional: LIST[md.switchesNode]]; IF NOT md.supports.Insert[md.cNode, $T] THEN ERROR; IF EnumerateDependancies[md.mesaNode, Mesa, NIL, md, NIL] OR EnumerateDependancies[md.cedarNode, Mesa, NIL, md, NIL] OR EnumerateDependancies[md.configNode, Config, NoteDep, md, md.subName] THEN NULL}; C => { from ¬ [mustHave: LIST[md.cNode], optional: LIST[md.switchesNode]]; IF NOT md.supports.Insert[md.cNode, $T] THEN ERROR; [] ¬ EnumerateDependancies[md.cNode, PlainC, NoteDep, md, NIL]}; Scheme => { from ¬ [NIL, NIL]; IF EnumerateDependancies[md.mesaNode, Scheme, NIL, md, NIL] OR EnumerateDependancies[md.configNode, Cluster, NoteDep, md, NIL] THEN NULL; {srcNode: Node ~ SELECT md.sourceType FROM Scheme => md.mesaNode, Cluster => md.configNode, Unknown => NIL, ENDCASE => ERROR; IF srcNode#NIL THEN { IF NOT md.supports.Insert[srcNode, $T] THEN ERROR; from.mustHave ¬ CONS[srcNode, from.mustHave]}; }}; ENDCASE => ERROR; md.supportsInvalid ¬ TRUE; UpdateSupport[md]; midSwitches ¬ GetSwitches[md.switchesPath, uSwitches]; SELECT md.sourceType FROM PlainC => { cmd ¬ Rope.Cat["MMCCC ", machClassSw, " -name ", md.shortName, dirSw]; cmd ¬ cmd.Cat[" ", midSwitches]; cmd ¬ cmd.Cat[" -aux ", NodeToAllButOne[target: md.cNode, nodeList: from.mustHave] ]; }; Mesa => { cmd ¬ Rope.Cat["MMCCMesa ", machClassSw, " -name ", md.shortName, dirSw]; cmd ¬ cmd.Cat[" ", midSwitches]; }; Config => { cmd ¬ Rope.Cat["MMCCConfig ", machClassSw, " -name ", md.shortName, dirSw]; cmd ¬ cmd.Cat[" ", midSwitches]; cmd ¬ cmd.Cat[" -raux ", NodeToOnlyObjs[md.baseName, from.mustHave, oTail], NodeToOnlyObjs[md.baseName, from.mustHave, libTail] ]; }; Scheme => cmd ¬ Rope.Cat["Gambit ", md.shortName, ".scheme"]; Cluster => cmd ¬ Rope.Cat["Cluster ", md.shortName, ".cluster"]; Unknown => cmd ¬ Rope.Concat[ SELECT md.genesis FROM C => "MMCCC ", Cedar => "(MMCCMesa or MMCCConfig) ", Scheme => "(Gambit or Cluster) ", ENDCASE => ERROR, md.shortName]; ENDCASE => ERROR ShouldNotHappen; md.cmd ¬ cmd; RETURN}; NodeToOnlyObjs: PROC [baseName: ROPE, nodeList: NodeList, objTail: ROPE] RETURNS [aRope: ROPE] ~ -- Results are ordered as they appear in argument-- { baseLen: INT ~ baseName.Length[]; tailLen: INT ~ objTail.Length[]; ObjNameOrNIL: PROC [aNode: Node] RETURNS [shortName: ROPE ¬ NIL] ~ { nodeName: ROPE; nnLen: INT; [name: nodeName] ¬ MakeDo.PublicPartsOfNode[aNode]; nnLen ¬ nodeName.Length[]; IF nnLen=libTailLen AND name.EqualSubstrs[start1: len-libTailLen, s2: libTail]]}; NodeToAllButOne: PROC [target: Node, nodeList: NodeList] RETURNS [aRope: ROPE] ~ { ShortName: PROC [aNode: Node] RETURNS [shortName: ROPE] ~ { nodeName, fullName: ROPE; nameCP: FS.ComponentPositions; [name: nodeName] ¬ MakeDo.PublicPartsOfNode[aNode]; [fullFName: fullName, cp: nameCP] ¬ FS.ExpandName[nodeName]; shortName ¬ fullName.Substr[start: nameCP.base.start, len: nameCP.ext.start + nameCP.ext.length - nameCP.base.start]; }; aRope ¬ NIL; FOR list: NodeList ¬ nodeList, list.rest WHILE list # NIL DO IF list.first # target THEN aRope ¬ Rope.Cat[aRope, " ", ShortName[list.first]]; ENDLOOP; RETURN [aRope: aRope]; }; EnumerateDependancies: PROC [sourceNode: Node, sourceType: MDPs.SourceType, consume: PROC [fileName: ROPE], md: SourceData, subDir: ROPE] RETURNS [BOOLEAN] ~ { Pass: PROC [fileName: ROPE] ~ { c0: CHAR ~ IF fileName.Length[]>0 THEN fileName.Fetch[0] ELSE 'x; IF c0#'[ AND c0#'/ THEN fileName ¬ subDir.Concat[fileName]; consume[fileName]}; pd: MDPs.ParseData ~ MDPs.GetParseData[sourceNode, sourceType]; IF pd=NIL THEN RETURN [FALSE]; IF consume#NIL THEN { To: PROC [fileName: ROPE] ~ IF subDir.Length[]#0 THEN Pass ELSE consume; MDPs.EnumerateWithSuffix[pd.refdModules, ".c2c.o", To]; FOR rl: RopeList ¬ pd.refdFileSeq, rl.rest WHILE rl#NIL DO To[rl.first] ENDLOOP; sourceNode ¬ sourceNode}; md.sourceType ¬ pd.sourceType; RETURN [TRUE]}; Log: PROC [fmt: ROPE, val: IO.Value] ~ { IF NOT dolog THEN RETURN; SimpleFeedback.PutF[myRouterName, oneLiner, $Log, fmt, val]; RETURN}; OnProfileChange: UserProfile.ProfileChangedProc ~ { userList: LIST OF ROPE _ UserProfile.ListOfTokens["MakeDo.UserClasses", NIL]; dolog _ UserProfile.Boolean[key: "CcDeps.Talk", default: FALSE]; <> userClassList _ NIL; FOR list: LIST OF ROPE _ userList, list.rest UNTIL list = NIL DO classList: LIST OF ROPE _ UserProfile.ListOfTokens[Rope.Concat["MakeDo.UserClass.", list.first]]; IF classList # NIL THEN { classDirList: LIST OF ClassDir; userClass: UserClass; dirAndClass: DirAndClass; FOR cl: LIST OF ROPE _ classList, cl.rest.rest UNTIL cl = NIL DO classDirList _ CONS[[cl.first, cl.rest.first], classDirList]; knownLocalDirs _ CONS[[cl.first, list.first, cl.rest.first, cl.rest.first], knownLocalDirs]; ENDLOOP; userClass _ [list.first, classDirList]; userClassList _ CONS[userClass, userClassList]; }; ENDLOOP; }; UserClassDirsCmd: Commander.CommandProc ~ { class: ROPE ~ CommanderOps.NextArgument[cmd]; classDirList: LIST OF ClassDir; DO dir, switches: ROPE; IF ( dir ¬ CommanderOps.NextArgument[cmd] ) = NIL THEN EXIT; IF ( switches ¬ CommanderOps.NextArgument[cmd] ) = NIL THEN EXIT; classDirList _ CONS[[dir, switches], classDirList]; knownLocalDirs _ CONS[[dir, class, switches, switches], knownLocalDirs]; ENDLOOP; IF classDirList = NIL THEN RETURN; userClassList ¬ CONS[[class, classDirList], userClassList]; }; SetMakeDoClassProc: Commander.CommandProc ~ { arg: ROPE ~ CommanderOps.NextArgument[cmd]; IF arg = NIL THEN { currentClass _ NIL; RETURN}; FOR list: LIST OF UserClass _ userClassList, list.rest UNTIL list = NIL DO IF NOT Rope.Equal[arg, list.first.class] THEN LOOP; currentClassDirs _ list.first.classDirs; currentClass _ arg; RETURN; ENDLOOP; cmd.out.PutF1["%g is not a user defined makedo class\n", [rope[arg]] ]; }; PrintUserClassesCmd: Commander.CommandProc ~ { FOR list: LIST OF UserClass ¬ userClassList, list.rest UNTIL list = NIL DO first: BOOL ¬ TRUE; cmd.out.PutRope["[class: "]; cmd.out.PutRope[list.first.class]; cmd.out.PutRope[",\n\tLIST["]; FOR cl: LIST OF ClassDir ¬ list.first.classDirs, cl.rest UNTIL cl = NIL DO IF first THEN first ¬ FALSE ELSE cmd.out.PutRope[",\n\t "]; cmd.out.PutRope["[dir: "]; cmd.out.PutRope[cl.first.dir]; cmd.out.PutRope[", switches: "]; cmd.out.PutRope[cl.first.switches]; cmd.out.PutRope["]"]; ENDLOOP; cmd.out.PutRope["] ]"]; cmd.out.PutChar['\n]; ENDLOOP; }; AddFinder[["Cc", SourceFind], front]; UserProfile.CallWhenProfileChanges[OnProfileChange]; Commander.Register["SetMakeDoClass", SetMakeDoClassProc, "Set the class of machine for Makedo'ing"]; Commander.Register["MakeDo.UserClass", UserClassDirsCmd, "add user class; syntax is class {dir switches}* - brackets are not part of the input"]; Commander.Register["MakeDo.PrintUserClasses", PrintUserClassesCmd, "prints the user defined classes, from commands and profile"]; END. )J CcDeps.Mesa Copyright Ó 1988, 1990, 1992, 1993 by Xerox Corporation. All rights reserved. Eduardo Pelegri-Llopart, January 18, 1990 2:23:40 pm PST After ConfigAndMesaDeps.mesa Deals with (user-created and Mimosa & Cinder-created) C files. Output files are .o JKF March 14, 1989 10:28:07 am PST Last tweaked by Mike Spreitzer on May 12, 1993 10:44 am PDT Bill Jackson (bj) January 16, 1989 1:31:39 pm PST Mna, May 3, 1992 2:13 pm PDT Willie-s, March 2, 1993 2:34 pm PST INVARIANT StampRef in node props depInfo: ExtendADotOut.DependencyInfo, The stamp table and when the file was created. Used for caching information. Maintains information that MakeDo "knows" about and does not have to re-compute. depInfo: ExtendADotOut.DependencyInfo ¬ NIL, if the ".o" file has been extended, this information is acurate and easy to extract stampTable is the desired collection of stamp encoded in the O file. For Cedar-generated files, can we read some dependency info? For C and Scheme files, always TRUE. Constants A FinderProc looks for an action that will make an object with name resultName. It returns an indication of whether it found it, a pointer to the node describing the object, and a list of the nodes produced by the action. cmdFrom is a list of the determiners, while from is a list of all the nodes needed by the action to be runnable, discriminating between mandatory and optional nodes. FoundData is a record holding all the useful information that may be needed later. The action found by this finder is "Cc", details depend on the source of the C file We only know what to do with .o files. Only accept the local directories that make sense LOOPHOLE only needed for PrincOps Is an action a consistent with a current result? The action is derived from the current determiners and result is in Makes of the action. We know that the only valid result is the ONode. What to check depends on what we have available. It can be either the source creation time, or the encoded-in-O-file stamp, or the collection of mob-version stamps. thisDepInfo: ExtendADotOut.DependencyInfo; thisDepInfo ¬ CurDepInfo[node: sn]; IF thisDepInfo # NIL AND ContainsDepInfo[md.depInfo] THEN { StampInDepInfo: PROC [name: ROPE, depInfo: ExtendADotOut.DependencyInfo] RETURNS [stamp: MobDefs.VersionStamp ¬ MobDefs.NullVersion] ~ { FOR list: LIST OF ExtendADotOut.ObjectID ¬ depInfo.dependList, list.rest WHILE list # NIL DO id: ExtendADotOut.ObjectID ~ list.first; IF Rope.Equal[s1: id.name, s2: name] THEN RETURN [id.stamp]; ENDLOOP; }; stampUsed: MobDefs.VersionStamp ~ StampInDepInfo[thisName, md.depInfo]; IF thisDepInfo.self.stamp # stampUsed THEN { out: IO.STREAM ¬ IO.ROS[]; out.PutF["Version stamp of %g (", IO.rope[thisName]]; TRUSTED {MobListerUtils.PrintVersion[thisDepInfo.self.stamp, out, TRUE]}; out.PutF[") is different from the version stamp used to create %g (", IO.rope[md.oName]]; TRUSTED {MobListerUtils.PrintVersion[stampUsed, out, TRUE]}; out.PutF[")"]; consistent ¬ FALSE; reason ¬ out.RopeFromROS[]; RETURN [TRUE]; }; } ELSE { diff: ROPE ¬ NIL; NoteDiff: PROC [name, stampClass: ROPE, stamp: MobDefs.VersionStamp] RETURNS [BOOL] --Mobery.EnumerateStampProc-- ~ { elt: ROPE ~ IO.PutFR["%g: %g!%08x%08x", [rope[stampClass]], [rope[name]], [cardinal[stamp[0]]], [cardinal[stamp[1]]] ]; IF diff=NIL THEN diff ¬ elt ELSE diff ¬ diff.Cat[", ", elt]; RETURN [FALSE]}; IF md.stampTable = NIL THEN md.stampTable ¬ CurStampTab[node: md.oNode]; thisStampTable ¬ CurStampTab[node: sn]; Mobery.EnumerateStampTableDifference[thisStampTable, md.stampTable, NoteDiff]; IF diff#NIL THEN { consistent ¬ FALSE; reason ¬ IO.PutFR["Some stamps (%g) in %g are not in %g", [rope[diff]], [rope[thisName]], [rope[md.oName]] ]; RETURN [TRUE]; }; } Update the information that may have changed since last time. Extract information (Stamps and Create times) from the O that currently exist. It does not change the contents of md.support, which is done in RederiveWork[]. nothing has changed -- md.depInfo ¬ CurDepInfo[node: md.oNode]; IF NOT ContainsDepInfo[md.depInfo] THEN md.stampTable ¬ CurStampTab[node: md.oNode]; md.oReadable ¬ md.depInfo # NIL OR md.stampTable # NIL; Get the current Stamp Table of a node. Information is cached. depInfo: NIL, sr.depInfo ¬ NIL; ContainsDepInfo: PROC [depInfo: ExtendADotOut.DependencyInfo] RETURNS [BOOL] ~ INLINE { IF depInfo = NIL THEN RETURN [FALSE]; RETURN [depInfo.action.class # null]; }; CurDepInfo: ENTRY PROC [node: Node] RETURNS [depInfo: ExtendADotOut.DependencyInfo] ~ { Get the current dependency or Stamp Table of a node. Information is cached. ENABLE UNWIND => {}; sr: StampTableRef ¬ NARROW[node.GetProp[$StampTable]]; created: BasicTime.GMT ¬ InnerGetCreated[node]; fileName: ROPE ~ node.PublicPartsOfNode[].name; len: INT ~ Rope.Length[fileName]; ExpandNamesInDepInfo: PROC [depInfo: ExtendADotOut.DependencyInfo, fileName: ROPE] RETURNS [newInfo: ExtendADotOut.DependencyInfo] ~ { fileName is in FS format; all the file names in the DependencyInfo are in / format. FromSlash: PROC [old: CHAR] RETURNS [CHAR] ~ { IF old = '/ THEN RETURN ['>]; RETURN [old]; }; base: ROPE; selfName: ROPE ~ depInfo.self.name; selfConverted: ROPE; IF selfName.Fetch[0] = '/ THEN { selfConverted ¬ FS.ExpandName[selfName].fullFName; depInfo.self.name ¬ selfConverted; base ¬ NIL; } ELSE { tailPos: INT; selfConverted ¬ Rope.Translate[base: selfName, translator: FromSlash]; tailPos ¬ fileName.FindBackward[s2: selfConverted, case: TRUE]; IF tailPos = -1 THEN RETURN [NIL]; This actually shouldn't happen. base ¬ fileName.Substr[len: tailPos]; depInfo.self.name ¬ FS.ExpandName[name: selfConverted, wDir: base].fullFName; }; FOR list: LIST OF ExtendADotOut.ObjectID ¬ depInfo.dependList, list.rest WHILE list # NIL DO id: ExtendADotOut.ObjectID ¬ list.first; IF id.name.Fetch[0] # '/ THEN IF base = NIL THEN RETURN [NIL] This shouldn't happen ELSE { tailConverted: ROPE ~ Rope.Translate[base: id.name, translator: FromSlash]; newName: ROPE ~ FS.ExpandName[name: tailConverted, wDir: base].fullFName; list.first.name ¬ newName; }; ENDLOOP; RETURN [depInfo]; }; <> GetIt: PROC [] RETURNS [depInfo: ExtendADotOut.DependencyInfo ¬ NIL] ~ { <