FSPseudoServersImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Russ Atkinson (RRA) October 24, 1985 3:06:35 pm PDT
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] = {
Translates the server name into the server name specified for writing. If no such translation is present, returns the original server name.
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] = {
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.
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] = {
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.
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 => {
Insert into the new position in the list
new.rest ← each;
EXIT;
};
equal => {
Insert into the new position in the list, splice out old entry
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 [ROPENIL] = {
... turns the first entry in the PseudoServerList into a rope parsable by PseudoServerFromRope. If list = NIL, NIL is returned.
IF list # NIL THEN {
out: STREAMIO.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: ROPENIL, 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: STREAMIO.RIS[rope];
readTail: LIST OF ROPENIL;
new ← LIST [[server: NIL, avoidCheck: FALSE, write: NIL, read: NIL]];
DO
token: ROPEIO.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.