mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 13:39:39 +01:00 
			
		
		
		
	+ finished the internal omf library writer (implementing writing of the library
dictionary at the and of the file) and enabled it for the i8086 internal asm git-svn-id: trunk@30701 -
This commit is contained in:
		
							parent
							
								
									dbe1081389
								
							
						
					
					
						commit
						7923b6142e
					
				@ -858,7 +858,7 @@ implementation
 | 
			
		||||
            asmbin : '';
 | 
			
		||||
            asmcmd : '';
 | 
			
		||||
            supported_targets : [system_i8086_msdos];
 | 
			
		||||
            flags : [af_outputbinary,af_needar,af_no_debug];
 | 
			
		||||
            flags : [af_outputbinary,af_no_debug];
 | 
			
		||||
            labelprefix : '..@';
 | 
			
		||||
            comment : '; ';
 | 
			
		||||
            dollarsign: '$';
 | 
			
		||||
 | 
			
		||||
@ -504,6 +504,15 @@ interface
 | 
			
		||||
      property PaddingBytes: Word read FPaddingBytes write FPaddingBytes;
 | 
			
		||||
    end;
 | 
			
		||||
 | 
			
		||||
  const
 | 
			
		||||
    { list of all the possible omf library dictionary block counts - contains
 | 
			
		||||
      all the prime numbers less than 255 }
 | 
			
		||||
    OmfLibDictionaryBlockCounts: array [0..53] of Byte =
 | 
			
		||||
      (2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,
 | 
			
		||||
       101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,
 | 
			
		||||
       193,197,199,211,223,227,229,233,239,241,251);
 | 
			
		||||
 | 
			
		||||
  type
 | 
			
		||||
    TOmfLibHash = record
 | 
			
		||||
      block_x: Integer;
 | 
			
		||||
      block_d: Integer;
 | 
			
		||||
 | 
			
		||||
@ -30,10 +30,21 @@ interface
 | 
			
		||||
 | 
			
		||||
uses
 | 
			
		||||
  cclasses,
 | 
			
		||||
  globtype,
 | 
			
		||||
  owbase;
 | 
			
		||||
 | 
			
		||||
type
 | 
			
		||||
 | 
			
		||||
  { TOmfLibDictionaryEntry }
 | 
			
		||||
 | 
			
		||||
  TOmfLibDictionaryEntry=class(TFPHashObject)
 | 
			
		||||
  private
 | 
			
		||||
    FPageNum: Word;
 | 
			
		||||
  public
 | 
			
		||||
    constructor Create(HashObjectList:TFPHashObjectList;const aName:TSymStr;aPageNum:Word);
 | 
			
		||||
    property PageNum: Word read FPageNum write FPageNum;
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  { TOmfLibObjectWriter }
 | 
			
		||||
 | 
			
		||||
  TOmfLibObjectWriter=class(TObjectWriter)
 | 
			
		||||
@ -44,10 +55,13 @@ type
 | 
			
		||||
    FObjFileName: string;
 | 
			
		||||
    FObjData: TDynamicArray;
 | 
			
		||||
    FObjStartPage: Word;
 | 
			
		||||
    FDictionary: TFPHashObjectList;
 | 
			
		||||
 | 
			
		||||
    procedure WriteHeader(DictStart: DWord; DictBlocks: Word);
 | 
			
		||||
    procedure WriteFooter;
 | 
			
		||||
    procedure WriteLib;
 | 
			
		||||
    function WriteDictionary: byte;
 | 
			
		||||
    function TryWriteDictionaryWithSize(nblocks: Byte): Boolean;
 | 
			
		||||
  public
 | 
			
		||||
    constructor createAr(const Aarfn:string);override;
 | 
			
		||||
    destructor  destroy;override;
 | 
			
		||||
@ -70,6 +84,28 @@ implementation
 | 
			
		||||
      libbufsize = 65536;
 | 
			
		||||
      objbufsize = 65536;
 | 
			
		||||
 | 
			
		||||
{*****************************************************************************
 | 
			
		||||
                                   Helpers
 | 
			
		||||
*****************************************************************************}
 | 
			
		||||
 | 
			
		||||
    function ModName2DictEntry(const modnm: string): string;
 | 
			
		||||
      begin
 | 
			
		||||
        if Copy(modnm,Length(modnm)-1,2)='.o' then
 | 
			
		||||
          Result:=Copy(modnm,1,Length(modnm)-2)+'!'
 | 
			
		||||
        else
 | 
			
		||||
          Result:=modnm;
 | 
			
		||||
      end;
 | 
			
		||||
 | 
			
		||||
{*****************************************************************************
 | 
			
		||||
                                TOmfLibDictionaryEntry
 | 
			
		||||
*****************************************************************************}
 | 
			
		||||
 | 
			
		||||
    constructor TOmfLibDictionaryEntry.Create(HashObjectList: TFPHashObjectList; const aName: TSymStr; aPageNum: Word);
 | 
			
		||||
      begin
 | 
			
		||||
        inherited Create(HashObjectList,aName);
 | 
			
		||||
        PageNum:=aPageNum;
 | 
			
		||||
      end;
 | 
			
		||||
 | 
			
		||||
{*****************************************************************************
 | 
			
		||||
                                TOmfLibObjectWriter
 | 
			
		||||
*****************************************************************************}
 | 
			
		||||
@ -79,6 +115,7 @@ implementation
 | 
			
		||||
        FPageSize:=512;
 | 
			
		||||
        FLibName:=Aarfn;
 | 
			
		||||
        FLibData:=TDynamicArray.Create(libbufsize);
 | 
			
		||||
        FDictionary:=TFPHashObjectList.Create;
 | 
			
		||||
        { header is at page 0, so first module starts at page 1 }
 | 
			
		||||
        FObjStartPage:=1;
 | 
			
		||||
      end;
 | 
			
		||||
@ -90,6 +127,7 @@ implementation
 | 
			
		||||
          WriteLib;
 | 
			
		||||
        FLibData.Free;
 | 
			
		||||
        FObjData.Free;
 | 
			
		||||
        FDictionary.Free;
 | 
			
		||||
        inherited destroy;
 | 
			
		||||
      end;
 | 
			
		||||
 | 
			
		||||
@ -107,12 +145,21 @@ implementation
 | 
			
		||||
    procedure TOmfLibObjectWriter.closefile;
 | 
			
		||||
      var
 | 
			
		||||
        RawRec: TOmfRawRecord;
 | 
			
		||||
        ObjHeader: TOmfRecord_THEADR;
 | 
			
		||||
      begin
 | 
			
		||||
        FLibData.seek(FObjStartPage*FPageSize);
 | 
			
		||||
        FObjData.seek(0);
 | 
			
		||||
        RawRec:=TOmfRawRecord.Create;
 | 
			
		||||
        repeat
 | 
			
		||||
          RawRec.ReadFrom(FObjData);
 | 
			
		||||
          if RawRec.RecordType=RT_THEADR then
 | 
			
		||||
            begin
 | 
			
		||||
              ObjHeader:=TOmfRecord_THEADR.Create;
 | 
			
		||||
              ObjHeader.DecodeFrom(RawRec);
 | 
			
		||||
              { create a dictionary entry with the module name }
 | 
			
		||||
              TOmfLibDictionaryEntry.Create(FDictionary,ModName2DictEntry(ObjHeader.ModuleName),FObjStartPage);
 | 
			
		||||
              ObjHeader.Free;
 | 
			
		||||
            end;
 | 
			
		||||
          RawRec.WriteTo(FLibData);
 | 
			
		||||
        until RawRec.RecordType in [RT_MODEND,RT_MODEND32];
 | 
			
		||||
        RawRec.Free;
 | 
			
		||||
@ -124,7 +171,7 @@ implementation
 | 
			
		||||
 | 
			
		||||
    procedure TOmfLibObjectWriter.writesym(const sym: string);
 | 
			
		||||
      begin
 | 
			
		||||
        inherited writesym(sym);
 | 
			
		||||
        TOmfLibDictionaryEntry.Create(FDictionary,sym,FObjStartPage);
 | 
			
		||||
      end;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -174,6 +221,8 @@ implementation
 | 
			
		||||
    procedure TOmfLibObjectWriter.WriteLib;
 | 
			
		||||
      var
 | 
			
		||||
        libf: TCCustomFileStream;
 | 
			
		||||
        DictStart: LongWord;
 | 
			
		||||
        DictBlocks: Byte;
 | 
			
		||||
      begin
 | 
			
		||||
        libf:=CFileStreamClass.Create(FLibName,fmCreate);
 | 
			
		||||
        if CStreamError<>0 then
 | 
			
		||||
@ -182,9 +231,95 @@ implementation
 | 
			
		||||
            exit;
 | 
			
		||||
          end;
 | 
			
		||||
        WriteFooter;
 | 
			
		||||
        WriteHeader(FLibData.Pos,2);
 | 
			
		||||
        DictStart:=FLibData.Pos;
 | 
			
		||||
        DictBlocks:=WriteDictionary;
 | 
			
		||||
        WriteHeader(DictStart,DictBlocks);
 | 
			
		||||
        FLibData.WriteStream(libf);
 | 
			
		||||
        libf.Free;
 | 
			
		||||
      end;
 | 
			
		||||
 | 
			
		||||
    function TOmfLibObjectWriter.WriteDictionary: Byte;
 | 
			
		||||
      var
 | 
			
		||||
        nb: Byte;
 | 
			
		||||
      begin
 | 
			
		||||
        for nb in OmfLibDictionaryBlockCounts do
 | 
			
		||||
          if TryWriteDictionaryWithSize(nb) then
 | 
			
		||||
            exit(nb);
 | 
			
		||||
        { could not write dictionary, even with the largest number of blocks }
 | 
			
		||||
        internalerror(2015042201);
 | 
			
		||||
      end;
 | 
			
		||||
 | 
			
		||||
    function TOmfLibObjectWriter.TryWriteDictionaryWithSize(nblocks: Byte): Boolean;
 | 
			
		||||
      const
 | 
			
		||||
        nbuckets=37;
 | 
			
		||||
        freespace=nbuckets;
 | 
			
		||||
      type
 | 
			
		||||
        PBlock=^TBlock;
 | 
			
		||||
        TBlock=array[0..511] of byte;
 | 
			
		||||
      var
 | 
			
		||||
        blocks: array of TBlock;
 | 
			
		||||
        i: Integer;
 | 
			
		||||
        N: TSymStr;
 | 
			
		||||
        length_of_string: Integer;
 | 
			
		||||
        h: TOmfLibHash;
 | 
			
		||||
        start_block,start_bucket: Integer;
 | 
			
		||||
        space_required: Integer;
 | 
			
		||||
        pb: PBlock;
 | 
			
		||||
        success: Boolean;
 | 
			
		||||
        store_at: Integer;
 | 
			
		||||
        PageNum: Word;
 | 
			
		||||
      begin
 | 
			
		||||
        SetLength(blocks,nblocks);
 | 
			
		||||
        for i:=0 to nblocks-1 do
 | 
			
		||||
          begin
 | 
			
		||||
            FillChar(blocks[i],SizeOf(blocks[i]),0);
 | 
			
		||||
            blocks[i][freespace]:=(freespace+1) div 2;
 | 
			
		||||
          end;
 | 
			
		||||
 | 
			
		||||
        for i:=0 to FDictionary.Count-1 do
 | 
			
		||||
          begin
 | 
			
		||||
            N:=TOmfLibDictionaryEntry(FDictionary[i]).Name;
 | 
			
		||||
            PageNum:=TOmfLibDictionaryEntry(FDictionary[i]).PageNum;
 | 
			
		||||
            length_of_string:=Length(N);
 | 
			
		||||
            h:=compute_omf_lib_hash(N,nblocks);
 | 
			
		||||
            start_block:=h.block_x;
 | 
			
		||||
            start_bucket:=h.bucket_x;
 | 
			
		||||
            space_required:=1+length_of_string+2;
 | 
			
		||||
            if odd(space_required) then
 | 
			
		||||
              Inc(space_required);
 | 
			
		||||
            repeat
 | 
			
		||||
              pb:=@blocks[h.block_x];
 | 
			
		||||
              success:=false;
 | 
			
		||||
              repeat
 | 
			
		||||
                if pb^[h.bucket_x]=0 then
 | 
			
		||||
                  begin
 | 
			
		||||
                    if (512-pb^[freespace]*2)<space_required then
 | 
			
		||||
                      break;
 | 
			
		||||
                    pb^[h.bucket_x]:=pb^[freespace];
 | 
			
		||||
                    store_at:=2*pb^[h.bucket_x];
 | 
			
		||||
                    pb^[store_at]:=length_of_string;
 | 
			
		||||
                    Move(N[1],pb^[store_at+1],length_of_string);
 | 
			
		||||
                    pb^[store_at+1+length_of_string]:=Byte(PageNum);
 | 
			
		||||
                    pb^[store_at+1+length_of_string+1]:=Byte(PageNum shr 8);
 | 
			
		||||
                    Inc(pb^[freespace],space_required div 2);
 | 
			
		||||
                    if pb^[freespace]=0 then
 | 
			
		||||
                      pb^[freespace]:=255;
 | 
			
		||||
                    success:=true;
 | 
			
		||||
                    break;
 | 
			
		||||
                  end;
 | 
			
		||||
                h.bucket_x:=(h.bucket_x+h.bucket_d) mod nbuckets;
 | 
			
		||||
              until h.bucket_x=start_bucket;
 | 
			
		||||
              if not success then
 | 
			
		||||
                begin
 | 
			
		||||
                  h.block_x:=(h.block_x+h.block_d) mod nblocks;
 | 
			
		||||
                  if h.block_x=start_block then
 | 
			
		||||
                    exit(false); // not enough blocks
 | 
			
		||||
                  pb^[freespace]:=255;
 | 
			
		||||
                end;
 | 
			
		||||
            until success;
 | 
			
		||||
          end;
 | 
			
		||||
        FLibData.write(blocks[0],nblocks*SizeOf(TBlock));
 | 
			
		||||
        Result:=true;
 | 
			
		||||
      end;
 | 
			
		||||
 | 
			
		||||
end.
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user