DIRECTORY
BasicTime USING [GMT],
BcdDefs USING [VersionStamp],
DefaultRemoteNames USING [Get],
FS USING [Error, ExpandName],
Rope USING [Concat, Equal, ROPE],
UserProfile USING [CallWhenProfileChanges, ListOfTokens, ProfileChangedProc],
VersionMap USING [Map, MapAndName, MapList, RestoreMapFromFile, VersionToName],
VersionMapDefaults USING [];
VersionMapDefaultsImpl:
CEDAR
MONITOR
IMPORTS DefaultRemoteNames, FS, Rope, UserProfile, VersionMap
EXPORTS VersionMapDefaults
= BEGIN OPEN Rope;
Operations on default version map lists.
WhichMapList:
TYPE =
ATOM;
$Source => the source symbol version map list (initially from CedarSource.VersionMap)
$Symbols => the source symbol version map list (initially from CedarSymbols.VersionMap)
other => a user-defined version map variety (initially empty)
assumeImmutable: BOOL ← TRUE;
root: EntryList ← NIL;
EntryList: TYPE = LIST OF Entry;
Entry: TYPE = RECORD [key: ATOM ← NIL, mapList: VersionMap.MapList ← NIL];
defaultSourceName: ROPE ← Rope.Concat[DefaultRemoteNames.Get[].current, "VersionMap>CedarSource.VersionMap"];
defaultSymbolsName: ROPE ← Rope.Concat[DefaultRemoteNames.Get[].current, "VersionMap>CedarSymbols.VersionMap"];
FileNameFromVersion:
PUBLIC
PROC [which:
ATOM, version: BcdDefs.VersionStamp]
RETURNS [name:
ROPE ←
NIL, created: BasicTime.
GMT] = {
... returns a name corresponding to the given version stamp in the indicated map list (does not check for multiple names, since that is the responsibility of the version map creator).
mapList: VersionMap.MapList ← GetMapList[which];
IF mapList #
NIL
THEN {
mapAndName: VersionMap.MapAndName ← VersionMap.VersionToName[mapList, version];
name ← mapAndName.name;
created ← mapAndName.created;
};
};
GetMapList:
PUBLIC
ENTRY
PROC [which:
ATOM]
RETURNS [list: VersionMap.MapList ←
NIL] = {
... gets the current selected version map list. If there is no such map, then NIL will be returned unless which = $Source or which = $Symbols, which will restore the official version maps from CedarSource.VersionMap or CedarSymbols.VersionMap respectively.
ENABLE UNWIND => NULL;
mapFileName: ROPE ← NIL;
FOR eList: EntryList ← root, eList.rest
WHILE eList #
NIL
DO
IF eList.first.key = which THEN RETURN [eList.first.mapList];
ENDLOOP;
SELECT which
FROM
$Source => mapFileName ← defaultSourceName;
$Symbols => mapFileName ← defaultSymbolsName;
ENDCASE => RETURN;
list ← LIST[VersionMap.RestoreMapFromFile[mapFileName, TRUE]];
root ← CONS[Entry[which, list], root];
};
AddToMapList:
PUBLIC
ENTRY
PROC [which:
ATOM, map: VersionMap.Map] = {
... adds a new map to the lookup list. Use this proc for adding personal version maps.
ENABLE UNWIND => NULL;
mapList: VersionMap.MapList ← LIST[map];
IF map = NIL THEN RETURN;
FOR eList: EntryList ← root, eList.rest
WHILE eList #
NIL
DO
IF eList.first.key = which
THEN {
mapList.rest ← eList.first.mapList;
eList.first.mapList ← mapList;
RETURN};
ENDLOOP;
There is no mapList under this key, so add it
root ← CONS[Entry[which, mapList], root];
};
SetMapList:
PUBLIC
ENTRY
PROC [which:
ATOM, list: VersionMap.MapList ←
NIL] = {
.. sets the current version map for source files. Since there can be a race between GetMapList and SetMapList, this operation should not be casually used!
ENABLE UNWIND => NULL;
FOR eList: EntryList ← root, eList.rest
WHILE eList #
NIL
DO
IF eList.first.key = which
THEN {
eList.first.mapList ← list;
RETURN};
ENDLOOP;
There is no mapList under this key, so add it
root ← CONS[Entry[which, list], root];
};
ProcessUserProfile: UserProfile.ProfileChangedProc = {
ProcessUserProfileList[$Symbols, "VersionMap.SymbolsMaps", defaultSymbolsName];
ProcessUserProfileList[$Source, "VersionMap.SourceMaps", defaultSourceName];
};
ProcessUserProfileList:
PROC [class:
ATOM, key:
ROPE, always:
ROPE] = {
list: LIST OF ROPE ← UserProfile.ListOfTokens[key, NIL];
always ← FS.ExpandName[always ! FS.Error => CONTINUE].fullFName;
FOR each:
LIST
OF
ROPE ← list, each.rest
WHILE each #
NIL
DO
each.first ←
FS.ExpandName[each.first !
FS.Error =>
CONTINUE].fullFName;
Try to make the name canonical in form
ENDLOOP;
list ← RemoveRope[list, always];
SetMapList[class, NIL];
ProcessAName[class, always];
WHILE list #
NIL
DO
name: ROPE = list.first;
list ← RemoveRope[list, name];
ProcessAName[class, name];
ENDLOOP;
};
ProcessAName:
PROC [class:
ATOM, name:
ROPE] = {
map: VersionMap.Map ← NIL;
map ← VersionMap.RestoreMapFromFile[name ! FS.Error => CONTINUE];
IF map # NIL THEN AddToMapList[class, map];
};
RemoveRope:
PROC [list:
LIST
OF
ROPE, item:
ROPE]
RETURNS [
LIST
OF
ROPE] = {
lag: LIST OF ROPE ← NIL;
FOR each:
LIST
OF
ROPE ← list, each.rest
WHILE each #
NIL
DO
IF Rope.Equal[each.first, item,
FALSE]
THEN {
IF lag = NIL THEN list ← each.rest ELSE lag.rest ← each.rest;
LOOP;
};
lag ← each;
ENDLOOP;
RETURN [list];
};
UserProfile.CallWhenProfileChanges[ProcessUserProfile];
END.