<> <> <> <> <<>> 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; <> 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)>> < 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]; FileNameFromVersion: PUBLIC PROC [which: ATOM, version: BcdDefs.VersionStamp] RETURNS [name: ROPE _ NIL] = { <<... 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: 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 _ "///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; <> 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; <> 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 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.