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.