<> <> <> <<>> 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; <> 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]; 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; <> 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", 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; <> 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.