<> <> <> DIRECTORY FSPseudoServers USING [PseudoServerList], 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 = 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] = { <<... returns the PseudoServerList for the given name (NIL if no such translation).>> 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] = { <<... deletes the given pseudo server (if any) from the root PseudoServerList, and returns the deleted element from the list (NIL if no such element).>> 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] = { <<... inserts the first item in the PseudoServerList into the root 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] = { <<... turns the first entry in the PseudoServerList into a rope parsable by PseudoServerFromRope. If list = NIL, NIL is returned.>> 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] = { <<... parses the given rope, returning an error message if there was an error, and error = NIL if there was no error.>> ris: STREAM _ IO.RIS[rope]; readTail: LIST OF ROPE _ NIL; new _ LIST [[server: NIL, avoidCheck: FALSE, write: NIL, read: NIL]]; DO token: ROPE _ IO.GetTokenRope[ris, IO.IDProc ! IO.EndOfStream => EXIT].token; IF Rope.Match["-*", token] THEN { IF Rope.Equal[token, "-r", FALSE] THEN new.first.avoidCheck _ TRUE; LOOP; }; IF NOT LegalName[token] THEN RETURN ["illegal name", NIL]; token _ StripBrackets[token]; SELECT TRUE FROM new.first.server = NIL => new.first.server _ token; new.first.write = NIL => new.first.write _ token; readTail = NIL => new.first.read _ readTail _ LIST[token]; ENDCASE => readTail _ (readTail.rest _ LIST[token]); ENDLOOP; SELECT TRUE FROM new.first.server = NIL => RETURN ["no server name", NIL]; new.first.write = NIL => RETURN ["no write server", NIL]; new.first.read = NIL => RETURN ["no read servers", NIL]; ENDCASE; }; 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.