Может быть лучше сделать как-нибудь так?

## Код:
```
MODULE AixBasicProtocols;

   TYPE
      Chunk = POINTER TO RECORD
         next: Chunk;
         data: POINTER TO ARRAY OF BYTE;
         offset: INTEGER
      END;
      TemporaryBuffer* = POINTER TO RECORD
         root: Chunk;
         len: INTEGER
      END;
      
      Protocol* = POINTER TO ABSTRACT RECORD
      END;
      LineOnlyReceiver* = POINTER TO ABSTRACT RECORD (Protocol)
         buffer: TemporaryBuffer;
         delimiter: POINTER TO ARRAY OF BYTE
      END;

   PROCEDURE (b: TemporaryBuffer) Append* (IN data: ARRAY OF BYTE; beg, len: INTEGER), NEW;
      VAR chunk: Chunk;
         i: INTEGER;
   BEGIN
      ASSERT(len > 0, 20);
      ASSERT(beg >= 0, 21);
      ASSERT(beg + len <= LEN(data), 22);
      NEW(chunk);
      NEW(chunk.data, len);
      i := 0;
      WHILE i < len DO
         chunk.data[i] := data[beg];
         INC(beg);
         INC(i)
      END;
      chunk.next := b.root;
      b.root := chunk;
      chunk.offset := b.len;
      INC(b.len, len)
   END Append;

   PROCEDURE (b: TemporaryBuffer) GetBytes* (): POINTER TO ARRAY OF BYTE, NEW;
      VAR data: POINTER TO ARRAY OF BYTE;
         i, j, len: INTEGER;
         chunk: Chunk;
   BEGIN
      IF b.len > 0 THEN
         NEW(data, b.len);
         chunk := b.root;
         WHILE chunk # NIL DO
            i := chunk.offset;
            j := 0;
            len := LEN(chunk.data);
            WHILE j < len DO
               data[i] := chunk.data[j];
               INC(j);
               INC(i)
            END;
            chunk := chunk.next
         END
      END;
      RETURN data
   END GetBytes;

   PROCEDURE (b: TemporaryBuffer) Clear*, NEW;
   BEGIN
      b.len := 0;
      b.root := NIL
   END Clear;

   PROCEDURE NewTemporaryBuffer* (): TemporaryBuffer;
      VAR b: TemporaryBuffer;
   BEGIN
      NEW(b);
      b.len := 0;
      RETURN(b)
   END NewTemporaryBuffer;

   PROCEDURE (p: Protocol) DataReceived- (IN data: ARRAY OF BYTE; beg, len: INTEGER), NEW, ABSTRACT;

   PROCEDURE (p: LineOnlyReceiver) LineReceived- (IN data: ARRAY OF BYTE), NEW, ABSTRACT;

   PROCEDURE (p: LineOnlyReceiver) DataReceived- (IN data: ARRAY OF BYTE; beg, len: INTEGER);
      VAR i, dlen, j, l, k: INTEGER;
   BEGIN
      ASSERT(len > 0, 20);
      ASSERT(beg >= 0, 21);
      ASSERT(beg + len <= LEN(data), 22);
      dlen := LEN(p.delimiter);
      i := beg; j := i;
      LOOP
         WHILE (i < len) & (data[i] # p.delimiter[0]) DO
            INC(i)
         END;
         IF i = len THEN EXIT END;
         l := i - j;
         INC(i); k := 1;
         WHILE (i < len) & (k < dlen) & (data[i] = p.delimiter[k]) DO
            INC(i);
            INC(k)
         END;
         IF k = dlen THEN
            p.buffer.Append(data, j, l);
            p.LineReceived(p.buffer.GetBytes());
            p.buffer.Clear();
            j := i
         END
      END;
      IF i > j THEN
         p.buffer.Append(data, j, i - j)
      END
   END DataReceived;

   PROCEDURE (p: LineOnlyReceiver) InitializeLineOnlyReceiver* (IN delimiter: ARRAY OF BYTE), NEW;
      VAR i, len: INTEGER;
   BEGIN
      len := LEN(delimiter);
      p.buffer := NewTemporaryBuffer();
      NEW(p.delimiter, len);
      i := 0;
      WHILE i < len DO
         p.delimiter[i] := delimiter[i];
         INC(i)
      END
   END InitializeLineOnlyReceiver;

END AixBasicProtocols.
```


Т.е. не обязательно при получении данных из потока помещать их в буфер, а лучше передать полученные данные сразу в Protocol (метод DataReceived) - а он сам решит, что с ними делать. Даже если ему и нужно будет поместить данные в буфер, то он будет использовать свою, более эффективную реализацию.

В этом примере LineOnlyReceiver - абстрактный Protocol, который принимает данные (DataReceived), разделяет на строки с помощью заданного разделителя и вызывает для каждой строки метод LineReceived.

Здесь Protocol - это и есть CommAction.Engine, только у него вместо Do - DataReceived.