VersionMapDefaultsImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Russ Atkinson, October 29, 1984 1:06:32 pm PST
Paul Rovner, August 19, 1983 1:17 pm
DIRECTORY
BcdDefs USING [VersionStamp],
FS USING [Error],
Rope USING [Equal, ROPE],
UserProfile USING [CallWhenProfileChanges, ListOfTokens, ProfileChangedProc],
VersionMap USING [Map, MapList, RestoreMapFromFile, VersionToName],
VersionMapDefaults USING [];
VersionMapDefaultsImpl: CEDAR MONITOR
IMPORTS 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: BOOLTRUE;
root: EntryList ← NIL;
EntryList: TYPE = LIST OF Entry;
Entry: TYPE = RECORD [key: ATOMNIL, mapList: VersionMap.MapList ← NIL];
FileNameFromVersion: PUBLIC PROC
[which: ATOM, version: BcdDefs.VersionStamp] RETURNS [name: ROPENIL] = {
... 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
name ← VersionMap.VersionToName[mapList, version].name;
};
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: ROPENIL;
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 ← "///CedarSource.VersionMap";
$Symbols => mapFileName ← "///CedarSymbols.VersionMap";
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", "///CedarSymbols.VersionMap"];
ProcessUserProfileList[$Source, "VersionMap.SourceMaps", "///CedarSource.VersionMap"];
};
ProcessUserProfileList: PROC [class: ATOM, key: ROPE, always: ROPE] = {
list: LIST OF ROPE ← UserProfile.ListOfTokens[key, NIL];
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 => IF error.group # bug THEN CONTINUE];
IF map # NIL THEN AddToMapList[class, map];
};
RemoveRope: PROC [list: LIST OF ROPE, item: ROPE] RETURNS [LIST OF ROPE] = {
lag: LIST OF ROPENIL;
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.