PDRemoteStreamStub.mesa
Copyright (C) 1984, Xerox Corporation. All rights reserved.
Michael Plass, September 5, 1984 10:18:39 pm PDT
DIRECTORY IO, Stream, STP, Rope, PDRemoteStream, String, Commander, PDQueue;
PDRemoteStreamStub: PROGRAM
IMPORTS Rope, STP, String, Stream, Commander, PDQueue, IO
EXPORTS PDRemoteStream
= BEGIN
Error: PUBLIC ERROR [expl: LONG STRING, retryable: BOOL] = CODE;
RopeFromString: PROC [string: LONG STRING] RETURNS [Rope.ROPE] = {
i: INTEGER ← -1;
fet: SAFE PROC RETURNS [CHAR] = TRUSTED {RETURN [string[i←i+1]]};
IF string = NIL THEN RETURN [NIL];
RETURN [Rope.FromProc[string.length, fet]];
};
Rs: PROC [string: LONG STRING] RETURNS [Rope.ROPE] = RopeFromString;
AppendRope: PROC [string: LONG STRING, rope: Rope.ROPE] = {
action: Rope.ActionType = TRUSTED {
string[string.length] ← c;
string.length ← string.length + 1;
};
[] ← rope.Map[action: action];
};
Retryable: PROC [code: STP.ErrorCode] RETURNS [BOOL] = {
RETURN [SELECT code FROM connectionTimedOut, connectionRejected, connectionClosed, noConnection, noNameLookupResponse => TRUE, ENDCASE => FALSE]
};
Lookup: PUBLIC PROC [fileName: LONG STRING, createDate: LONG STRING, name, password: LONG STRING] RETURNS [bytes: INT] = {
bytes ← MyLookup[fileName, createDate, name, password !
STP.Error => TRUSTED {
expl: LONG STRING ← [80];
AppendRope[expl, error];
ERROR Error[expl: expl, retryable: Retryable[code]]
};
];
};
ParseTest: PROC [fileName: Rope.ROPE] RETURNS [server, rest: Rope.ROPE] = {
f: LONG STRING ← [80];
s: LONG STRING ← [80];
r: LONG STRING ← [80];
AppendRope[f, fileName];
ParseName[f, s, r];
server ← Rs[s];
rest ← Rs[r];
};
ParseName: PUBLIC PROC [fileName, server, rest: LONG STRING] = {
state: NAT ← 0;
server.length ← 0;
rest.length ← 0;
FOR i: NAT IN [0..fileName.length) DO
c: CHAR ← fileName[i];
charType: NATSELECT c FROM
'[ => 0,
'/ => 1,
'] => 2,
'< => 3,
'> => 4,
'! => 5,
IN ['0..'9], IN ['a..'z], IN ['A..'Z] => 6,
'-, '+, '$, '., '' => 6
ENDCASE => Error[expl: "Illegal character in filename", retryable: FALSE];
SELECT state*7+charType FROM
0*7+0 => state ← 1;
0*7+1 => state ← 7;
1*7+6 => {server[server.length] ← c; server.length ← server.length + 1};
1*7+2 => state ← 2;
2*7+3 => {state ← 3; rest[rest.length] ← '<; rest.length ← rest.length + 1};
3*7+6,
3*7+4 => {rest[rest.length] ← c; rest.length ← rest.length + 1};
3*7+5 => {state ← 4; rest[rest.length] ← c; rest.length ← rest.length + 1};
4*7+6 => {
rest[rest.length] ← c; rest.length ← rest.length + 1;
IF c IN ['0..'9] THEN state ← 5
ELSE IF c = 'l OR c = 'L OR c = 'h OR c='H THEN state ← 6
ELSE state ← 9
};
5*7+6 => {
rest[rest.length] ← c; rest.length ← rest.length + 1;
IF c NOT IN ['0..'9] THEN state ← 9
};
7*7+6 => {server[server.length] ← c; server.length ← server.length + 1};
7*7+1 => {state ← 8; rest[rest.length] ← '<; rest.length ← rest.length + 1};
7*8+6 => {rest[rest.length] ← c; rest.length ← rest.length + 1};
7*8+1 => {rest[rest.length] ← '>; rest.length ← rest.length + 1};
7*8+5 => {state ← 4; rest[rest.length] ← c; rest.length ← rest.length + 1};
ENDCASE => Error[expl: "Illegal filename", retryable: FALSE];
ENDLOOP;
SELECT state FROM
3, 8 => {rest[rest.length] ← '!; rest[rest.length+1] ← 'H; rest.length ← rest.length + 2};
5, 6 => NULL;
ENDCASE => Error[expl: "Illegal filename", retryable: FALSE];
};
MyLookup: PROC [fileName, createDate, name, password: LONG STRING] RETURNS [bytes: INT ← 0] = {
server: LONG STRING ← [80];
rest: LONG STRING ← [80];
stp: STP.Handle ← STP.Create[];
open: BOOLFALSE;
BEGIN ENABLE UNWIND => {
IF open THEN stp.Close[ ! STP.Error => TRUSTED {CONTINUE}];
stp ← stp.Destroy
};
expandedName: LONG STRING ← [80];
success: BOOLEANFALSE;
NoteFileProc: STP.NoteFileProcType = TRUSTED {
fileInfo: STP.FileInfo ← stp.GetFileInfo[];
continue ← no;
success ← TRUE;
AppendRope[expandedName, file];
bytes ← fileInfo.size;
createDate.length ← 0;
AppendRope[createDate, fileInfo.create];
};
desiredProps: STP.DesiredProperties ← ALL[FALSE];
desiredProps[directory] ← TRUE;
desiredProps[nameBody] ← TRUE;
desiredProps[version] ← TRUE;
desiredProps[createDate] ← TRUE;
desiredProps[size] ← TRUE;
ParseName[fileName, server, rest];
String.AppendChar[expandedName, '[ ];
String.AppendString[expandedName, server];
String.AppendChar[expandedName, '] ];
[] ← stp.Open[Rs[server]];
open ← TRUE;
stp.Login[Rs[name], Rs[password]];
stp.SetDesiredProperties[desiredProps];
stp.Enumerate[Rs[rest], NoteFileProc];
stp.Close[ ! STP.Error => TRUSTED {CONTINUE}];
stp ← stp.Destroy;
IF success THEN {String.Copy[to: fileName, from: expandedName]}
ELSE Error[expl: "File not found", retryable: FALSE];
END;
};
Read: PUBLIC PROC [fileName: LONG STRING, name, password: LONG STRING, action: PROC[Stream.Handle]] = {
MyRead[fileName, name, password, action !
STP.Error => TRUSTED {
expl: LONG STRING ← [80];
AppendRope[expl, error];
ERROR Error[expl: expl, retryable: Retryable[code]]
};
];
};
MyRead: PROC [fileName: LONG STRING, name, password: LONG STRING, action: PROC[Stream.Handle]] = {
server: LONG STRING ← [80];
rest: LONG STRING ← [80];
stp: STP.Handle ← STP.Create[];
open: BOOLFALSE;
stream: Stream.Handle;
BEGIN ENABLE UNWIND => {
IF open THEN stp.Close[ ! STP.Error => TRUSTED {CONTINUE}];
stp ← stp.Destroy
IF stream # NIL THEN {stream.Delete; stream ← NIL};
};
ParseName[fileName, server, rest];
[] ← stp.Open[Rs[server]];
open ← TRUE;
stp.Login[Rs[name], Rs[password]];
stream ← Stream.FromIOStreams[stp.CreateRemoteStream[Rs[rest], read], NIL];
action[stream];
stp.Close[ ! STP.Error => TRUSTED {CONTINUE}];
stp ← stp.Destroy;
stream.Delete;
stream ← NIL
END;
};
PeachLogCommand: Commander.CommandProc = TRUSTED {
out ← cmd.out;
PDQueue.RegisterTTY[WriteLine];
[] ← PDQueue.SetLogState[TRUE];
};
out: IO.STREAMNIL;
WriteLine: PROC [line: LONG STRING] ~ {
out.PutRope[Rs[line]];
out.PutRope["\n"];
};
Commander.Register["PeachLog", PeachLogCommand, ""];
END.