CcDeps.Mesa
Copyright Ó 1988, 1990 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 October 5, 1992 12:33 pm PDT
Bill Jackson (bj) January 16, 1989 1:31:39 pm PST
Mna, May 3, 1992 2:13 pm PDT
DIRECTORY Atom, BasicTime, CommandTool, ExtendADotOut, FS, IO, MakeDo, MakeDoGrossHack, MakeDoParsers, MakeDoPorting, MakeDoPrivate, MobDefs, Mobery, MobListerUtils, PBasics, PFS, PFSNames, RefTab, Rope, SimpleFeedback, UserProfile;
CcDeps: CEDAR MONITOR
IMPORTS Atom, BasicTime, CommandTool, FS, IO, MakeDo, MakeDoParsers, MakeDoPorting, MakeDoPrivate, Mobery, MobListerUtils, PBasics, PFS, PFSNames, RefTab, Rope, SimpleFeedback, UserProfile
EXPORTS MakeDoGrossHack
INVARIANT
StampRef in node props
= BEGIN OPEN MakeDo, MDPs:MakeDoParsers;
ShouldNotHappen: ERROR = CODE;
ROPE: TYPE = Rope.ROPE;
StampTableRef: TYPE = REF StampTableRep; StampTableRep: TYPE = RECORD [
created: BasicTime.GMT,
depInfo: ExtendADotOut.DependencyInfo,
stampTable: Mobery.StampTable,
depInfoValid: BOOLFALSE,
stampTableValid: BOOLFALSE];
The stamp table and when the file was created. Used for caching information.
SourceData: TYPE = REF SourceDataRep; SourceDataRep: TYPE = RECORD [
Maintains information that MakeDo "knows" about and does not have to re-compute.
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,
bschemeNode: Node ← NIL,
boot: BOOLFALSE,
depInfo: ExtendADotOut.DependencyInfo ← NIL,
if the ".o" file has been extended, this information is acurate and easy to extract
stampTable: Mobery.StampTable ← NIL,
stampTable is the desired collection of stamp encoded in the O file.
oCreateTime: BasicTime.GMT,
oReadable: BOOL,
For Cedar-generated files, can we read some dependency info?
For C and Scheme files, always TRUE.
useAltSwitches: BOOL, --GROSS HACK!
supportsInvalid: BOOLFALSE,
cmd: ROPENIL
];
Genesis: TYPE ~ {C, Cedar, Scheme};
installDir: ROPE ~ CommandTool.CurrentWorkingDirectory[];
installed, badInstall: BOOLFALSE;
dolog: BOOLFALSE;
myRouterName: ATOM ~ Atom.MakeAtom["MakeDo.CcDeps"];
findAltSwitches: BOOLFALSE;
Constants
c2cTail: ROPE = ".c2c";
sxTail: ROPE = ".sx";
c2coTail: ROPE = Rope.Cat[c2cTail, ".o"];
c2coTailLength: INT = c2coTail.Length[];
sxoTail: ROPE = Rope.Cat[sxTail, ".o"];
sxoTailLength: INT = sxoTail.Length[];
c2ccTail: ROPE = Rope.Cat[c2cTail, ".c"];
sxcTail: ROPE = Rope.Cat[sxTail, ".c"];
mobExt: ROPE = "mob";
mobTail: ROPE = Rope.Cat[".", mobExt];
mesaTail: ROPE = ".mesa";
cedarTail: ROPE = ".cedar";
configTail: ROPE = ".config";
schemeTail: ROPE = ".scheme";
bschemeTail: ROPE = ".bscheme";
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: ROPENIL --the alternate switches — GROSS HACK
];
knownLocalDirs: LIST OF DirAndClass = LIST[
DirAndClass[dir: "sun3", class: "sun3", switches: "-c -g"],
DirAndClass[dir: "sun4", class: "sun4", switches: "-c -g"],
DirAndClass[dir: "sun4-o3", class: "sun4", switches: "-c -O3", altSwitches: "-c -O2"],
DirAndClass[dir: "sun4o3", class: "sun4", switches: "-c -O3", altSwitches: "-c -O2"],
DirAndClass[dir: "29k", class: "amd29000", switches: "-c -g"],
DirAndClass[dir: "sun4-profiled", class: "sun4", switches: "-c -p"],
DirAndClass[dir: "sun4-gprof", class: "sparc", switches: "-c -pg"],
DirAndClass[dir: "rs6000", class: "rs6000", switches: "-c -g"],
DirAndClass[dir: "rs6000o", class: "rs6000", switches: "-c -O", altSwitches: "-c -O"],
DirAndClass[dir: "rs6000-o", class: "rs6000", switches: "-c -O", altSwitches: "-c -O"],
DirAndClass[dir: "mipsl", class: "mipsl", switches: "-c -g", altSwitches: "-c -g"],
DirAndClass[dir: "mipsl-o", class: "mipsl", switches: "-c -O", altSwitches: "-c -O"],
DirAndClass[dir: "mips", class: "mips", switches: "-c -g", altSwitches: "-c -g"],
DirAndClass[dir: "mips-o", class: "mips", switches: "-c -O", altSwitches: "-c -O"]
]; -- 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 -- ~ {
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
shortName: ROPE; -- the part after last directory delim and before .c2c.o
middleName: ROPE; --either .c2c, .sx, or null
subName: ROPENIL; --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];
We only know what to do with .o files.
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};
Only accept the local directories that make sense
}
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.bschemeNode ← GetNode[Rope.Cat[baseName, shortName, bschemeTail], fileClass];
md.configNode ← GetNode[Rope.Cat[baseName, shortName, clusterTail], fileClass];
cmdFrom ← LIST[md.mesaNode, md.bschemeNode, md.configNode]};
ENDCASE => ERROR;
sought ← md.oNode;
class ← CcClass;
[from, cmd] ← RederiveWork[md];
makes ← LIST[md.oNode];
RETURN};
GetSwitches: PROC [sp: PFS.PATH] RETURNS [switches: ROPENIL] = {
ss: IO.STREAMNIL;
ss ← PFS.StreamOpen[sp !PFS.Error => CONTINUE];
IF ss # NIL THEN {
[] ← ss.SkipWhitespace[];
IF NOT ss.EndOf[] THEN switches ← IO.GetLineRope[ss];
ss.Close[]};
RETURN};
MesafySwitches: PROC [switches, defaultMsw: ROPE] RETURNS [ROPE] = {
IF switches.Length = 0 THEN switches ← IO.PutFR["-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.PutFR["-mSw \"%q\"", [rope[switches]] ];
RETURN [switches]};
SupportIsLoaded: PROC [] RETURNS [BOOL] ~ {
moberies, moblisteries, pfs: BOOL;
moberies ← PBasics.IsBound[LOOPHOLE[Mobery.ReadStampTable]] AND PBasics.IsBound[LOOPHOLE[Mobery.StampTableSubset]];
moblisteries ← PBasics.IsBound[LOOPHOLE[MobListerUtils.PrintVersion]];
LOOPHOLE only needed for PrincOps
pfs ← PBasics.IsBound[LOOPHOLE[PFS.PathFromRope]] AND PBasics.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-- =
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.
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: BOOLFALSE;
CheckSupport: PROC [key, val: REF ANY] RETURNS [stop: BOOLFALSE] --RefTab.EachPairAction-- ~ {
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.
sn: Node = MakeDo.NarrowToNode[key];
thisTime: Time = InnerGetCreated[sn];
thisName: ROPE ~ sn.PublicPartsOfNode[].name;
thisIsLib: BOOL ~ IsLibName[thisName];
thisDepInfo: ExtendADotOut.DependencyInfo;
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];
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.STREAMIO.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: ROPENIL;
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];
};
}
};
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] = {
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[].
oldO: Time = md.oCreateTime;
oLength: INT;
[md.oCreateTime, oLength]← InnerGetInfo[md.oNode];
IF oLength=0 THEN md.oCreateTime ← MakeDo.notExistTime;
IF md.oCreateTime = MakeDo.notExistTime THEN RETURN;
IF oldO = md.oCreateTime AND NOT md.supportsInvalid THEN RETURN;
nothing has changed --
IF md.genesis=Cedar THEN {
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;
};
md.supportsInvalid ← FALSE;
};
CurStampTab: ENTRY PROC [node: Node] RETURNS [stampTable: Mobery.StampTable] ~ {
Get the current 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;
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,
depInfo: NIL,
stampTable: NIL]]
];
IF created = MakeDo.notExistTime
THEN {
sr.stampTable ← NIL;
sr.depInfo ← 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]
};
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];
};
<<GetFromFileName: PROC [] RETURNS [depInfo: ExtendADotOut.DependencyInfo] ~ {
depInfo ← NEW [ExtendADotOut.DependencyInfoRep ← [
self: [name: fileName, class: ExtendADotOut.ObjectClassFromFileName[fileName], stamp: ExtendADotOut.VersionStampFromTime[created]],
action: [name: NIL, class: null, stamp: MobDefs.NullVersion],
dependList: NIL
]];
};>>
GetIt: PROC [] RETURNS [depInfo: ExtendADotOut.DependencyInfo ← NIL] ~ {
<<SELECT TRUE FROM
NOT PBasics.IsBound[LOOPHOLE[ExtendADotOut.GetDependencyInfo]] => RETURN [NIL];
len >= 2 AND Rope.EqualSubstrs[s1: fileName, start1: len-2, s2: ".c"] => {
Log["DepInfo from create time for %g\n", IO.rope[fileName]];
depInfo ← GetFromFileName[];
};
len >= 2 AND Rope.EqualSubstrs[s1: fileName, start1: len-2, s2: ".h"] => {
Log["DepInfo from create time for %g\n", IO.rope[fileName]];
depInfo ← GetFromFileName[];
};
ENDCASE => {
Log["GetDependencyInfo for %g", IO.rope[fileName]];
depInfo ← ExtendADotOut.GetDependencyInfo[fileName ! ExtendADotOut.Fail => {depInfo ← GetFromFileName[] ; CONTINUE }];
depInfo ← ExpandNamesInDepInfo[depInfo, fileName];
};>>
RETURN [depInfo];
};
IF sr = NIL THEN node.SetProp[
prop: $StampTable,
val: sr ← NEW [StampTableRep ← [
created: notExistTime,
depInfo: NIL,
stampTable: NIL]]
];
IF created = MakeDo.notExistTime
THEN {
sr.stampTable ← NIL;
sr.depInfo ← NIL;
sr.stampTableValid ← sr.depInfoValid ← TRUE;
RETURN [depInfo: sr.depInfo]; -- cached value --
};
IF created = sr.created THEN {
IF NOT sr.depInfoValid THEN {
sr.depInfoValid ← TRUE;
sr.depInfo ← GetIt[];
};
RETURN [depInfo: sr.depInfo]; -- cached value --
};
sr.created ← created;
sr.stampTableValid ← FALSE;
sr.depInfoValid ← TRUE;
sr.depInfo ← GetIt[];
depInfo ← sr.depInfo;
RETURN [depInfo: sr.depInfo]; -- cached value --
};
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] ~ {
Returns a "something" or NIL, depending on whether we know about the subName or not.
dir: ROPE;
IF subName = NIL THEN RETURN [NIL, NIL];
dir ← Rope.Substr[subName, 0, subName.Length[]-1];
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] ~ {
RederiveWork determines which of a collection of actions implied by md is currently favored by the state of the system. It returns the action and the list of all the nodes needed for this action to be startable.
NoteDep: PROC [fileName: ROPE] ~ {
Collect one more dependency into the from set; also reconstructs md.support.
Elements of from.mustHave appear in the reverse of the EnumerateDependancies order.
n: Node; p: PFS.PATH; fn: ROPE;
p ← PFS.PathFromRope[fileName !PFS.Error => {MakeDo.Warning[IO.PutFR["PFS.Error[%g, %g] while processing dependency on %g of %g", [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.Cat[" -dir ", md.subName] ELSE NIL;
machClass, uSwitches, midSwitches, mmSwitches, machClassSw: ROPE;
[mach: machClass, switches: uSwitches] ← RemoteMachClassAndSwitches[md.subName, knownLocalDirs, md.useAltSwitches];
machClassSw ← IF machClass # NIL THEN Rope.Cat[" -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.bschemeNode, Scheme, NIL, md, NIL, TRUE]
OR EnumerateDependancies[md.configNode, Cluster, NoteDep, md, NIL] THEN NULL;
{srcNode: Node ~ SELECT md.sourceType FROM
Scheme => IF md.boot THEN md.bschemeNode ELSE 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];
mmSwitches ← MesafySwitches[midSwitches, uSwitches];
SELECT md.sourceType FROM
PlainC => {
cmd ← Rope.Cat["MMCCC ", machClassSw, " -name ", md.shortName, dirSw];
cmd ← cmd.Cat[" ", mmSwitches];
cmd ← cmd.Cat[" -aux ", NodeToAllButOne[target: md.cNode, nodeList: from.mustHave] ];
};
Mesa => {
cmd ← Rope.Cat["MMCCMesa ", machClassSw, " -name ", md.shortName, dirSw];
cmd ← cmd.Cat[" ", mmSwitches];
};
Config => {
cmd ← Rope.Cat["MMCCConfig ", machClassSw, " -name ", md.shortName, dirSw];
cmd ← cmd.Cat[" ", mmSwitches];
cmd ← cmd.Cat[" -raux ",
NodeToOnlyObjs[md.baseName, from.mustHave, oTail],
NodeToOnlyObjs[md.baseName, from.mustHave, libTail]
];
};
Scheme => cmd ← IO.PutFR[IF md.boot
THEN "Gambit -m %g %g.bscheme"
ELSE "Gambit %g %g.scheme",
[rope[midSwitches]], [rope[md.shortName]] ];
Cluster => cmd ← Rope.Cat["Cluster ", midSwitches, " ", md.shortName, ".cluster"];
Unknown => cmd ← Rope.Cat[
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: ROPENIL] ~ {
nodeName: ROPE;
nnLen: INT;
[name: nodeName] ← MakeDo.PublicPartsOfNode[aNode];
nnLen ← nodeName.Length[];
IF nnLen<tailLen OR NOT nodeName.EqualSubstrs[start1: nnLen-tailLen, s2: objTail] THEN RETURN [NIL];
IF baseName.EqualSubstrs[s2: nodeName, len2: baseLen] THEN {
shortName ← nodeName.Substr[start: baseLen];
IF Rope.IsPrefix["<", shortName] THEN shortName ← shortName.Substr[start: 1];
RETURN};
RETURN [nodeName]};
aRope ← NIL;
FOR list: NodeList ← nodeList, list.rest WHILE list # NIL DO
nameToAdd: ROPE ← ObjNameOrNIL[list.first];
IF nameToAdd#NIL THEN aRope ← Rope.Cat[aRope, " ", nameToAdd];
ENDLOOP;
RETURN};
IsLibName: PROC [name: ROPE] RETURNS [BOOL] ~ {
len: INT ~ name.Length[];
RETURN [len>=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];
};
NodeToAllButOne: PROC [target: Node, nodeList: NodeList] RETURNS [aRope: ROPE] ~ {
ExplodeTarget: PROC [target: Node] RETURNS [targetShortName: ROPE, targetDirLen: INT] ~ {
targetName: ROPE ~ MakeDo.PublicPartsOfNode[target].name;
targetFullFName: ROPE;
targetCP: FS.ComponentPositions;
[fullFName: targetFullFName, cp: targetCP] ← FS.ExpandName[targetName];
targetShortName ← targetFullFName.Substr[start: targetCP.base.start];
RETURN [targetShortName: targetShortName, targetDirLen: targetCP.base.start];
};
targetShortName: ROPE;
targetDirLen: INT;
ShortName: PROC [aNode: Node] RETURNS [shortName: ROPE] ~ {
nodeName, fullName: ROPE;
[name: nodeName] ← MakeDo.PublicPartsOfNode[aNode];
fullName ← FS.ExpandName[nodeName].fullFName;
shortName ← fullName.Substr[start: targetDirLen];
};
[targetShortName: targetShortName, targetDirLen: targetDirLen] ← ExplodeTarget[target];
aRope ← NIL;
FOR list: NodeList ← nodeList, list.rest WHILE list # NIL DO
newName: ROPE = ShortName[list.first];
IF NOT Rope.Equal[s1: newName, s2: targetShortName, case: FALSE] THEN
aRope ← Rope.Cat[aRope, " ", newName];
ENDLOOP;
RETURN [aRope: aRope];
};
NodeToAllButOne: PROC [target: ROPE, 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
newName: ROPE = ShortName[list.first];
IF NOT Rope.Equal[s1: newName, s2: target, case: FALSE] THEN
aRope ← Rope.Cat[aRope, " ", newName];
ENDLOOP;
RETURN [aRope: aRope];
};
EnumerateDependancies: PROC [sourceNode: Node, sourceType: MDPs.SourceType, consume: PROC [fileName: ROPE], md: SourceData, subDir: ROPE, boot: BOOLFALSE] RETURNS [BOOLEAN] ~ {
If sourceNode exists, then callback to consume with all the fileNames that are required to be present by the semantics of sourceType and the contents of sourceNode. Caching is done.
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;
md.boot ← boot;
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 ~ {
dolog ← UserProfile.Boolean[key: "CcDeps.Talk", default: FALSE];
<<ExtendADotOut.SetSwitch[debug, dolog];>>
RETURN};
AddFinder[["Cc", SourceFind], front];
UserProfile.CallWhenProfileChanges[OnProfileChange];
END.
JKF October 7, 1988 10:51:46 am PDT
Just changed -lcedarc to -lxrc
JKF March 14, 1989 10:27:47 am PST
Added a class for profiled code.