DIRECTORY FSPseudoServers USING [PseudoServerList], FSPseudoServersExtra USING [], IO USING [EndOfStream, GetTokenRope, IDProc, PutRope, RIS, RopeFromROS, ROS, STREAM], Rope USING [Compare, Equal, Fetch, Length, Match, ROPE, SkipTo, Substr]; FSPseudoServersImpl: CEDAR MONITOR IMPORTS IO, Rope EXPORTS FSPseudoServers, FSPseudoServersExtra = BEGIN OPEN FSPseudoServers; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; pseudoServers: PseudoServerList _ NIL; GetPseudoServers: PUBLIC ENTRY PROC RETURNS [PseudoServerList] = { RETURN [pseudoServers]; }; SetPseudoServers: PUBLIC ENTRY PROC [list: PseudoServerList] = { pseudoServers _ list; }; TranslateForWrite: PUBLIC PROC [server: ROPE] RETURNS [ROPE] = { FOR each: PseudoServerList _ pseudoServers, each.rest WHILE each # NIL DO IF Rope.Equal[each.first.server, server, FALSE] THEN RETURN [each.first.write]; ENDLOOP; RETURN [server]; }; TranslateForRead: PUBLIC PROC [server: ROPE] RETURNS [LIST OF ROPE] = { FOR each: PseudoServerList _ pseudoServers, each.rest WHILE each # NIL DO IF Rope.Equal[each.first.server, server, FALSE] THEN RETURN [each.first.read]; ENDLOOP; RETURN [LIST[server]]; }; AvoidRemoteCheck: PUBLIC PROC [server: ROPE] RETURNS [BOOL] = { FOR each: PseudoServerList _ pseudoServers, each.rest WHILE each # NIL DO IF Rope.Equal[each.first.server, server, FALSE] THEN RETURN [each.first.avoidCheck]; ENDLOOP; RETURN [FALSE]; }; Lookup: PUBLIC ENTRY PROC [server: ROPE] RETURNS [PseudoServerList] = { ENABLE UNWIND => NULL; lag: PseudoServerList _ NIL; FOR each: PseudoServerList _ pseudoServers, each.rest WHILE each # NIL DO SELECT Rope.Compare[server, each.first.server, FALSE] FROM equal => RETURN [each]; ENDCASE; lag _ each; ENDLOOP; RETURN [NIL]; }; DeletePseudoServer: PUBLIC ENTRY PROC [server: ROPE] RETURNS [PseudoServerList] = { ENABLE UNWIND => NULL; lag: PseudoServerList _ NIL; FOR each: PseudoServerList _ pseudoServers, each.rest WHILE each # NIL DO IF Rope.Equal[server, each.first.server, FALSE] THEN { IF lag = NIL THEN pseudoServers _ each.rest ELSE lag.rest _ each.rest; each.rest _ NIL; RETURN [each]; }; lag _ each; ENDLOOP; RETURN [NIL]; }; InsertPseudoServer: PUBLIC ENTRY PROC [new: PseudoServerList] = { ENABLE UNWIND => NULL; IF new # NIL THEN { lag: PseudoServerList _ NIL; server: ROPE _ new.first.server; FOR each: PseudoServerList _ pseudoServers, each.rest WHILE each # NIL DO SELECT Rope.Compare[server, each.first.server, FALSE] FROM less => { new.rest _ each; EXIT; }; equal => { new.rest _ each.rest; EXIT; }; ENDCASE; lag _ each; ENDLOOP; IF lag = NIL THEN pseudoServers _ new ELSE lag.rest _ new; }; }; RopeFromPseudoServer: PUBLIC PROC [list: PseudoServerList] RETURNS [ROPE _ NIL] = { IF list # NIL THEN { out: STREAM _ IO.ROS[]; IO.PutRope[out, list.first.server]; IF list.first.avoidCheck THEN IO.PutRope[out, " -r"]; IO.PutRope[out, " "]; IO.PutRope[out, list.first.write]; FOR each: LIST OF ROPE _ list.first.read, each.rest WHILE each # NIL DO IO.PutRope[out, " "]; IO.PutRope[out, each.first]; ENDLOOP; RETURN [IO.RopeFromROS[out]]; }; }; PseudoServerFromRope: PUBLIC PROC [rope: ROPE] RETURNS [error: ROPE _ NIL, new: PseudoServerList _ NIL] = { ris: STREAM _ IO.RIS[rope]; server: ROPE _ IO.GetTokenRope[ris, IO.IDProc ! IO.EndOfStream => GO TO bogusLine].token; IF LegalName[server] THEN { readTail: LIST OF ROPE _ NIL; new _ LIST [[server: server, avoidCheck: FALSE, write: NIL, read: NIL]]; DO token: ROPE _ IO.GetTokenRope[ris, IO.IDProc ! IO.EndOfStream => EXIT].token; IF NOT LegalName[token] THEN RETURN ["illegal token in rope", NIL]; IF Rope.Equal[token, "-r", FALSE] THEN {new.first.avoidCheck _ TRUE; LOOP}; IF Rope.Match["-*", token] THEN LOOP; token _ StripBrackets[token]; IF new.first.write = NIL THEN {new.first.write _ token; LOOP}; IF readTail = NIL THEN {new.first.read _ readTail _ LIST[token]; LOOP}; readTail.rest _ LIST[token]; readTail _ readTail.rest; ENDLOOP; IF new.first.write = NIL THEN RETURN ["no write server", NIL]; IF new.first.read = NIL THEN RETURN ["no read servers", NIL]; RETURN; }; RETURN["illegal name in server rope", NIL]; EXITS bogusLine => RETURN["empty server rope", NIL]; }; StripBrackets: PROC [name: ROPE] RETURNS [ROPE] = { len: INT _ Rope.Length[name]; pos1: INT _ Rope.SkipTo[name, 0, "["]; pos2: INT _ Rope.SkipTo[name, 0, "]"]; nlen: INT _ pos2-pos1-1; IF pos2 = len AND pos1 = len AND len > 0 THEN RETURN [name]; IF nlen <= 0 THEN RETURN [NIL]; RETURN [Rope.Substr[name, pos1+1, nlen]]; }; LegalName: PROC [rope: ROPE] RETURNS [BOOL] = { len: INT _ Rope.Length[rope]; IF len = 0 THEN RETURN [FALSE]; FOR i: INT IN [0..Rope.Length[rope]) DO SELECT Rope.Fetch[rope, i] FROM IN [41C..'z] => {}; ENDCASE => RETURN [FALSE]; ENDLOOP; RETURN [TRUE]; }; END. κFSPseudoServersImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Russ Atkinson, October 18, 1984 9:59:10 pm PDT Translates the server name into the server name specified for writing. If no such translation is present, returns the original server name. Translates the server name into the server names specified for reading. If no such translation is present, returns a list containing the original server name. Determines if the server name implies not checking for remote versions. This is useful to reduce server traffic in cases where the files are known to be frozen. ... returns the PseudoServerList for the given name (NIL if no such translation). ... deletes the given pseudo server (if any) from the root PseudoServerList, and returns the deleted element from the list (NIL if no such element). ... inserts the first item in the PseudoServerList into the root PseudoServerList. Insert into the new position in the list Insert into the new position in the list, splice out old entry ... turns the first entry in the PseudoServerList into a rope parsable by PseudoServerFromRope. If list = NIL, NIL is returned. ... parses the given rope, returning an error message if there was an error, and NIL if there was no error. ΚZ˜šœ™Jšœ Οmœ1™™>Jšœ˜Jšžœ˜J˜—Jšžœ˜—Jšœ ˜ Jšžœ˜—Jšžœžœžœžœ˜:J˜—J˜J˜—š Ÿœžœžœžœžœžœ˜SJšœkžœžœ ™€šžœžœžœ˜Jšœžœžœžœ˜Jšžœ!˜#Jšžœžœžœ˜5Jšžœ˜Jšžœ ˜"š žœžœžœžœžœžœž˜GJšžœ˜Jšžœ˜Jšžœ˜—Jšžœžœ˜J˜—J˜J˜—codešŸœžœžœžœžœ žœžœžœ˜kJšœk™kJšœžœžœžœ˜Jš œžœžœžœ žœžœžœ˜Yšžœžœ˜Jš œ žœžœžœžœ˜Jš œžœžœ žœžœ˜Hšž˜Jš œžœžœžœ žœžœ˜MJš žœžœžœžœžœ˜CJš žœžœžœžœžœ˜KJšžœžœžœ˜%Jšœ˜Jšžœžœžœžœ˜>Jš žœ žœžœžœ žœ˜GJšœžœ˜Jšœ˜Jšžœ˜—Jš žœžœžœžœžœ˜>Jš žœžœžœžœžœ˜=Jšžœ˜J˜—Jšžœ žœ˜+Jšžœžœžœ˜4J˜J˜—š Ÿ œžœžœžœžœ˜3Jšœžœ˜Jšœžœ˜&Jšœžœ˜&Jšœžœ˜Jš žœ žœ žœ žœžœ˜