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 [
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.