VersionMap2FromFile.mesa
Copyright Ó 1990 by Xerox Corporation. All rights reserved.
Last tweaked by Mike Spreitzer on April 10, 1992 9:55 am PDT
DIRECTORY Atom, BasicTime, MorePfsNames, PFS, PFSNames, Rope, SymTab, VersionMap, VersionMap2, VersionMap2Binding, VersionMap2BindingByPattern, VersionMap2FromPattern, VersionMap2Implr, VersionMapDefaults;
VersionMap2FromFile: CEDAR PROGRAM
IMPORTS Atom, MorePfsNames, PFS, PFSNames, Rope, SymTab, VersionMap, VersionMap2, VersionMap2FromPattern, VersionMap2Implr, VersionMapDefaults
EXPORTS VersionMap2, VersionMap2Binding, VersionMap2BindingByPattern
=
BEGIN OPEN VM2:VersionMap2, VM2i:VersionMap2Implr, VM2P:VersionMap2FromPattern, PVM:VersionMap, PVMD:VersionMapDefaults, MPfsN:MorePfsNames;
ROPE: TYPE ~ Rope.ROPE;
allName: VM2.Name ← PFSNames.ConstructName[LIST[MPfsN.ConstructComponent[["**"], [all]], MPfsN.ConstructComponent[["*"], [all]]], TRUE];
class: VM2.MapClass ~ VM2i.FillinDefaults[TRUE, constant, [
CreateGenerator: MFFCreateGenerator,
Size: MFFSize,
data: NIL]];
rootToNpl: SymTab.Ref ~ SymTab.Create[case: TRUE];
srcCache: VM2.Map ~ VM2.CreateVariableMap[];
intCache:VM2.Map ~ VM2.CreateVariableMap[];
exlCache: VM2.Map ~ VM2.CreateVariableMap[];
NamePatternList: TYPE ~ LIST OF RECORD [
pat: VM2.Name,
maps: ARRAY VM2P.Kind OF VM2.Map];
ScanLists: PUBLIC PROC [Consume: PROC [root: ROPE] RETURNS [stop: BOOL]] ~ {
PerPair: PROC [key: ROPE, val: REF ANY] RETURNS [quit: BOOL] ~ {
quit ← Consume[key];
RETURN};
[] ← rootToNpl.Pairs[PerPair];
RETURN};
ScanList: PUBLIC PROC [root: ROPE, Consume: PROC [pattern: VM2.Name] RETURNS [stop: BOOL]] ~ {
npl: NamePatternList ← NARROW[rootToNpl.Fetch[root].val];
FOR l: NamePatternList ← npl, l.rest WHILE l#NIL DO
IF Consume[l.first.pat] THEN RETURN;
ENDLOOP;
RETURN};
AddToList: PUBLIC PROC [root: ROPE, pattern: VM2.Name] ~ {
npl: NamePatternList ← NARROW[rootToNpl.Fetch[root].val];
FOR l: NamePatternList ← npl, l.rest WHILE l#NIL DO
IF VM2.NameEqual[l.first.pat, pattern] THEN RETURN;
ENDLOOP;
npl ← CONS[
[pattern, [
VM2P.Create[pattern, VM2P.OneKind[source], srcCache, VM2.nullMap, TRUE],
VM2P.Create[pattern, VM2P.OneKind[intermediate], intCache, VM2.nullMap, TRUE],
VM2P.Create[pattern, VM2P.OneKind[executable], exlCache, VM2.nullMap, TRUE] ]],
npl];
[] ← rootToNpl.Store[root, npl];
RETURN};
RemFromList: PUBLIC PROC [root: ROPE, pattern: VM2.Name] ~ {
head, l: NamePatternList ← NARROW[rootToNpl.Fetch[root].val];
last: NamePatternList ← NIL;
WHILE l#NIL DO
IF VM2.NameEqual[l.first.pat, pattern] THEN {
IF last=NIL THEN head ← l.rest ELSE last.rest ← l.rest;
}
ELSE last ← l;
l ← l.rest;
ENDLOOP;
[] ← rootToNpl.Store[root, head];
RETURN};
GetMap: PUBLIC PROC [key: ROPE] RETURNS [VM2.Map] ~ {
which: ATOM ~ Atom.MakeAtom[key];
all: PVM.MapList ~ PVMD.GetMapList[which];
map: VM2.Map ← VM2.anEmpty;
npl: NamePatternList;
kind: VM2P.Kind;
[npl, kind] ← Factor[key];
FOR list: PVM.MapList ← all, list.rest WHILE list#NIL DO
map ← map.Union[[class, list.first], other];
ENDLOOP;
FOR l: NamePatternList ← npl, l.rest WHILE l#NIL DO
map ← map.Union[l.first.maps[kind], map];
ENDLOOP;
RETURN [map]};
Factor: PROC [key: ROPE] RETURNS [npl: NamePatternList ← NIL, kind: VM2P.Kind ← source] ~ {
kl: INT ~ key.Length[];
Try: PROC [sfx: ROPE, k: VM2P.Kind] RETURNS [BOOL] ~ {
sfxl: INT ~ sfx.Length[];
IF sfxl<=kl AND Rope.EqualSubstrs[key, kl-sfxl, sfxl, sfx, 0, sfxl, TRUE] THEN {
npl ← NARROW[rootToNpl.Fetch[key.Substr[0, kl-sfxl]].val];
kind ← k;
RETURN [TRUE]}
ELSE RETURN [FALSE]};
got: BOOL ← Try["Source", source]
OR Try["Intermediate", intermediate]
OR Try["Executable", executable];
RETURN};
<<GetMap: PUBLIC PROC [key: ROPE] RETURNS [VM2.Map] ~ {
found: BOOL;
ma: REF ANY;
[found, ma] ← keyCache.Fetch[key];
IF found THEN RETURN [VM2.DeRefify[ma]^];
{fileNames: VM2.LOR ← UserProfile.ListOfTokens[
key: Rope.Cat["VersionMap.", key, "Maps"],
default: SELECT TRUE FROM
key.Equal["Source", FALSE] => LIST["/PCedar/VersionMap/PCedarSource.VersionMap"],
key.Equal["Intermediate", FALSE] => LIST["/PCedar/VersionMap/PCedarIntermediate.VersionMap"],
key.Equal["Executable", FALSE] => LIST["/PCedar/VersionMap/PCedarSparcExecutable.VersionMap", "/PCedar/VersionMap/PCedarSparcOptExecutable.VersionMap"],
ENDCASE => NIL
];
map: VM2.Map ← VM2.anEmpty;
FOR fileNames ← fileNames, fileNames.rest WHILE fileNames#NIL DO
next: VM2.Map ~ MapFromFile[PFS.PathFromRope[fileNames.first !PFS.Error => LOOP], VM2.nullCreated, TRUE];
map ← map.Union[next];
ENDLOOP;
[] ← keyCache.Insert[key, map.Refify[]];
RETURN [map]}};>>
MapFromFile: PUBLIC PROC [fileName: VM2.Name, created: VM2.Created, assumeImmutable: BOOL] RETURNS [VM2.Map] ~ {
om: PVM.Map ~ PVM.RestoreMapFromFile[fileName, created, assumeImmutable];
RETURN [[class, om]]};
MapIsFromFile: PUBLIC PROC [map: VM2.Map] RETURNS [VM2.MaybeFromFile] ~ {
IF map.class=class THEN {
om: PVM.Map ~ NARROW[map.data];
RETURN [[TRUE, om.fileName, om.askedForUID, om.assumeImmutable]]};
RETURN [[FALSE, VM2.nullName, VM2.nullCreated, FALSE]]};
MFFCreateGenerator: PROC [map: VM2.Map, inOrder: BOOL, pfml: VM2.PatternFactoredMapList] RETURNS [gen: VM2.Generator] ~ {
om: PVM.Map ~ NARROW[map.data];
IF pfml.pattern.stamp # VM2.nullStamp THEN {
theStamp: VM2.VersionStamp ~ pfml.pattern.stamp;
manl: PVM.MapAndNameList ~ PVM.VersionToAllNames[LIST[om], theStamp];
pfml.pattern.stamp ← VM2.nullStamp;
RETURN CreateManlGenerator[map, inOrder, pfml, manl, theStamp]};
IF pfml.pattern.name = VM2.nullName THEN pfml.pattern.name ← allName;
{shortNameC: PFSNames.Component ~ pfml.pattern.name.ShortName[];
shortNameR: ROPE ~ shortNameC.ComponentRope[--don't want or expect this to include version--];
starp: INT ~ shortNameR.Index[s2: "*"];
dstarp: INT ~ shortNameR.Find["**"];
IF dstarp >= 0 THEN {--foo/x**y => foo/x*y + foo/x**/*y
path1: VM2.Name ~ pfml.pattern.name.ReplaceShortName[MPfsN.ConsComponent[[shortNameR, 0, dstarp+2], [all]]];
path2: VM2.Name ~ PFSNames.ConstructName[LIST[MPfsN.ConstructComponent[[shortNameR, dstarp+1], shortNameC.version]]];
simpleR: ROPE ~ shortNameR.Replace[dstarp, 1, NIL];
simpleC: PFSNames.Component ~ MPfsN.ConstructComponent[[simpleR], shortNameC.version];
simpleP: VM2.Name ~ pfml.pattern.name.ReplaceShortName[simpleC];
g1: VM2.Generator ~ MFFCreateGenerator[map, inOrder, [[simpleP, pfml.pattern.created, pfml.pattern.stamp], pfml.stampInd, pfml.general]];
g2: VM2.Generator ~ MFFCreateGenerator[map, inOrder, [[path1.Cat[path2], pfml.pattern.created, pfml.pattern.stamp], pfml.stampInd, pfml.general]];
RETURN g1.GeneratorUnion[g2, inOrder]}
ELSE {
prefix: ROPE ~ shortNameR.Substr[len: starp];
rangeList: PVM.RangeList ~ PVM.ShortNameToRanges[LIST[om], prefix];
rg: RangeGenerator ~ NEW [RangeGeneratorPrivate ← [rangeList, prefix, prefix.Length[], pfml]];
FOR rl: PVM.RangeList ← rangeList, rl.rest WHILE rl#NIL DO
rl.first.len ← rl.first.map.Length[] - rl.first.first;
ENDLOOP;
gen ← NEW [VM2.GeneratorRep ← [RangeNext, VM2i.DullClose, rg]];
IF inOrder THEN gen ← VM2.GeneratorSort[gen];
RETURN};
}};
RangeGenerator: TYPE ~ REF RangeGeneratorPrivate;
RangeGeneratorPrivate: TYPE ~ RECORD [
rangeList: PVM.RangeList,
prefix: ROPE, prefixLen: INT,
pfml: VM2.PatternFactoredMapList
];
RangeNext: PROC [gen: VM2.Generator] RETURNS [VM2.VersionTuple] ~ {
rg: RangeGenerator ~ NARROW[gen.data];
DO t: VM2.VersionTuple;
nameR: ROPE;
gmt: BasicTime.GMT;
stamp: VM2.VersionStamp;
IF rg.rangeList = NIL THEN RETURN [VM2.nullTuple];
IF rg.rangeList.first.len = 0 THEN {rg.rangeList ← rg.rangeList.rest; LOOP};
[nameR, stamp, gmt, rg.rangeList.first] ← PVM.RangeToEntry[rg.rangeList.first];
t ← [PFS.PathFromRope[nameR], VM2.CreatedFromGMT[gmt], stamp];
{snr: ROPE ~ t.name.ShortName[].ComponentRope[--no version part wanted or expected--];
IF NOT rg.prefix.EqualSubstrs[s2: snr, len2: rg.prefixLen, case: FALSE] THEN {rg.rangeList ← rg.rangeList.rest; LOOP};
IF VM2.PfmlHas[rg.pfml, t] THEN RETURN [t];
}ENDLOOP;
};
CreateManlGenerator: PROC [map: VM2.Map, inOrder: BOOL, pfml: VM2.PatternFactoredMapList, manl: PVM.MapAndNameList, stamp: VM2.VersionStamp] RETURNS [gen: VM2.Generator] ~ {
IF VM2i.NamePatternAcceptsAll[pfml.pattern.name, 2] THEN pfml.pattern.name ← VM2.nullName;
{mg: ManlGenerator ~ NEW [ManlGeneratorPrivate ← [manl, stamp, pfml, pfml.pattern=[] ]];
gen ← NEW [VM2.GeneratorRep ← [ManlNext, VM2i.DullClose, mg]];
IF inOrder THEN gen ← VM2.GeneratorSort[gen];
RETURN}};
ManlGenerator: TYPE ~ REF ManlGeneratorPrivate;
ManlGeneratorPrivate: TYPE ~ RECORD [
manl: PVM.MapAndNameList,
stamp: VM2.VersionStamp,
pfml: VM2.PatternFactoredMapList,
patternAcceptsAll: BOOL];
ManlNext: PROC [gen: VM2.Generator] RETURNS [VM2.VersionTuple] ~ {
mg: ManlGenerator ~ NARROW[gen.data];
DO
IF mg.manl=NIL THEN RETURN [VM2.nullTuple];
{t: VM2.VersionTuple ~ [PFS.PathFromRope[mg.manl.first.name], VM2.CreatedFromGMT[mg.manl.first.created], mg.stamp];
mg.manl ← mg.manl.rest;
IF VM2.PfmlHas[mg.pfml, t] THEN RETURN [t];
}ENDLOOP;
};
MFFSize: PROC [map: VM2.Map, limit: INT] RETURNS [INT] ~ {
om: PVM.Map ~ NARROW[map.data];
RETURN om.Length[]};
END.