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.