Press enter to see results or esc to cancel.

Creating Unit File

CompileUnit calls this procedure to create unit file which is in fact a collection of symbol tables. All segment addresses are cleared and symbol table data is written to the file.

Procedure CreateUnitFile;
Var SavedUnitSegment: Word;
    UnitFile: File;
    UnitFileSize, BytesToWrite: LongInt;
    UnitPtr: Pointer;
    BytesWritten: Word;

    UnitCounter: Word;
    UnitIdentifier: PIdentifier;
    UnitIdentifierRec: PtrRec absolute UnitIdentifier;
    UnitIdentifierData: PUnitIdentifierData;
    UnitHeader: PUnitHeader;
begin
  If cmoCompileToDisk in CompilerModeOptions then
    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;

      SavedUnitSegment := PUnitHeader (Ptr (MainSymbolTable.Segment, 0))^.PreviousUnitSegment;
      PUnitHeader (Ptr (MainSymbolTable.Segment, 0))^.PreviousUnitSegment := 0;
      FindFilePath (StrPCopy (@Identifier, CurrentSourceFile^.Name.Str),
                      Dir_Forced or Dir_EXE_TPU or Ext_Forced or Ext_TPU);
      CreateFile (UnitFile, @Identifier);
      OutputFileHandle := FileRec (UnitFile).Handle;
      UnitFileSize := LongInt (HeapPtrRec.Seg - MainSymbolTable.Segment) * 16;
      UnitPtr := Ptr (MainSymbolTable.Segment, 0);
{$I-}
      While UnitFileSize > 0 do
        begin
          BytesToWrite := UnitFileSize;
          If BytesToWrite > $FFF0 then BytesToWrite := $FFF0;
          BlockWrite (UnitFile, UnitPtr^, BytesToWrite, BytesWritten);
          If IOResult <> 0 then Error (DiskFull);
          Dec (UnitFileSize, BytesWritten);
          UnitPtr := Ptr (Seg (UnitPtr^) + $0FFF, 0);
        end;
      Close (UnitFile);
{$I+}
      OutputFileHandle := 0;
      PUnitHeader (Ptr (MainSymbolTable.Segment, 0))^.PreviousUnitSegment := SavedUnitSegment;
      Asm
        LES   DI, UnitHeader
        MOV   CX, UnitCounter
    @1:
        POP   DI
        POP   WORD PTR ES:[DI]
        LOOP  @1
      end;
    end;
  CodeBytes := SymbolTable [stCode].UsedSize;
  DataBytes := SymbolTable [stTypedConstants].UsedSize + SizeOfVariablesInDataSegment;
end;