XCommunicationsImpl.mesa
Copyright Ó 1988, 1989, 1991 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, July 29, 1988 5:51:46 pm PDT
Christian Jacobi, March 1, 1989 9:42:32 am PST
DIRECTORY
Ascii, Atom, XCommunications, IO, Rope, SymTab;
XCommunicationsImpl:
CEDAR
MONITOR
IMPORTS Atom, Rope, SymTab
EXPORTS XCommunications
SHARES IO
~ BEGIN OPEN XCommunications;
Error: PUBLIC ERROR [what: Rope.ROPE] = CODE;
protocolsReg: SymTab.Ref ¬ SymTab.Create[case: FALSE];
applicationsReg: Atom.PropList ¬ NIL; --elements PropList's again
RegisterCommunication:
PUBLIC
PROC [protocolData: ProtocolData] = {
protocolData.success ¬ TRUE;
[] ¬ SymTab.Store[protocolsReg, Atom.GetPName[protocolData.protocol], NEW[ProtocolData¬protocolData]];
};
RegisterScanSpecific:
PUBLIC
ENTRY
PROC [application:
ATOM, protocol:
ATOM, scan: ScanProcType] = {
protocolsForApp: Atom.PropList ¬ NARROW[Atom.GetPropFromList[applicationsReg, application]];
protocolsForApp ¬ Atom.PutPropOnList[protocolsForApp, protocol, NEW[ScanProcType ¬ scan]];
applicationsReg ¬ Atom.PutPropOnList[applicationsReg, application, protocolsForApp];
};
ScanName:
PUBLIC PROC [name: Rope.
ROPE]
RETURNS [sn: ScannedName ¬ [
NIL,
NIL,
NIL]] = {
leng: INT ¬ Rope.Length[name];
SkipChar:
PROC [pos:
INT]
RETURNS [
BOOL] = {
SELECT Rope.Fetch[name, pos]
FROM
Ascii.SP, Ascii.NUL, Ascii.FF, Ascii.LF, Ascii.CR, Ascii.TAB => RETURN [TRUE];
ENDCASE => RETURN [FALSE];
};
SubString:
PROC [first, firstNot:
INT]
RETURNS [r: Rope.
ROPE¬NIL] = {
firstNot ¬ MIN[firstNot, leng];
WHILE firstNot>first AND SkipChar[first] DO first ¬ first+1 ENDLOOP;
WHILE firstNot>first AND SkipChar[firstNot-1] DO firstNot ¬ firstNot-1 ENDLOOP;
IF firstNot>first THEN r ¬ Rope.Substr[name, first, firstNot-first];
};
pos1, pos2: INT;
pos1 ¬ Rope.SkipTo[name, 0, "%"];
IF pos1<leng THEN {sn.protocol ¬ SubString[0, pos1]; pos1 ¬ pos1+1} ELSE pos1 ¬ 0;
pos2 ¬ Rope.SkipTo[name, pos1, ":"];
sn.server ¬ SubString[pos1, pos2];
IF pos2<leng THEN {pos2 ¬ pos2+1};
sn.specific ¬ SubString[pos2, LAST[INT]];
};
GetProtocol:
PUBLIC
PROC [protocol: Rope.
ROPE, defaultProtocol:
ATOM ¬
NIL]
RETURNS [pd: ProtocolData ¬ []] = {
IF Rope.IsEmpty[protocol]
AND defaultProtocol#
NIL
THEN
protocol ¬ Atom.GetPName[defaultProtocol];
WITH SymTab.Fetch[protocolsReg, protocol].val
SELECT
FROM
rpd: REF ProtocolData => pd ¬ rpd;
ENDCASE => {};
};
GetScanner:
PROC [application:
ATOM, protocol:
ATOM]
RETURNS [scanner: ScanProcType¬
NIL] = {
protocolsForApp: Atom.PropList ¬ NARROW[Atom.GetPropFromList[applicationsReg, application]];
IF protocolsForApp#
NIL
THEN
WITH Atom.GetPropFromList[protocolsForApp, protocol]
SELECT
FROM
s: REF ScanProcType => scanner ¬ s;
ENDCASE => {};
};
ScanSpecific:
PUBLIC
PROC [application:
ATOM, protocol:
ATOM, scannedName: ScannedName]
RETURNS [base: Rope.
ROPE, port:
REF
ANY] = {
scanner: ScanProcType;
IF protocol=
NIL
THEN {
pd: ProtocolData ¬ GetProtocol[scannedName.protocol];
IF pd.protocol=NIL OR ~pd.success THEN ERROR Error["protocol not registered"];
protocol ¬ pd.protocol
};
scanner ¬ GetScanner[application, protocol];
IF scanner=NIL THEN ERROR Error["application not registered"];
[base, port] ¬ scanner[application, protocol, scannedName];
};
CreateStreams:
PUBLIC
PROC [application:
ATOM, name: Rope.
ROPE, defaultProtocol:
ATOM ¬
NIL]
RETURNS [sd: StreamData] = {
base: Rope.ROPE; port: REF ANY;
scannedName: ScannedName ¬ ScanName[name];
pData: ProtocolData ¬ GetProtocol[scannedName.protocol, defaultProtocol];
IF NOT pData.success OR pData.create=NIL THEN {sd.errorMsg ¬ "unknown protocol"; RETURN};
[base, port] ¬ ScanSpecific[application, pData.protocol, scannedName ! Error => GOTO Oops];
[sd] ¬ pData.create[base, port];
[sd] ¬ FinishStreamData[sd];
EXITS Oops => sd.errorMsg ¬ "application does not support protocol";
};
FinishStreamData:
PUBLIC PROC [sd: StreamData]
RETURNS [d: StreamData] = {
IF sd.success
THEN {
IF sd.in=
NIL
OR sd.out=
NIL
THEN {
sd.success ¬ FALSE; IF Rope.IsEmpty[sd.errorMsg] THEN sd.errorMsg ¬ "no streams created"
}
ELSE {
IF sd.putChar=NIL THEN sd.putChar ¬ sd.out.streamProcs.putChar;
IF sd.unsafePutBlock=NIL THEN sd.unsafePutBlock ¬ sd.out.streamProcs.unsafePutBlock;
IF sd.getChar=NIL THEN sd.getChar ¬ sd.in.streamProcs.getChar;
IF sd.sendNow=NIL THEN sd.sendNow ¬ sd.out.streamProcs.flush;
IF sd.errorFromStream=NIL THEN sd.errorFromStream ¬ DefaultErrorFromStream;
}
};
RETURN [sd];
};
DefaultErrorFromStream:
PROC [self:
IO.
STREAM]
RETURNS [Rope.
ROPE] = {
RETURN ["failure"];
};
END.