-- FTPUtilities.mesa, Edited by: HGM August 3, 1980  4:20 PM
-- Randy Gobbel		20-May-81 12:16:58  
-- Andrew Birrell	30-Mar-81 11:40:05  

-- Copyright  Xerox Corporation 1979, 1980, 1981

DIRECTORY
  Stream USING [Block],
  ByteBltDefs USING [ByteBlt],
  FTPDefs,
  FTPPrivateDefs;

FTPUtilities: PROGRAM
  IMPORTS ByteBltDefs, FTPPrivateDefs
  EXPORTS FTPPrivateDefs
  SHARES FTPDefs =
BEGIN OPEN FTPDefs, FTPPrivateDefs; 


-- **********************!  Transmission Primitives  !***********************

-- Note:  These transmission primitives increment the connection's total byte count
--   and do not trace the transmitted data.

SendBlock: PUBLIC PROCEDURE [ftper: FTPer, source: POINTER, byteCount: CARDINAL] =
  BEGIN OPEN ftper;
  -- Note:  Forces transmission.
  -- local variables
    bytePointerObject: BytePointerObject ← [source, FALSE, byteCount];
  -- send block
    communicationPrimitives.SendBytes[communicationSystem, connection, @bytePointerObject];
  -- force transmission
  -- don't! ADB
  --  communicationPrimitives.ForceOutput[communicationSystem, connection];
  -- increment total byte count for connection
    totalByteCount ← totalByteCount + byteCount;
  END;

ReceiveBlock: PUBLIC PROCEDURE [ftper: FTPer, destination: POINTER, maxWordCount: CARDINAL] RETURNS [actualByteCount: CARDINAL] =
  BEGIN OPEN ftper;
  -- local variables
    bytePointerObject: BytePointerObject ←
      [destination, FALSE, bytesPerWord*maxWordCount];
  -- receive next block
    communicationPrimitives.ReceiveBytes[
      communicationSystem, connection, @bytePointerObject, TRUE];
    actualByteCount ← bytesPerWord*maxWordCount - bytePointerObject.count;
  -- increment total byte count for connection
    totalByteCount ← totalByteCount + actualByteCount;
  END;

SendBytes: PUBLIC PROCEDURE [ftper: FTPer, bytePointer: BytePointer] =
  BEGIN OPEN ftper;
  -- Note:  No operation if bytePointer.count=0.
  -- local constants
    byteCount: CARDINAL = bytePointer.count;
  -- nop if no bytes
    IF bytePointer.count = 0 THEN RETURN;
  -- send bytes
    communicationPrimitives.SendBytes[communicationSystem, connection, bytePointer];
  -- increment total byte count for connection
    totalByteCount ← totalByteCount + byteCount;
  END;

ReceiveBytes: PUBLIC PROCEDURE [ftper: FTPer, bytePointer: BytePointer] =
  BEGIN OPEN ftper;
  -- Note:  No operation if bytePointer.count=0.
  -- local constants
    byteCount: CARDINAL = bytePointer.count;
  -- nop if no bytes
    IF bytePointer.count = 0 THEN RETURN;
  -- receive bytes
    communicationPrimitives.ReceiveBytes[communicationSystem, connection, bytePointer, FALSE];
  -- increment total byte count for connection
    totalByteCount ← totalByteCount + byteCount;
  END;

SendWord: PUBLIC PROCEDURE [ftper: FTPer, word: WORD] =
  BEGIN OPEN ftper;
  -- local constants
    wordPointer: Word = LOOPHOLE[@word];
  -- send word
    communicationPrimitives.SendByte[communicationSystem, connection, wordPointer.lhByte];
    communicationPrimitives.SendByte[communicationSystem, connection, wordPointer.rhByte];
  -- increment total byte count for connection
    totalByteCount ← totalByteCount + bytesPerWord;
  END;

ReceiveWord: PUBLIC PROCEDURE [ftper: FTPer] RETURNS [word: WORD] =
  BEGIN OPEN ftper;
  -- local constants
    wordPointer: Word = LOOPHOLE[@word];
  -- receive word
    [wordPointer.lhByte, ] ←
      communicationPrimitives.ReceiveByte[communicationSystem, connection, FALSE];
    [wordPointer.rhByte, ] ←
      communicationPrimitives.ReceiveByte[communicationSystem, connection, FALSE];
  -- increment total byte count for connection
    totalByteCount ← totalByteCount + bytesPerWord;
  END;

SendByte: PUBLIC PROCEDURE [ftper: FTPer, byte: Byte] =
  BEGIN OPEN ftper;
  -- send byte
    communicationPrimitives.SendByte[communicationSystem, connection, byte];
  -- increment total byte count for connection
    totalByteCount ← totalByteCount + 1;
  END;

ReceiveByte: PUBLIC PROCEDURE [ftper: FTPer] RETURNS [byte: Byte] =
  BEGIN OPEN ftper;
  -- receive byte
    [byte, ] ← communicationPrimitives.ReceiveByte[communicationSystem, connection, FALSE];
  -- increment total byte count for connection
    totalByteCount ← totalByteCount + 1;
  END;

-- **********************!  Byte Primitives  !***********************

TransferBytes: PUBLIC PROCEDURE [srcBytePointer, dstBytePointer: BytePointer] =
  BEGIN
  to, from: Stream.Block;
  bytes: CARDINAL;
  from.blockPointer ← srcBytePointer.address;
  from.startIndex ← IF srcBytePointer.offset THEN 1 ELSE 0;
  from.stopIndexPlusOne ← from.startIndex+srcBytePointer.count;
  to.blockPointer ← dstBytePointer.address;
  to.startIndex ← IF dstBytePointer.offset THEN 1 ELSE 0;
  to.stopIndexPlusOne ← to.startIndex+dstBytePointer.count;
  bytes ← ByteBltDefs.ByteBlt[to: to, from: from];
  AdvanceBytePointer[srcBytePointer,bytes];
  AdvanceBytePointer[dstBytePointer,bytes];
  END;


-- **********************!  Main Program  !***********************

-- no operation

END. -- of FTPUtilities