<<>> <> <> <> <> <> <> <> <<>> DIRECTORY Basics, CirioNub, CirioNubPrivate, IO, NetworkStream, RefText, Rope ; CirioNubImpl: CEDAR PROGRAM IMPORTS Basics, IO, NetworkStream, RefText, Rope EXPORTS CirioNub ~ { <> ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; ProcID: TYPE ~ CirioNub.ProcID; Block16: TYPE ~ CirioNub.Block16; Block16Record: TYPE ~ CirioNub.Block16Record; Block32: TYPE ~ CirioNub.Block32; Block32Record: TYPE ~ CirioNub.Block32Record; CallResult: TYPE ~ CirioNub.CallResult; CallResultRecord: TYPE ~ CirioNub.CallResultRecord; ReturnCode: TYPE ~ CirioNub.ReturnCode; Wrapper: TYPE ~ CirioNubPrivate.Wrapper; Tag: TYPE ~ CirioNubPrivate.Tag; nullProcID: ProcID ~ CARD.LAST; WrapperAndFWord: TYPE ~ --WORD16-- MACHINE DEPENDENT RECORD [ wrapper: Wrapper, fWord: Basics.FWORD ]; Handle: TYPE ~ REF Object; Object: PUBLIC TYPE ~ RECORD [ debuggee: ROPE, streamIn: STREAM ¬ NIL, streamOut: STREAM ¬ NIL, procBeingCalled: ProcID ¬ nullProcID, putBlockDeficit: CARD ¬ 0 ]; <> wordSize: WORD ¬ Basics.bytesPerWord; wordSizeMask: WORD ¬ Basics.BITNOT[(wordSize-1)]; wellKnownDebuggee: ROPE ¬ ":4815"; defaultProtocolFamily: ATOM ¬ $ARPA; FixDebuggeeRope: PROC [family: ATOM, debuggee: ROPE] RETURNS [fixed: ROPE] ~ { IF family # $ARPA THEN RETURN [debuggee]; IF Rope.IsEmpty[debuggee] THEN RETURN [wellKnownDebuggee]; IF Rope.Find[debuggee, ":"] = -1 THEN RETURN [Rope.Concat[debuggee, wellKnownDebuggee]]; RETURN [debuggee]; }; RoundUp: PROC [x: WORD] RETURNS [WORD] ~ INLINE { RETURN[ Basics.BITAND[x+(wordSize-1), LOOPHOLE[wordSizeMask]] ] }; <> Error: PUBLIC ERROR [code: ATOM] ~ CODE; <> CallEnabled: PROC [proc: PROC] ~ { ENABLE NetworkStream.Error, IO.Error, IO.EndOfStream => ERROR Error[$communicationFailureFromCallEnabled]; proc[]; }; <> Create: PUBLIC PROC [protocolFamily: ATOM, debuggee: ROPE, timeoutMsec: CARD] RETURNS [h: Handle] ~ { IF protocolFamily = NIL THEN protocolFamily ¬ defaultProtocolFamily; h ¬ NEW[Object ¬ [debuggee~FixDebuggeeRope[protocolFamily, debuggee]]]; { ENABLE { NetworkStream.Error, IO.Error => ERROR Error[$connectError]; NetworkStream.Timeout => ERROR Error[$timeout]; }; [in~h.streamIn, out~h.streamOut] ¬ NetworkStream.CreateStreams[ protocolFamily, debuggee, $basicStream, timeoutMsec, NIL ]; }; <> }; Destroy: PUBLIC PROC [h: Handle] ~ { ENABLE IO.Error, IO.EndOfStream, NetworkStream.Error, NetworkStream.Timeout => CONTINUE; s: STREAM; s ¬ h.streamIn; h.streamIn ¬ NIL; IO.Close[s, TRUE]; s ¬ h.streamOut; h.streamOut ¬ NIL; IO.Close[s, TRUE]; }; StartCall: PUBLIC PROC [h: Handle, procID: ProcID] ~ { IF h.streamOut = NIL THEN ERROR Error[$noConnectionFromStartCall]; h.putBlockDeficit ¬ 0; IF h.procBeingCalled # nullProcID THEN ERROR; h.procBeingCalled ¬ procID; }; MakeUpPutBlockDeficit: PROC [h: Handle] ~ { buf: CARD32 ¬ 0; WHILE h.putBlockDeficit > 0 DO len: INT ~ MIN[h.putBlockDeficit, 4]; TRUSTED { IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@buf]], startIndex~0, count~len] ]; }; h.putBlockDeficit ¬ h.putBlockDeficit - len; ENDLOOP; }; Put32Inner: PROC [h: Handle, card32: CARD32, tag: Tag] ~ { DoPut32Inner: PROC ~ { wf: WrapperAndFWord ¬ [ wrapper ~ [ tag ~ Basics.HFromCard16[ORD[tag]], len ~ Basics.HFromCard16[BYTES[CARD32]] ], fWord ~ Basics.FFromCard32[card32] ]; IF h.streamOut = NIL THEN ERROR Error[$noConnectionFromPut32Inner]; IF h.putBlockDeficit # 0 THEN MakeUpPutBlockDeficit[h]; TRUSTED { IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@wf]], startIndex~0, count~BYTES[WrapperAndFWord]] ]; }; }; CallEnabled[DoPut32Inner]; }; PutCard32: PUBLIC PROC [h: Handle, card32: CARD32] ~ { Put32Inner[h, card32, card32]; }; PutInt32: PUBLIC PROC [h: Handle, int32: INT32] ~ { Put32Inner[h, LOOPHOLE[int32, CARD32], int32]; }; PutRope: PUBLIC PROC [h: Handle, rope: ROPE] ~ { DoPutRope: PROC ~ { len: CARD16 ¬ CARD16[Rope.Length[rope]]; w: Wrapper ¬ [ tag ~ Basics.HFromCard16[ORD[Tag.string]], len ~ Basics.HFromCard16[len] ]; IF h.streamOut = NIL THEN ERROR Error[$noConnectionFromPutRope]; IF h.putBlockDeficit # 0 THEN MakeUpPutBlockDeficit[h]; TRUSTED { IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@w]], startIndex~0, count~BYTES[Wrapper]] ]; }; h.putBlockDeficit ¬ RoundUp[len]; IO.PutRope[h.streamOut, rope]; h.putBlockDeficit ¬ h.putBlockDeficit - len; }; CallEnabled[DoPutRope]; }; PutBlock8: PUBLIC PROC [h: Handle, block8: REF TEXT] ~ { DoPutBlock8: PROC ~ { len: CARD16 ¬ block8.length; w: Wrapper ¬ [ tag ~ Basics.HFromCard16[ORD[Tag.block8]], len ~ Basics.HFromCard16[len] ]; IF h.streamOut = NIL THEN ERROR Error[$noConnectionFromPutBlock8]; IF h.putBlockDeficit # 0 THEN MakeUpPutBlockDeficit[h]; TRUSTED { IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@w]], startIndex~0, count~BYTES[Wrapper]] ]; }; h.putBlockDeficit ¬ RoundUp[len]; IO.PutText[h.streamOut, block8]; h.putBlockDeficit ¬ h.putBlockDeficit - len; }; CallEnabled[DoPutBlock8]; }; PutBlock8Cnt: PUBLIC PROC [h: Handle, cnt: CARDINAL] ~ { DoPutBlock8Cnt: PROC ~ { w: Wrapper ¬ [ tag ~ Basics.HFromCard16[ORD[Tag.block8]], len ~ Basics.HFromCard16[CARD16[cnt]] ]; IF h.streamOut = NIL THEN ERROR Error[$noConnectionFromPutBlock8Cnt]; IF h.putBlockDeficit # 0 THEN MakeUpPutBlockDeficit[h]; TRUSTED { IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@w]], startIndex~0, count~BYTES[Wrapper]] ]; }; h.putBlockDeficit ¬ RoundUp[cnt]; }; CallEnabled[DoPutBlock8Cnt]; }; PutBlock8Next: PUBLIC PROC [h: Handle, byte: BYTE] ~ { DoPutBlock8Next: PROC ~ { IF h.streamOut = NIL THEN ERROR Error[$noConnectionFromPutBlock8Next]; IF h.putBlockDeficit < 1 THEN ERROR Error[$putBlockErrorFromPutBlock8Next]; IO.PutChar[h.streamOut, VAL[byte]]; h.putBlockDeficit ¬ h.putBlockDeficit - 1; }; CallEnabled[DoPutBlock8Next]; }; PutBlock16: PUBLIC PROC [h: Handle, block16: Block16] ~ { DoPutBlock16: PROC ~ { len: CARD16 ¬ block16.count*BYTES[CARD16]; w: Wrapper ¬ [ tag ~ Basics.HFromCard16[ORD[Tag.block16]], len ~ Basics.HFromCard16[len] ]; IF h.streamOut = NIL THEN ERROR Error[$noConnectionFromPutBlock16]; IF h.putBlockDeficit # 0 THEN MakeUpPutBlockDeficit[h]; TRUSTED { IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@w]], startIndex~0, count~BYTES[Wrapper]] ]; }; h.putBlockDeficit ¬ RoundUp[len]; FOR i: NAT IN [0 .. block16.count) DO x: Basics.HWORD ¬ Basics.HFromCard16[block16[i]]; TRUSTED {IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@x]], startIndex~0, count~BYTES[CARD16]]]}; ENDLOOP; h.putBlockDeficit ¬ h.putBlockDeficit - len; }; CallEnabled[DoPutBlock16]; }; hEqC16: BOOL [TRUE..TRUE] ~ BYTES[CARD16] = BYTES[Basics.HWORD]; PutBlock16Cnt: PUBLIC PROC [h: Handle, cnt: CARDINAL] ~ { DoPutBlock16Cnt: PROC ~ { w: Wrapper ¬ [ tag ~ Basics.HFromCard16[ORD[Tag.block16]], len ~ Basics.HFromCard16[CARD16[cnt]] ]; IF h.streamOut = NIL THEN ERROR Error[$noConnectionFromPutBlock16Cnt]; IF h.putBlockDeficit # 0 THEN MakeUpPutBlockDeficit[h]; TRUSTED { IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@w]], startIndex~0, count~BYTES[Wrapper]] ]; }; h.putBlockDeficit ¬ RoundUp[cnt]; }; CallEnabled[DoPutBlock16Cnt]; }; PutBlock16Next: PUBLIC PROC [h: Handle, card16: CARD16] ~ { DoPutBlock16Next: PROC ~ { it: Basics.HWORD; IF h.streamOut = NIL THEN ERROR Error[$noConnectionFromPutBlock16Next]; IF h.putBlockDeficit < BYTES[Basics.HWORD] THEN ERROR Error[$putBlockErrorFromPutBlock16Next]; it ¬ Basics.HFromCard16[card16]; TRUSTED { IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@it]], startIndex~0, count~BYTES[Basics.HWORD]] ]; }; h.putBlockDeficit ¬ h.putBlockDeficit - BYTES[Basics.HWORD]; }; CallEnabled[DoPutBlock16Next]; }; PutBlock32: PUBLIC PROC [h: Handle, block32: Block32] ~ { DoPutBlock32: PROC ~ { len: CARD16 ¬ block32.count*BYTES[CARD32]; w: Wrapper ¬ [ tag ~ Basics.HFromCard16[ORD[Tag.block32]], len ~ Basics.HFromCard16[len] ]; IF h.streamOut = NIL THEN ERROR Error[$noConnectionFromPutBlock32]; IF h.putBlockDeficit # 0 THEN MakeUpPutBlockDeficit[h]; TRUSTED { IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@w]], startIndex~0, count~BYTES[Wrapper]] ]; }; h.putBlockDeficit ¬ RoundUp[len]; FOR i: NAT IN [0 .. block32.count) DO f: Basics.FWORD ¬ Basics.FFromCard32[block32[i]]; TRUSTED {IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@f]], startIndex~0, count~BYTES[CARD32]]]}; ENDLOOP; h.putBlockDeficit ¬ h.putBlockDeficit - len; }; CallEnabled[DoPutBlock32]; }; fEqCard32: BOOL[TRUE..TRUE] ~ BYTES[CARD32] = BYTES[Basics.FWORD]; PutBlock32Cnt: PUBLIC PROC [h: Handle, cnt: CARDINAL] ~ { DoPutBlock32Cnt: PROC ~ { w: Wrapper ¬ [ tag ~ Basics.HFromCard16[ORD[Tag.block32]], len ~ Basics.HFromCard16[CARD16[cnt]] ]; IF h.streamOut = NIL THEN ERROR Error[$noConnectionFromPutBlock32Cnt]; IF h.putBlockDeficit # 0 THEN MakeUpPutBlockDeficit[h]; TRUSTED { IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@w]], startIndex~0, count~BYTES[Wrapper]] ]; }; h.putBlockDeficit ¬ RoundUp[cnt]; }; CallEnabled[DoPutBlock32Cnt]; }; PutBlock32Next: PUBLIC PROC [h: Handle, card32: CARD32] ~ { DoPutBlock32Next: PROC ~ { it: Basics.FWORD; IF h.streamOut = NIL THEN ERROR Error[$noConnectionFromPutBlock32Next]; IF h.putBlockDeficit < BYTES[Basics.FWORD] THEN ERROR Error[$putBlockErrorFromPutBlock32Next]; it ¬ Basics.FFromCard32[card32]; TRUSTED { IO.UnsafePutBlock[h.streamOut, [base~LOOPHOLE[LONG[@it]], startIndex~0, count~BYTES[Basics.FWORD]] ]; }; h.putBlockDeficit ¬ h.putBlockDeficit - BYTES[Basics.FWORD]; }; CallEnabled[DoPutBlock32Next]; }; Get32: PROC [h: Handle] RETURNS [CARD32] ~ { ENABLE NetworkStream.Error, IO.Error, IO.EndOfStream => ERROR Error[$communicationFailureFromGet32]; it: Basics.FWORD; IF h.streamIn = NIL THEN ERROR Error[$noConnectionFromGet32]; TRUSTED { nRead: INT ¬ IO.UnsafeGetBlock[h.streamIn, [base~LOOPHOLE[LONG[@it]], startIndex~0, count~BYTES[Basics.FWORD]] ]; IF nRead # BYTES[Basics.FWORD] THEN ERROR Error[$protocolFromGet32]; }; RETURN[ Basics.Card32FromF[it] ]; }; GetBlock8: PROC [h: Handle, len: CARD16] RETURNS[block8: REF TEXT] ~ { DoGetBlock8: PROC ~ { roundedLen: INT ¬ RoundUp[len]; IF h.streamIn = NIL THEN ERROR Error[$noConnectionFromGetBlock8]; block8 ¬ RefText.New[roundedLen]; TRUSTED { nRead: INT ¬ IO.UnsafeGetBlock[h.streamIn, [base~LOOPHOLE[block8], startIndex~BYTES[TEXT[0]], count~roundedLen] ]; IF nRead # roundedLen THEN ERROR Error [$protocolFromGetBlock8]; }; block8.length ¬ len; }; CallEnabled[DoGetBlock8]; }; GetBlock16: PROC [h: Handle, len: CARD16] RETURNS[block16: Block16] ~ { DoGetBlock16: PROC ~ { roundedLen: INT ¬ RoundUp[len]; IF h.streamIn = NIL THEN ERROR Error[$noConnectionFromGetBlock16]; block16 ¬ NEW[ Block16Record[roundedLen/BYTES[CARD16]] ]; TRUSTED { nRead: INT ¬ IO.UnsafeGetBlock[h.streamIn, [base~LOOPHOLE[block16], startIndex~BYTES[Block16Record[0]], count~roundedLen] ]; IF nRead # roundedLen THEN ERROR Error [$protocolFromGetBlock16]; }; block16.count ¬ len / BYTES[CARD16]; FOR i: CARDINAL IN [0 .. block16.count) DO block16[i] ¬ Basics.Card16FromH[LOOPHOLE[block16[i]]]; ENDLOOP; }; CallEnabled[DoGetBlock16]; }; GetBlock32: PROC [h: Handle, len: CARD16] RETURNS[block32: Block32] ~ { DoGetBlock32: PROC ~ { roundedLen: INT ¬ RoundUp[len]; IF h.streamIn = NIL THEN ERROR Error[$noConnectionFromGetBlock32]; block32 ¬ NEW[ Block32Record[roundedLen/BYTES[CARD32]] ]; TRUSTED { nRead: INT ¬ IO.UnsafeGetBlock[h.streamIn, [base~LOOPHOLE[block32], startIndex~BYTES[Block32Record[0]], count~roundedLen] ]; IF nRead # roundedLen THEN ERROR Error[$protocolFromGetBlock32]; }; block32.count ¬ len/BYTES[CARD32]; FOR i: CARDINAL IN [0 .. block32.count) DO block32[i] ¬ Basics.Card32FromF[LOOPHOLE[block32[i]]]; ENDLOOP; }; CallEnabled[DoGetBlock32]; }; Call: PUBLIC PROC [h: Handle] RETURNS [rc: ReturnCode, result: CallResult] ~ { DoCall: PROC ~ { AddRes: PROC [r: REF] ~ { IF result.count >= result.maxCount THEN { oldRes: CallResult ¬ result; result ¬ NEW[CallResultRecord[oldRes.maxCount*2]]; FOR i: CARDINAL IN [0 .. oldRes.count) DO result.val[i] ¬ oldRes.val[i] ENDLOOP; result.count ¬ oldRes.count; }; result.val[result.count] ¬ r; result.count ¬ result.count.SUCC; }; IF (h.streamIn = NIL) OR (h.streamOut = NIL)THEN ERROR Error[$noConnectionFromCall]; IF h.putBlockDeficit # 0 THEN MakeUpPutBlockDeficit[h]; Put32Inner[h, h.procBeingCalled, procID]; NetworkStream.SendSoon[h.streamOut, 0]; result ¬ NEW[CallResultRecord[10]]; result.count ¬ 0; DO w: Wrapper; t: Tag; len: CARDINAL; TRUSTED { nRead: INT ¬ IO.UnsafeGetBlock[ h.streamIn, [base~LOOPHOLE[LONG[@w]], startIndex~0, count~BYTES[Wrapper]] ]; IF nRead # BYTES[Wrapper] THEN ERROR Error[$protocol1FromCall]; }; t ¬ VAL[Basics.Card16FromH[w.tag]]; len ¬ Basics.Card16FromH[w.len]; SELECT t FROM retCode => { rc ¬ VAL[CARD16[Get32[h]]]; EXIT }; card32 => { AddRes[ NEW[CARD32 ¬ LOOPHOLE[Get32[h]]] ] }; int32 => { AddRes[ NEW[INT32 ¬ LOOPHOLE[Get32[h]]] ] }; string, block8 => { AddRes[ GetBlock8[h, len] ] }; block16 => { AddRes[ GetBlock16[h, len] ] }; block32 => { AddRes[ GetBlock32[h, len] ] }; ENDCASE => ERROR Error[$protocol2FromCall]; ENDLOOP; h.procBeingCalled ¬ nullProcID; }; CallEnabled[DoCall]; }; }.