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