CcDeps.Mesa
Copyright Ó 1988, 1991 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 March 19, 1990 8:31 am PST
Bill Jackson (bj) January 16, 1989 1:31:39 pm PST
DIRECTORY
Basics USING [Comparison],
BasicTime USING [GMT, Period],
CommandTool USING [CurrentWorkingDirectory],
ExtendADotOut USING [Modifier, DependencyInfo, DependencyInfoRep, Fail, GetDependencyInfo, ObjectClassFromFileName, ObjectID, SetSwitch, VersionStampFromTime],
FS USING [ComponentPositions, Error, ExpandName, StreamOpen],
IO USING [Close, EndOf, Error, GetRope, PutF, PutFR, rope, RopeFromROS, ROS, SkipWhitespace, STREAM, Value],
MakeDo USING [Action, ActionClass, ActionClassRep, AddFinder, fileClass, From, GetNode, GetProp, InnerGetCreated, Node, NodeList, notExistTime, PublicPartsOfAction, PublicPartsOfNode, SetProp, Time, Warning],
MakeDoParsing,
MakeDoPrivate USING [MDInstall],
MakeDoPorting USING [logPath],
MobDefs USING [NullVersion, VersionStamp],
Mobery USING [ReadStampTable, StampTable, StampTableRep, StampTableSubset],
MobListerUtils USING [PrintVersion],
PBasics USING [IsBound],
Process USING [PauseMsec],
RedBlackTree USING [Compare, Create, DestroyTable, EnumerateIncreasing, Insert, Lookup, Table],
RefTab USING [Fetch],
Rope USING [Cat, Concat, Equal, EqualSubstrs, Fetch, FindBackward, Length, ROPE, Substr, Translate],
SimpleStreams USING [Create],
UserProfile USING [CallWhenProfileChanges, ProfileChangedProc, Boolean];
CcDeps: CEDAR MONITOR
IMPORTS
BasicTime, CommandTool, ExtendADotOut, FS, IO, Mobery, MobListerUtils, MakeDo, MakeDoParsing, MakeDoPrivate, MakeDoPorting, PBasics, Process, RedBlackTree, RefTab, Rope
, SimpleStreams, UserProfile =
INVARIANT
StampRef in node props
BEGIN OPEN MakeDo;
dolog: BOOL ¬ FALSE;
log: IO.STREAM ¬ SimpleStreams.Create[].out;
OnProfileChange: UserProfile.ProfileChangedProc ~ {
IF UserProfile.Boolean[key: "CcDeps.Talk", default: FALSE]
THEN {
dolog ¬ TRUE;
ExtendADotOut.SetSwitch[debug, TRUE];
}
ELSE {
dolog ¬ FALSE;
ExtendADotOut.SetSwitch[debug, FALSE];
};
};
Log: PROC [fmt: ROPE, val: IO.Value] ~ {
IF NOT dolog THEN RETURN;
log.PutF[fmt, val !IO.Error => IF ec=StreamClosed THEN {
Process.PauseMsec[1500];
log ¬ SimpleStreams.Create[].out;
RETRY}];
RETURN};
GotoSyntaxError: ERROR = CODE;
ShouldNotHappen: ERROR = CODE;
ROPE: TYPE = Rope.ROPE;
StampTableRef: TYPE = REF StampTableRep; StampTableRep: TYPE = RECORD [
created: BasicTime.GMT,
depInfo: ExtendADotOut.DependencyInfo,
stampTable: Mobery.StampTable,
depInfoValid: BOOL ¬ FALSE,
stampTableValid: BOOL ¬ FALSE];
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.
oName, cName, shortName, localDir: ROPE,
sourceType: SourceType ¬ Unknown,
isC2C: BOOL,
supports: RedBlackTree.Table,
mesaNode, cedarNode, configNode, switchesNode, oNode, cNode: Node,
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 ¬ FALSE,
supportsInvalid: BOOL ¬ FALSE,
cmd: ROPE ¬ NIL
];
SourceType: TYPE = {Unknown, MesaGenerated, ConfigGenerated, PlainCFile};
Support: TYPE = REF SupportRep; SupportRep: TYPE = RECORD [
node: Node
];
To collect the files that will support our action.
installDir: ROPE ~ CommandTool.CurrentWorkingDirectory[];
installed, badInstall: BOOL ¬ FALSE;
Constants
c2cTail: ROPE = ".c2c";
c2coTail: ROPE = Rope.Cat[c2cTail, ".o"];
c2coTailLength: CARDINAL = c2coTail.Length[];
c2ccTail: ROPE = Rope.Cat[c2cTail, ".c"];
mobExt: ROPE = "mob";
mobTail: ROPE = Rope.Cat[".", mobExt];
mesaTail: ROPE = ".mesa";
cedarTail: ROPE = ".cedar";
configTail: ROPE = ".config";
switchesTail: ROPE = ".switches";
sTail: ROPE = ".s";
oExt: ROPE = "o";
oTail: ROPE = Rope.Cat[".", oExt];
cTail: ROPE = ".c";
DirAndClass: TYPE = RECORD [
dir: ROPE, -- the directory name --
class: ROPE, -- the corresponding machine class --
switches: ROPE -- the default switches --
];
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"],
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"]
]; -- if in these directories, we issue this -mach --
CcClass: ActionClass ¬ NEW [ActionClassRep ¬ [
CheckConsistency: CheckConsistency,
Rederive: RederiveSource,
ClearCaches: ClearCaches
]];
GetSupportKey: PROC [data: REF ANY] RETURNS [Node] --RedBlackTree.GetKey-- = {
s: Support = NARROW[data];
RETURN[s.node]};
CompareSupport: PROC [k, data: REF ANY] RETURNS [Basics.Comparison] --RedBlackTree.Compare-- = {
k1: INT = LOOPHOLE[k];
k2: INT = LOOPHOLE[GetSupportKey[data]];
RETURN [SELECT k1 FROM
<k2 => less,
=k2 => equal,
>k2 => greater,
ENDCASE => ERROR ShouldNotHappen];
};
ClearCaches: PROC [ac: ActionClass] ~ {
MakeDoParsing.ClearCache[];
installed ¬ badInstall ¬ FALSE;
};
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
baseDir, localDir, shortName, middleName: ROPE;
baseDir: full expanded name, up to, but not including, the sun3 directory part
localDir: local directory (can be null)
shortName: local name up to, but not including, .c2c.o
middleName: either the .c2c extension or null.
oName, cName: ROPE;
oExpanded: ROPE;
oCP: FS.ComponentPositions;
oNode, cNode: Node;
isC2C: BOOL ¬ FALSE;
md: SourceData;
GetLocalDir: PROC [name, sep: ROPE] RETURNS [dir: ROPE ¬ NIL] ~ {
pos, pos2: INT;
pos ¬ Rope.FindBackward[s1: name, s2: sep];
IF pos # -1 THEN {
pos2 ¬ Rope.FindBackward[s1: name, s2: sep, pos1: pos-1];
dir ¬ Rope.Substr[base: name, start: pos2+1, len: pos-pos2];
IF RemoteMachClassAndSwitches[dir, knownLocalDirs].mach = NIL THEN dir ¬ NIL;
Only accept the local directories that make sense
};
};
found ¬ NOT badInstall;
IF NOT found THEN RETURN;
localDir ¬ GetLocalDir[resultName, "/"];
IF localDir = NIL THEN localDir ¬ GetLocalDir[resultName, ">"];
[oExpanded, oCP, ] ¬ FS.ExpandName[resultName !FS.Error => {found ¬ FALSE; CONTINUE}];
IF NOT found THEN RETURN;
found ¬ oExpanded.EqualSubstrs[start1: oCP.ext.start, len1: oCP.ext.length, s2: oExt, case: FALSE];
IF NOT found THEN RETURN;
We only know what to do with .O files.
IF NOT installed THEN InstallMe[];
found ¬ NOT badInstall;
IF NOT found THEN RETURN;
IF (oCP.ver.start - oCP.base.start) >= c2coTailLength
THEN {
isC2C ¬ oExpanded.EqualSubstrs[start1: oCP.ext.start + oCP.ext.length - c2coTailLength, len1: c2coTailLength, s2: c2coTail, case: FALSE];
middleName ¬ c2cTail;
} ELSE {
isC2C ¬ FALSE;
middleName ¬ NIL;
};
middleName ¬ IF isC2C THEN c2cTail ELSE NIL;
shortName ¬ oExpanded.Substr[start: oCP.base.start, len: oCP.base.length - middleName.Length[]];
baseDir ¬ oExpanded.Substr[start: 0, len: oCP.base.start];
IF localDir # NIL THEN {
pos: INT;
pos ¬ Rope.FindBackward[baseDir, localDir];
baseDir ¬ baseDir.Substr[start: 0, len: pos];
};
oName ¬ Rope.Cat[baseDir, localDir, shortName, middleName, oTail];
cName ¬ Rope.Cat[baseDir, shortName, middleName, cTail];
oNode ¬ GetNode[oName, fileClass];
cNode ¬ GetNode[cName, fileClass];
foundData ¬ md ¬ NEW [SourceDataRep ¬ [
oName: oName,
cName: cName,
shortName: shortName,
localDir: localDir,
isC2C: isC2C,
supports: RedBlackTree.Create[GetSupportKey, CompareSupport],
mesaNode: GetNode[Rope.Cat[baseDir, shortName, mesaTail], fileClass],
cedarNode: GetNode[Rope.Cat[baseDir, shortName, cedarTail], fileClass],
configNode: GetNode[Rope.Cat[baseDir, shortName, configTail], fileClass],
switchesNode: GetNode[oName.Concat[switchesTail], fileClass],
oNode: oNode,
cNode: cNode,
oCreateTime: MakeDo.notExistTime
]];
IF isC2C
THEN {
cmdFrom ¬ LIST[
md.cedarNode, md.mesaNode, md.configNode,
md.cedarNodeUp, md.mesaNodeUp, md.configNodeUp, -- files one up --
md.switchesNode];
}
ELSE {
cmdFrom ¬ LIST[md.cNode, -- md.cNodeUp, -- md.switchesNode];
};
sought ¬ md.oNode;
class ¬ CcClass;
[from, cmd] ¬ RederiveWork[md];
makes ¬ LIST[md.oNode];
RETURN};
GetSwitches: PROC [oName: ROPE] RETURNS [switches: ROPE] =
BEGIN
ss: IO.STREAM ¬ NIL;
ss ¬ FS.StreamOpen[oName.Cat[switchesTail] !FS.Error => CONTINUE];
IF ss = NIL THEN RETURN [NIL];
[] ¬ ss.SkipWhitespace[];
IF ss.EndOf[] THEN { ss.Close[]; RETURN [NIL] };
switches ¬ IO.GetRope[ss];
ss.Close[];
END;
SupportIsLoaded: PROC [] RETURNS [BOOL] ~ INLINE {
moberies: BOOL;
moblisteries: BOOL;
moberies ¬ PBasics.IsBound[LOOPHOLE[Mobery.ReadStampTable]] AND PBasics.IsBound[LOOPHOLE[Mobery.StampTableSubset]];
moblisteries ¬ PBasics.IsBound[LOOPHOLE[MobListerUtils.PrintVersion]];
LOOPHOLE only needed for PrincOps
RETURN [moberies AND moblisteries];
};
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: BOOL ¬ FALSE;
CheckSupport: PROC [data: REF ANY] RETURNS [stop: BOOL ¬ FALSE] --RedBlackTree.EachNode-- ~ {
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.
s: Support = NARROW[data];
thisTime: Time = InnerGetCreated[s.node];
thisName: Rope.ROPE ~ s.node.PublicPartsOfNode[].name;
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];
};
thisDepInfo ¬ CurDepInfo[node: s.node];
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 {
IF md.stampTable = NIL
THEN md.stampTable ¬ CurStampTab[node: md.oNode];
thisStampTable ¬ CurStampTab[node: s.node];
IF NOT Mobery.StampTableSubset[thisStampTable, md.stampTable] THEN {
consistent ¬ FALSE;
reason ¬ Rope.Cat["Stamps in ", thisName, " are not a subset of the stamps in ", 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
MesaGenerated, ConfigGenerated, PlainCFile => 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.EnumerateIncreasing[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;
md.oCreateTime ¬ InnerGetCreated[md.oNode];
IF md.oCreateTime = MakeDo.notExistTime THEN RETURN;
IF oldO = md.oCreateTime AND NOT md.supportsInvalid THEN RETURN;
-- 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;
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[Rope.Cat[base, tailConverted]].fullFName;
list.first.name ¬ newName;
};
ENDLOOP;
RETURN [depInfo];
};
GetFromFileName: PROC [] RETURNS [depInfo: ExtendADotOut.DependencyInfo] ~ INLINE {
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] ~ {
SELECT TRUE FROM
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 [localDir: ROPE, known: LIST OF DirAndClass] RETURNS [mach: ROPE, switches: ROPE] ~ {
Returns a "something" or NIL, depending on whether we know about the localDir or not.
dir: ROPE;
IF localDir = NIL THEN RETURN [NIL, NIL];
dir ¬ Rope.Substr[localDir, 0, localDir.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: pair.switches];
ENDLOOP;
RETURN [NIL, NIL]
};
NoteC: PROC [pe: MakeDoParsing.ParseEntry, consume: PROC[ROPE]] ~ {
WITH pe.parseData.Fetch[$Includes].val SELECT FROM
list: LIST OF ROPE => {
FOR list ¬ list, list.rest WHILE list # NIL DO
name: ROPE ~ list.first;
consume[name];
ENDLOOP;
};
ENDCASE => NULL;
};
NoteConfig: PROC [pe: MakeDoParsing.ParseEntry, consume: PROC[ROPE]] ~ {
WITH pe.parseData.Fetch[$Requests].val SELECT FROM
list: LIST OF ROPE => {
FOR list ¬ list, list.rest WHILE list # NIL DO
name: ROPE ~ list.first;
consume[name.Cat[c2coTail]];
ENDLOOP;
};
ENDCASE => NULL;
WITH pe.parseData.Fetch[$StaticRequests].val SELECT FROM
list: LIST OF ROPE => {
FOR list ¬ list, list.rest WHILE list # NIL DO
name: ROPE ~ list.first;
consume[name];
ENDLOOP;
};
ENDCASE => NULL;
};
NoteMesa: PROC [pe: MakeDoParsing.ParseEntry, consume: PROC[ROPE]] ~ { NULL };
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.
n: Node;
s: Support;
len: INT = fileName.Length[];
This is temporary until I get the semantics cleared up
IF Rope.SkipTo[s: fileName, skip: "/>"] < len THEN ERROR ShouldNotHappen;
IF len >= 2 AND Rope.EqualSubstrs[s1: fileName, start1: len-2, len1: 2, s2: oTail, case: FALSE]
THEN fileName ¬ Rope.Cat[md.localDir, fileName];
n ¬ GetNode[fileName, fileClass];
s ¬ NARROW[md.supports.Lookup[n]];
IF s = NIL THEN {
s ¬ NEW [SupportRep ¬ [n]];
md.supports.Insert[s, n];
This is adding the files to the set on which the output nodes depend on.
};
from.mustHave ¬ CONS[n, from.mustHave];
RETURN};
Q: PROC [rope: ROPE] RETURNS [qRope: ROPE] ~ {
qRope ¬ IO.PutFR["\"%q\"", IO.rope[rope]];
RETURN [qRope];
};
userSwitches: Rope.ROPE;
mimosaSwitches: Rope.ROPE;
ss: Support;
IterateList: TYPE ~ LIST OF RECORD [node: Node, class: ATOM, proc: PROC[MakeDoParsing.ParseEntry, PROC[ROPE]]];
iterateList: IterateList;
QNIL: ROPE = Q[NIL];
dirSw: ROPE = IF md.localDir # NIL THEN Rope.Cat[" -dir ", md.localDir] ELSE NIL;
machClass: ROPE;
uSwitches: ROPE;
defaultSwitches: ROPE;
machClassSw: ROPE;
[mach: machClass, switches: uSwitches] ¬ RemoteMachClassAndSwitches[md.localDir, knownLocalDirs];
defaultSwitches ¬ Q[uSwitches];
machClassSw ¬ IF machClass # NIL THEN Rope.Cat[" -class ", machClass] ELSE NIL;
from ¬ [mustHave: LIST[md.cNode], optional: LIST[md.switchesNode]];
md.supports.DestroyTable[];
ss ¬ NEW [SupportRep ¬ [md.cNode]];
md.supports.Insert[ss, md.cNode];
IF md.isC2C
THEN {
This is a mesa, cedar, or config generated file.
iterateList ¬ LIST[[md.mesaNode, $Mesa, NoteMesa], [md.cedarNode, $Mesa, NoteMesa], [md.configNode, $Config, NoteConfig]];
}
ELSE {
This should be a plain C file.
iterateList ¬ LIST[[md.cNode, $C, NoteC]];
};
FOR list: IterateList ¬ iterateList, list.rest WHILE list # NIL DO
node: Node ~ list.first.node;
class: ATOM ~ list.first.class;
proc: PROC[MakeDoParsing.ParseEntry, PROC[ROPE]] ~ list.first.proc;
pe: MakeDoParsing.ParseEntry ¬ MakeDoParsing.GetParseEntry[node: node, class: class];
IF pe # NIL THEN {
type: ATOM ~ NARROW[pe.parseData.Fetch[$SourceType].val];
md.sourceType ¬ SELECT type FROM
$CedarProg, $CedarMonitor, $CedarDefs => MesaGenerated,
$Config => ConfigGenerated,
$C => PlainCFile,
ENDCASE => PlainCFile;
proc[pe, NoteDep];
EXIT;
};
ENDLOOP;
md.supportsInvalid ¬ TRUE;
UpdateSupport[md];
mimosaSwitches ¬ userSwitches ¬ Q[GetSwitches[md.oName]];
SELECT md.sourceType FROM
MesaGenerated => {
IF mimosaSwitches.Equal[QNIL] THEN mimosaSwitches ¬ defaultSwitches;
cmd ¬ Rope.Cat[cmd, "MMCCMesa "];
cmd ¬ Rope.Cat[cmd, machClassSw];
cmd ¬ Rope.Cat[cmd, " -name ", md.shortName];
cmd ¬ Rope.Cat[cmd, dirSw];
cmd ¬ Rope.Cat[cmd, " -mSw ", mimosaSwitches];
cmd ¬ Rope.Cat[cmd, " -uSw ", userSwitches];
};
ConfigGenerated => {
IF mimosaSwitches.Equal[QNIL] THEN mimosaSwitches ¬ defaultSwitches;
cmd ¬ Rope.Cat[cmd, "MMCCConfig "];
cmd ¬ Rope.Cat[cmd, machClassSw];
cmd ¬ Rope.Cat[cmd, " -name ", md.shortName];
cmd ¬ Rope.Cat[cmd, dirSw];
cmd ¬ Rope.Cat[cmd, " -mSw ", mimosaSwitches];
cmd ¬ Rope.Cat[cmd, " -uSw ", userSwitches];
cmd ¬ Rope.Cat[cmd, " -aux ", NodeToOnlyOs[from.mustHave]];
};
PlainCFile => {
IF mimosaSwitches.Equal[QNIL] THEN mimosaSwitches ¬ defaultSwitches;
cmd ¬ Rope.Cat[cmd, "MMCCC "];
cmd ¬ Rope.Cat[cmd, machClassSw];
cmd ¬ Rope.Cat[cmd, " -name ", md.shortName];
cmd ¬ Rope.Cat[cmd, dirSw];
cmd ¬ Rope.Cat[cmd, " -mSw ", mimosaSwitches];
cmd ¬ Rope.Cat[cmd, " -uSw ", userSwitches];
cmd ¬ Rope.Cat[cmd, " -aux ", NodeToAllButOne[target: md.cNode, nodeList: from.mustHave]];
cmd ← Rope.Cat[cmd, " -aux ", NodeToAllButOne[target: Rope.Cat[md.shortName, cTail], nodeList: from.mustHave]];
};
Unknown => cmd ¬ NIL;
ENDCASE => ERROR ShouldNotHappen;
md.cmd ¬ cmd;
RETURN};
NodeToOnlyOs: PROC [nodeList: NodeList] RETURNS [aRope: ROPE] ~ {
ONameOrNIL: PROC [aNode: Node] RETURNS [shortName: ROPE ¬ NIL] ~ {
nodeName, fullName: ROPE;
nameCP: FS.ComponentPositions;
extension: Rope.ROPE;
[name: nodeName] ¬ MakeDo.PublicPartsOfNode[aNode];
[fullFName: fullName, cp: nameCP] ¬ FS.ExpandName[nodeName];
shortName ¬ fullName.Substr[start: nameCP.base.start, len: nameCP.base.length];
extension ¬ fullName.Substr[start: nameCP.ext.start, len: nameCP.ext.length];
shortName ¬ IF Rope.Equal[s1: extension, s2: oExt, case: FALSE]
THEN shortName.Cat[oTail]
ELSE NIL;
RETURN [shortName];
};
nameToAdd: Rope.ROPE;
aRope ¬ NIL;
FOR list: NodeList ¬ nodeList, list.rest WHILE list # NIL DO
nameToAdd ¬ ONameOrNIL[list.first];
IF nameToAdd # NIL THEN aRope ¬ Rope.Cat[aRope, " ", ONameOrNIL[list.first]];
ENDLOOP;
RETURN [aRope: aRope];
};
NodeToAllButOne: PROC [target: Node, nodeList: NodeList] RETURNS [aRope: ROPE] ~ {
ExplodeTarget: PROC [target: Node] RETURNS [targetShortName: ROPE, targetDirLen: INT] ~ {
targetDir: ROPE;
targetName: ROPE ~ MakeDo.PublicPartsOfNode[target].name;
targetFullFName: ROPE;
targetCP: FS.ComponentPositions;
[fullFName: targetFullFName, cp: targetCP] ¬ FS.ExpandName[targetName];
targetDir ¬ targetFullFName.Substr[start: 0, len: targetCP.base.start];
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.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.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.ROPE = ShortName[list.first];
IF NOT Rope.Equal[s1: newName, s2: target, case: FALSE] THEN
aRope ← Rope.Cat[aRope, " ", newName];
ENDLOOP;
RETURN [aRope: aRope];
};
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.