?? RIGHT := 110 ??
MODULE ocm$checksum;

*copyc och$checksum

  FUNCTION [XDCL] ocp$checksum (p_sequence: ^SEQ ( * )): integer;

    CONST
      max_trailing_bytes = 3,
      shift_one_byte = 100(16),
      max_halfword = 0ffffffff(16);

    TYPE
      unsigned_8_bit = 0 .. 0ff(16),
      unsigned_32_bit = 0 .. max_halfword;

    VAR
      accumulator: integer,
      shift: 0 .. 3,
      trailing_bytes: 0 .. 3,
      four_bytes: ^unsigned_32_bit,
      sequence: ^SEQ ( * ),
      one_byte: ^unsigned_8_bit,
      temp_bytes: unsigned_32_bit;

{ NOTE:  When a NEXT goes beyond the end of a sequence, it returns a NIL
{ pointer.  The value of the sequence pointer itself however, has not changed.
{ This fact is utilized in the code below when a NEXT of the ONE_BYTE
{ pointer is done after the NEXT for the FOUR_BYTES pointer returns NIL.

    sequence := p_sequence;

    RESET sequence;
    accumulator := 0;
    NEXT four_bytes IN sequence;
    WHILE four_bytes <> NIL DO
      accumulator := (accumulator + four_bytes^) * 2;
      accumulator := (accumulator MOD (max_halfword + 1)) + (accumulator DIV (max_halfword + 1));
      NEXT four_bytes IN sequence;
    WHILEND;
    trailing_bytes := 0;
    temp_bytes := 0;
    NEXT one_byte IN sequence;
    WHILE one_byte <> NIL DO
      temp_bytes := temp_bytes * shift_one_byte;
      temp_bytes := temp_bytes + one_byte^;
      trailing_bytes := trailing_bytes + 1;
      NEXT one_byte IN sequence;
    WHILEND;
    IF trailing_bytes > 0 THEN
      FOR shift := max_trailing_bytes DOWNTO trailing_bytes DO
        temp_bytes := temp_bytes * shift_one_byte;
      FOREND;
      accumulator := (accumulator + temp_bytes) * 2;
      accumulator := (accumulator MOD (max_halfword + 1)) + (accumulator DIV (max_halfword + 1));
    IFEND;
    ocp$checksum := accumulator;
  FUNCEND ocp$checksum;
MODEND ocm$checksum;
