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.