<> <> <> <> <> <> DIRECTORY PFSNames, PFSPrefixMap, PFSPrefixMapExtras, Rope ; PFSPrefixMapImpl: CEDAR MONITOR IMPORTS PFSNames EXPORTS PFSPrefixMap, PFSPrefixMapExtras = BEGIN OPEN PFSPrefixMap, PFSPrefixMapExtras; ROPE: TYPE = Rope.ROPE; defaultPrefixTable: PrefixTableList _ NIL; GetMap: PUBLIC ENTRY PROC RETURNS [el: EntryList] ~ { RETURN[ GetMapInternal[NIL] ] }; GetMapFromPTable: PUBLIC ENTRY PROC[pTable: PrefixTableList] RETURNS [el: EntryList] ~ { RETURN[ GetMapInternal[pTable] ] }; GetMapInternal: INTERNAL PROC[pTable: PrefixTableList] RETURNS [el: EntryList] ~ { IF pTable = NIL THEN pTable _ defaultPrefixTable; FOR each: PrefixTableList _ pTable, each.rest WHILE each # NIL DO el _ CONS[ [each.first.prefix, each.first.translation], el]; ENDLOOP; }; SetMap: PUBLIC ENTRY PROC[map: EntryList] ~ { defaultPrefixTable _ FromMapInternal[map] }; SetMapFromPTable: PUBLIC ENTRY PROC[pTable: PrefixTableList] ~ { defaultPrefixTable _ pTable }; FromMapToPTable: PUBLIC ENTRY PROC[map: EntryList] RETURNS[PrefixTableList] ~ { RETURN[FromMapInternal[map]] }; FromMapInternal: INTERNAL PROC[map: EntryList] RETURNS[pTable: PrefixTableList _ NIL] ~ { FOR each: EntryList _ map, each.rest WHILE each # NIL DO pTable _ InsertInternal[NIL, each.first.prefix, each.first.translation]; ENDLOOP; }; Translate: PUBLIC ENTRY PROC [name: PATH] RETURNS [PATH] ~ { RETURN[InnerTranslate[name, NIL]] }; TranslateWithPTable: PUBLIC ENTRY PROC [name: PATH, pTable: PrefixTableList _ NIL] RETURNS [PATH] ~ { RETURN[InnerTranslate[name, pTable]] }; InnerTranslate: INTERNAL PROC [name: PATH, pTable: PrefixTableList] RETURNS [PATH] ~ { <> ENABLE UNWIND => NULL; len: INT _ -1; entry: PrefixTableEntry _ []; IF pTable = NIL THEN pTable _ defaultPrefixTable; FOR each: PrefixTableList _ pTable, each.rest WHILE each # NIL DO matchLen: INT _ Match[name, each.first.prefix]; IF matchLen > len THEN { len _ matchLen; entry _ each.first; }; ENDLOOP; IF ( len = -1 ) THEN RETURN[ name ]; RETURN[ PFSNames.Cat[ entry.translation, PFSNames.SubName[name~name, start~len, directory~PFSNames.IsADirectory[name]]] ]; }; TranslateAndGetHints: PUBLIC ENTRY PROC [name: PATH] RETURNS [TranslationWithHints] ~ { RETURN[InnerTranslateAndGetHints[name, NIL]] }; TranslateAndGetHintsWithPTable: PUBLIC ENTRY PROC [name: PATH, pTable: PrefixTableList] RETURNS [TranslationWithHints] ~ { RETURN[InnerTranslateAndGetHints[name, pTable]] }; InnerTranslateAndGetHints: INTERNAL PROC [name: PATH, pTable: PrefixTableList] RETURNS [TranslationWithHints] ~ { <> ENABLE UNWIND => NULL; len: INT _ -1; translatedName: PATH; entry: PrefixTableEntry _ []; IF pTable = NIL THEN pTable _ defaultPrefixTable; FOR each: PrefixTableList _ pTable, each.rest WHILE each # NIL DO matchLen: INT _ Match[name, each.first.prefix]; IF matchLen > len THEN { len _ matchLen; entry _ each.first; }; ENDLOOP; IF ( len = -1 ) THEN RETURN[ [ translation: name, fsName: PFSNames.ComponentRope[PFSNames.Fetch[name, 0]], nameOnFS: PFSNames.ReplaceComponent[name: name, index: 0, new: []], replacedPrefix: IF name.ComponentCount[]>0 THEN name.SubName[0, 1, name.IsAbsolute[], TRUE] ELSE NIL, suppliedPrefixLen: IF name.ComponentCount[]>0 THEN 1 ELSE 0 ] ]; translatedName _ PFSNames.Cat[ entry.translation, PFSNames.SubName[name~name, start~len, directory~PFSNames.IsADirectory[name]]]; RETURN[ [ translation: translatedName, fsName: entry.fsName, nameOnFS: PFSNames.ReplaceComponent[name: translatedName, index: 0, new: []], replacedPrefix: entry.prefix, suppliedPrefixLen: entry.suppliedPrefixLen ] ]; }; Match: PROC [name, prefix: PATH] RETURNS [matchLen: INT _ -1] ~ { prefixLen: CARD _ PFSNames.ComponentCount[prefix]; nameLen: CARD _ PFSNames.ComponentCount[name]; IF (prefix.IsAbsolute[] # name.IsAbsolute[]) OR (nameLen < prefixLen) THEN RETURN[ -1 ]; FOR i: CARD IN [0..prefixLen) DO IF NOT PFSNames.EqualComponents[PFSNames.Fetch[name, i], PFSNames.Fetch[prefix, i]] THEN RETURN [-1]; ENDLOOP; RETURN[prefixLen]; }; Lookup: PUBLIC ENTRY PROC [prefix: PATH] RETURNS [PATH] ~ { RETURN[InnerLookup[prefix, NIL]] }; LookupWithPTable: PUBLIC ENTRY PROC [prefix: PATH, pTable: PrefixTableList] RETURNS [PATH] ~ { RETURN[InnerLookup[prefix, pTable]] }; InnerLookup: INTERNAL PROC [prefix: PATH, pTable: PrefixTableList] RETURNS [PATH] ~ { <<... returns the PrefixTable entry for the given name ([NIL, NIL] if no such translation).>> ENABLE UNWIND => NULL; IF pTable = NIL THEN pTable _ defaultPrefixTable; FOR each: PrefixTableList _ pTable, each.rest WHILE each # NIL DO IF PFSNames.Equal[prefix, each.first.prefix] THEN { RETURN[each.first.translation]; }; ENDLOOP; RETURN [NIL]; }; <<>> Delete: PUBLIC ENTRY PROC [name: PATH] RETURNS [existing: PATH] ~ { [existing, defaultPrefixTable] _ InnerDelete[name, NIL] }; DeleteFromPTable: PUBLIC ENTRY PROC [name: PATH, pTable: PrefixTableList] RETURNS [existing: PATH, newPTable: PrefixTableList] ~ { [existing, newPTable] _ InnerDelete[name, pTable] }; InnerDelete: INTERNAL PROC [name: PATH, pTable: PrefixTableList] RETURNS [existing: PATH, newPTable: PrefixTableList] ~ { <<... deletes the given prefix (if any) from the map, and returns the deleted element ([NIL, NIL] if no such element).>> ENABLE UNWIND => NULL; lag: PrefixTableList _ NIL; IF pTable = NIL THEN pTable _ defaultPrefixTable; newPTable _ pTable; FOR each: PrefixTableList _ pTable, each.rest WHILE each # NIL DO IF PFSNames.Equal[name, each.first.prefix] THEN { IF lag = NIL THEN newPTable _ each.rest ELSE lag.rest _ each.rest; each.rest _ NIL; RETURN [each.first.translation, newPTable]; }; lag _ each; ENDLOOP; RETURN [NIL, newPTable]; }; Insert: PUBLIC ENTRY PROC [prefix: PATH, translation: PATH] ~ { defaultPrefixTable _ InsertInternal[NIL, prefix, translation] }; InsertIntoNewPTable: PUBLIC ENTRY PROC[prefix: PATH, translation: PATH] RETURNS[newPTable: PrefixTableList] ~ { newPTable _ LIST[MakePrefixTableEntry[prefix, translation]]; }; InsertIntoPTable: PUBLIC ENTRY PROC[prefix: PATH, translation: PATH, pTable: PrefixTableList] RETURNS[newPTable: PrefixTableList] ~ { newPTable _ InsertInternal[pTable, prefix, translation] }; InsertInternal: INTERNAL PROC [pTable: PrefixTableList, prefix: PATH, translation: PATH] RETURNS[newPTable: PrefixTableList] ~ { <<... inserts the first item in the PseudoServerList into the root PseudoServerList.>> ENABLE UNWIND => NULL; IF pTable = NIL THEN newPTable _ defaultPrefixTable ELSE newPTable _ pTable; IF prefix#NIL THEN { lag: PrefixTableList _ NIL; newList: PrefixTableList _ LIST[MakePrefixTableEntry[prefix, translation]]; FOR each: PrefixTableList _ newPTable, each.rest WHILE each # NIL DO SELECT PFSNames.Compare[prefix, each.first.prefix, FALSE] FROM less => { <> newList.rest _ each; EXIT; }; equal => { <> newList.rest _ each.rest; EXIT; }; ENDCASE; lag _ each; ENDLOOP; IF lag = NIL THEN newPTable _ newList ELSE lag.rest _ newList; }; }; MakePrefixTableEntry: PROC [prefix: PATH, translation: PATH] RETURNS[PrefixTableEntry] ~ { RETURN[ [ prefix: prefix, translation: translation, fsName: PFSNames.ComponentRope[PFSNames.Fetch[translation, 0]], suppliedPrefixLen: PFSNames.ComponentCount[translation] ] ]; }; END.