Press enter to see results or esc to cancel.

Checking Public Identifiers

Turbo Pascal calculates a checksum of public identifiers for every unit to quickly check if something has been changed.

Procedure CalculateIdentifiersChecksum;
Var UnitCounter: Word;
    UnitHeader: PUnitHeader;
    UnitIdentifier: PIdentifier;
    UnitIdentifierRec: PtrRec absolute UnitIdentifier;
    UnitIdentifierData: PUnitIdentifierData;
    CheckSum, N: Word;
    IdWord: PWord;
begin
  UnitCounter := 0;                                                 { Push And Clear Unit Segments;}
  UnitHeader := Ptr (MainSymbolTable.Segment, 0);
  UnitIdentifier := Ptr (MainSymbolTable.Segment, UnitHeader^.UnitNameIdentifierOffset);
  Repeat
    UnitIdentifierData := PUnitIdentifierData (PChar (UnitIdentifier) + UnitIdentifier^.Name.Len + 4);
    Asm
      LES   DI, UnitIdentifierData
      PUSH  WORD PTR ES:[DI]            { UnitIdentifierData^.UnitSegment) }
      PUSH  DI                          { Ofs (UnitIdentifierData^) }
    end;
    UnitIdentifierData^.UnitSegment := 0;
    Inc (UnitCounter);
    UnitIdentifierRec.Ofs := UnitIdentifierData^.NextUnitIdentifier;
  until UnitIdentifierRec.Ofs = 0;

  CheckSum := 0;
  IdWord := Ptr (MainSymbolTable.Segment, UnitHeader^.PublicIdentifiersListOffset);
  For N := 1 to (SymbolTable [stMain].UsedSize - UnitHeader^.PublicIdentifiersListOffset) div 2 do
    begin
      Asm
        MOV   AX, CheckSum
        ROL   AX, 1
        MOV   CheckSum, AX
      end;
      Inc (CheckSum, IdWord^);
      Inc (IdWord);
    end;
  If CheckSum = 0 then CheckSum := $FFFF;
  UnitIdentifier := Ptr (MainSymbolTable.Segment, UnitHeader^.UnitNameIdentifierOffset);
  UnitIdentifierData := PUnitIdentifierData (PChar (UnitIdentifier) + UnitIdentifier^.Name.Len + 4);
  UnitIdentifierData^.PublicIdentifiersChecksum := CheckSum;

  Asm
    LES   DI, UnitHeader
    MOV   CX, UnitCounter
@1:
    POP   DI
    POP   WORD PTR ES:[DI]
    LOOP  @1
  end;
end;