mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 14:39:36 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			614 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			614 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    Copyright (c) 2015 by Nikolay Nikolov
 | 
						|
 | 
						|
    Contains the stuff for writing Relocatable Object Module Format (OMF)
 | 
						|
    libraries directly. This is the object format used on the i8086-msdos
 | 
						|
    platform (also known as .lib files in the dos world, even though Free
 | 
						|
    Pascal uses the extension .a).
 | 
						|
 | 
						|
    This program is free software; you can redistribute it and/or modify
 | 
						|
    it under the terms of the GNU General Public License as published by
 | 
						|
    the Free Software Foundation; either version 2 of the License, or
 | 
						|
    (at your option) any later version.
 | 
						|
 | 
						|
    This program is distributed in the hope that it will be useful,
 | 
						|
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
    GNU General Public License for more details.
 | 
						|
 | 
						|
    You should have received a copy of the GNU General Public License
 | 
						|
    along with this program; if not, write to the Free Software
 | 
						|
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
 | 
						|
 ****************************************************************************
 | 
						|
}
 | 
						|
unit owomflib;
 | 
						|
 | 
						|
{$i fpcdefs.inc}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
uses
 | 
						|
  cclasses,
 | 
						|
  globtype,
 | 
						|
  owbase;
 | 
						|
 | 
						|
type
 | 
						|
 | 
						|
  { TOmfLibObjectWriter }
 | 
						|
 | 
						|
  TOmfLibObjectWriter=class(TObjectWriter)
 | 
						|
  strict private
 | 
						|
    type
 | 
						|
 | 
						|
      { TOmfLibObjectModule }
 | 
						|
 | 
						|
      TOmfLibObjectModule=class
 | 
						|
      strict private
 | 
						|
        FObjFileName: string;
 | 
						|
        FObjData: TDynamicArray;
 | 
						|
        FPageNum: Word;
 | 
						|
      public
 | 
						|
        constructor Create(const fn:string);
 | 
						|
        destructor Destroy; override;
 | 
						|
 | 
						|
        property ObjData: TDynamicArray read FObjData;
 | 
						|
        property PageNum: Word read FPageNum write FPageNum;
 | 
						|
      end;
 | 
						|
 | 
						|
      { TOmfLibDictionaryEntry }
 | 
						|
 | 
						|
      TOmfLibDictionaryEntry=class(TFPHashObject)
 | 
						|
      strict private
 | 
						|
        FModuleIndex: Integer;
 | 
						|
      public
 | 
						|
        constructor Create(HashObjectList:TFPHashObjectList;const aName:TSymStr;aModuleIndex:Integer);
 | 
						|
        property ModuleIndex: Integer read FModuleIndex write FModuleIndex;
 | 
						|
      end;
 | 
						|
  strict private
 | 
						|
    FPageSize: Integer;
 | 
						|
    FLibName: string;
 | 
						|
    FLibData: TDynamicArray;
 | 
						|
    FFooterPos: LongWord;
 | 
						|
    FDictionary: TFPHashObjectList;
 | 
						|
    FObjectModules: TFPObjectList;
 | 
						|
    FCurrentModule: TOmfLibObjectModule;
 | 
						|
    FCurrentModuleIndex: Integer;
 | 
						|
 | 
						|
    procedure WriteHeader(DictStart: DWord; DictBlocks: Word);
 | 
						|
    procedure WriteFooter;
 | 
						|
    function TryPageSize(aPageSize: Integer): Boolean;
 | 
						|
    procedure DeterminePageSize;
 | 
						|
    procedure WriteLib;
 | 
						|
    function WriteDictionary: Word;
 | 
						|
    function TryWriteDictionaryWithSize(nblocks: Word): Boolean;
 | 
						|
  public
 | 
						|
    constructor createAr(const Aarfn:string);override;
 | 
						|
    constructor createAr(const Aarfn:string;PageSize:Integer);
 | 
						|
    destructor  destroy;override;
 | 
						|
    function  createfile(const fn:string):boolean;override;
 | 
						|
    procedure closefile;override;
 | 
						|
    procedure writesym(const sym:string);override;
 | 
						|
    procedure write(const b;len:longword);override;
 | 
						|
  end;
 | 
						|
 | 
						|
  { TOmfLibObjectReader }
 | 
						|
 | 
						|
  TOmfLibObjectReader=class(TObjectReader)
 | 
						|
  strict private
 | 
						|
    type
 | 
						|
 | 
						|
      { TOmfLibDictionaryEntry }
 | 
						|
 | 
						|
      TOmfLibDictionaryEntry=class(TFPHashObject)
 | 
						|
      strict private
 | 
						|
        FPageNum: Word;
 | 
						|
      public
 | 
						|
        constructor Create(HashObjectList:TFPHashObjectList;const aName:TSymStr;aPageNum:Word);
 | 
						|
        property PageNum: Word read FPageNum write FPageNum;
 | 
						|
      end;
 | 
						|
  strict private
 | 
						|
    LibSymbols : TFPHashObjectList;
 | 
						|
    islib: boolean;
 | 
						|
    CurrMemberPos : longint;
 | 
						|
    CurrMemberName : string;
 | 
						|
    FPageSize: Integer;
 | 
						|
    FIsCaseSensitive: Boolean;
 | 
						|
    procedure ReadLibrary;
 | 
						|
    procedure ReadDictionary(DictionaryOffset: DWord; DictionarySizeInBlocks: Word);
 | 
						|
  protected
 | 
						|
    function getfilename:string;override;
 | 
						|
    function GetPos: longint;override;
 | 
						|
    function GetIsArchive: boolean;override;
 | 
						|
  public
 | 
						|
    constructor createAr(const Aarfn:string;allow_nonar:boolean=false);override;
 | 
						|
    destructor  destroy;override;
 | 
						|
    function  openfile(const fn:string):boolean;override;
 | 
						|
    procedure closefile;override;
 | 
						|
    procedure seek(len:longint);override;
 | 
						|
    property IsCaseSensitive: Boolean read FIsCaseSensitive;
 | 
						|
  end;
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
    uses
 | 
						|
      SysUtils,
 | 
						|
      cstreams,cutils,
 | 
						|
      verbose,
 | 
						|
      omfbase;
 | 
						|
 | 
						|
    const
 | 
						|
      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;
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                 TOmfLibObjectWriter.TOmfLibObjectModule
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor TOmfLibObjectWriter.TOmfLibObjectModule.Create(const fn: string);
 | 
						|
      begin
 | 
						|
        FObjFileName:=fn;
 | 
						|
        FObjData:=TDynamicArray.Create(objbufsize);
 | 
						|
      end;
 | 
						|
 | 
						|
    destructor TOmfLibObjectWriter.TOmfLibObjectModule.Destroy;
 | 
						|
      begin
 | 
						|
        FObjData.Free;
 | 
						|
        inherited Destroy;
 | 
						|
      end;
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                 TOmfLibObjectWriter.TOmfLibDictionaryEntry
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor TOmfLibObjectWriter.TOmfLibDictionaryEntry.Create(
 | 
						|
        HashObjectList: TFPHashObjectList; const aName: TSymStr; aModuleIndex:Integer);
 | 
						|
      begin
 | 
						|
        inherited Create(HashObjectList,aName);
 | 
						|
        ModuleIndex:=aModuleIndex;
 | 
						|
      end;
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                                TOmfLibObjectWriter
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor TOmfLibObjectWriter.createAr(const Aarfn: string);
 | 
						|
      begin
 | 
						|
        createAr(Aarfn,-1);
 | 
						|
      end;
 | 
						|
 | 
						|
    constructor TOmfLibObjectWriter.createAr(const Aarfn: string;PageSize: Integer);
 | 
						|
      begin
 | 
						|
        FPageSize:=PageSize;
 | 
						|
        FLibName:=Aarfn;
 | 
						|
        FLibData:=TDynamicArray.Create(libbufsize);
 | 
						|
        FDictionary:=TFPHashObjectList.Create;
 | 
						|
        FObjectModules:=TFPObjectList.Create(True);
 | 
						|
        FCurrentModule:=nil;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    destructor TOmfLibObjectWriter.destroy;
 | 
						|
      begin
 | 
						|
        if Errorcount=0 then
 | 
						|
          WriteLib;
 | 
						|
        FLibData.Free;
 | 
						|
        FObjectModules.Free;
 | 
						|
        FDictionary.Free;
 | 
						|
        inherited destroy;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TOmfLibObjectWriter.createfile(const fn: string): boolean;
 | 
						|
      begin
 | 
						|
        FCurrentModule:=TOmfLibObjectModule.Create(fn);
 | 
						|
        FCurrentModuleIndex:=FObjectModules.Add(FCurrentModule);
 | 
						|
        createfile:=true;
 | 
						|
        fobjsize:=0;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TOmfLibObjectWriter.closefile;
 | 
						|
      var
 | 
						|
        RawRec: TOmfRawRecord;
 | 
						|
        ObjHeader: TOmfRecord_THEADR;
 | 
						|
      begin
 | 
						|
        FCurrentModule.ObjData.seek(0);
 | 
						|
        RawRec:=TOmfRawRecord.Create;
 | 
						|
        RawRec.ReadFrom(FCurrentModule.ObjData);
 | 
						|
        if RawRec.RecordType<>RT_THEADR then
 | 
						|
          begin
 | 
						|
            RawRec.Free;
 | 
						|
            InternalError(2018060801);
 | 
						|
          end;
 | 
						|
        ObjHeader:=TOmfRecord_THEADR.Create;
 | 
						|
        ObjHeader.DecodeFrom(RawRec);
 | 
						|
        { create a dictionary entry with the module name }
 | 
						|
        TOmfLibDictionaryEntry.Create(FDictionary,ModName2DictEntry(ObjHeader.ModuleName),FCurrentModuleIndex);
 | 
						|
        ObjHeader.Free;
 | 
						|
        RawRec.Free;
 | 
						|
        fobjsize:=0;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TOmfLibObjectWriter.writesym(const sym: string);
 | 
						|
      begin
 | 
						|
        TOmfLibDictionaryEntry.Create(FDictionary,sym,FCurrentModuleIndex);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TOmfLibObjectWriter.write(const b; len: longword);
 | 
						|
      begin
 | 
						|
        inc(fobjsize,len);
 | 
						|
        inc(fsize,len);
 | 
						|
        FCurrentModule.ObjData.write(b,len);
 | 
						|
      end;
 | 
						|
 | 
						|
    procedure TOmfLibObjectWriter.WriteHeader(DictStart: DWord; DictBlocks: Word);
 | 
						|
      var
 | 
						|
        Header: TOmfRecord_LIBHEAD;
 | 
						|
        RawRec: TOmfRawRecord;
 | 
						|
      begin
 | 
						|
        { set header properties }
 | 
						|
        Header:=TOmfRecord_LIBHEAD.Create;
 | 
						|
        Header.PageSize:=FPageSize;
 | 
						|
        Header.DictionaryOffset:=DictStart;
 | 
						|
        Header.DictionarySizeInBlocks:=DictBlocks;
 | 
						|
        Header.CaseSensitive:=true;
 | 
						|
 | 
						|
        { write header }
 | 
						|
        RawRec:=TOmfRawRecord.Create;
 | 
						|
        Header.EncodeTo(RawRec);
 | 
						|
        FLibData.seek(0);
 | 
						|
        RawRec.WriteTo(FLibData);
 | 
						|
        Header.Free;
 | 
						|
        RawRec.Free;
 | 
						|
      end;
 | 
						|
 | 
						|
    procedure TOmfLibObjectWriter.WriteFooter;
 | 
						|
      var
 | 
						|
        Footer: TOmfRecord_LIBEND;
 | 
						|
        RawRec: TOmfRawRecord;
 | 
						|
      begin
 | 
						|
        FLibData.seek(FFooterPos);
 | 
						|
        Footer:=TOmfRecord_LIBEND.Create;
 | 
						|
        Footer.CalculatePaddingBytes(FLibData.Pos);
 | 
						|
        RawRec:=TOmfRawRecord.Create;
 | 
						|
        Footer.EncodeTo(RawRec);
 | 
						|
        RawRec.WriteTo(FLibData);
 | 
						|
        Footer.Free;
 | 
						|
        RawRec.Free;
 | 
						|
      end;
 | 
						|
 | 
						|
    function TOmfLibObjectWriter.TryPageSize(aPageSize: Integer): Boolean;
 | 
						|
      var
 | 
						|
        I: Integer;
 | 
						|
        CurrentPage: Integer;
 | 
						|
        CurrentPos: LongWord;
 | 
						|
        pow: longint;
 | 
						|
      begin
 | 
						|
        if not IsPowerOf2(aPageSize,pow) then
 | 
						|
          internalerror(2018060701);
 | 
						|
        if (pow<4) or (pow>15) then
 | 
						|
          internalerror(2018060702);
 | 
						|
        FPageSize:=aPageSize;
 | 
						|
        { header is at page 0, so first module starts at page 1 }
 | 
						|
        CurrentPage:=1;
 | 
						|
        for I:=0 to FObjectModules.Count-1 do
 | 
						|
          with TOmfLibObjectModule(FObjectModules[I]) do
 | 
						|
            begin
 | 
						|
              if CurrentPage>high(word) then
 | 
						|
                exit(False);
 | 
						|
              PageNum:=CurrentPage;
 | 
						|
              { calculate next page }
 | 
						|
              CurrentPos:=CurrentPage*FPageSize+ObjData.Size;
 | 
						|
              CurrentPage:=(CurrentPos+FPageSize-1) div FPageSize;
 | 
						|
            end;
 | 
						|
        FFooterPos:=CurrentPage*FPageSize;
 | 
						|
        Result:=True;
 | 
						|
      end;
 | 
						|
 | 
						|
    procedure TOmfLibObjectWriter.DeterminePageSize;
 | 
						|
      var
 | 
						|
        I: Integer;
 | 
						|
      begin
 | 
						|
        if (FPageSize<>-1) and TryPageSize(FPageSize) then
 | 
						|
          { success }
 | 
						|
          exit;
 | 
						|
        for I:=4 to 15 do
 | 
						|
          if TryPageSize(1 shl I) then
 | 
						|
            exit;
 | 
						|
        internalerror(2018060703);
 | 
						|
      end;
 | 
						|
 | 
						|
    procedure TOmfLibObjectWriter.WriteLib;
 | 
						|
      var
 | 
						|
        libf: TCCustomFileStream;
 | 
						|
        DictStart, bytes: LongWord;
 | 
						|
        DictBlocks: Word;
 | 
						|
        I: Integer;
 | 
						|
        buf: array [0..1023] of Byte;
 | 
						|
      begin
 | 
						|
        DeterminePageSize;
 | 
						|
        libf:=CFileStreamClass.Create(FLibName,fmCreate);
 | 
						|
        if CStreamError<>0 then
 | 
						|
          begin
 | 
						|
            Message1(exec_e_cant_create_archivefile,FLibName);
 | 
						|
            exit;
 | 
						|
          end;
 | 
						|
        for I:=0 to FObjectModules.Count-1 do
 | 
						|
          with TOmfLibObjectModule(FObjectModules[I]) do
 | 
						|
            begin
 | 
						|
              FLibData.seek(PageNum*FPageSize);
 | 
						|
              ObjData.seek(0);
 | 
						|
              while ObjData.Pos<ObjData.size do
 | 
						|
                begin
 | 
						|
                  bytes:=ObjData.read(buf,Min(SizeOf(buf),ObjData.size-ObjData.Pos));
 | 
						|
                  FLibData.write(buf,bytes);
 | 
						|
                end;
 | 
						|
            end;
 | 
						|
        WriteFooter;
 | 
						|
        DictStart:=FLibData.Pos;
 | 
						|
        DictBlocks:=WriteDictionary;
 | 
						|
        WriteHeader(DictStart,DictBlocks);
 | 
						|
        FLibData.WriteStream(libf);
 | 
						|
        libf.Free;
 | 
						|
      end;
 | 
						|
 | 
						|
    function TOmfLibObjectWriter.WriteDictionary: Word;
 | 
						|
      var
 | 
						|
        nb: Word;
 | 
						|
      begin
 | 
						|
        for nb in OmfLibDictionaryBlockCounts do
 | 
						|
          if TryWriteDictionaryWithSize(nb) then
 | 
						|
            exit(nb);
 | 
						|
        { could not write dictionary, even with the largest number of blocks }
 | 
						|
        internalerror(2015042202);
 | 
						|
      end;
 | 
						|
 | 
						|
        function TOmfLibObjectWriter.TryWriteDictionaryWithSize(nblocks: Word
 | 
						|
      ): 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
 | 
						|
        blocks:=nil;
 | 
						|
        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:=TOmfLibObjectModule(FObjectModules[TOmfLibDictionaryEntry(FDictionary[i]).ModuleIndex]).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;
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                 TOmfLibObjectReader.TOmfLibDictionaryEntry
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
  constructor TOmfLibObjectReader.TOmfLibDictionaryEntry.Create(
 | 
						|
      HashObjectList: TFPHashObjectList; const aName: TSymStr; aPageNum: Word);
 | 
						|
    begin
 | 
						|
      inherited Create(HashObjectList,aName);
 | 
						|
      PageNum:=aPageNum;
 | 
						|
    end;
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                                TOmfLibObjectReader
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
  procedure TOmfLibObjectReader.ReadLibrary;
 | 
						|
    var
 | 
						|
      RawRecord: TOmfRawRecord;
 | 
						|
      Header: TOmfRecord_LIBHEAD;
 | 
						|
    begin
 | 
						|
      RawRecord:=TOmfRawRecord.Create;
 | 
						|
      RawRecord.ReadFrom(Self);
 | 
						|
      Header:=TOmfRecord_LIBHEAD.Create;
 | 
						|
      Header.DecodeFrom(RawRecord);
 | 
						|
      FPageSize:=Header.PageSize;
 | 
						|
      FIsCaseSensitive:=Header.CaseSensitive;
 | 
						|
      ReadDictionary(Header.DictionaryOffset, Header.DictionarySizeInBlocks);
 | 
						|
      Header.Free;
 | 
						|
      RawRecord.Free;
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TOmfLibObjectReader.ReadDictionary(DictionaryOffset: DWord; DictionarySizeInBlocks: Word);
 | 
						|
    const
 | 
						|
      nbuckets=37;
 | 
						|
      freespace=nbuckets;
 | 
						|
    type
 | 
						|
      PBlock=^TBlock;
 | 
						|
      TBlock=array[0..511] of byte;
 | 
						|
    var
 | 
						|
      blocks: array of TBlock;
 | 
						|
      blocknr: Integer;
 | 
						|
      block: PBlock;
 | 
						|
      ofs: Integer;
 | 
						|
      bucket: Integer;
 | 
						|
      length_of_string: Byte;
 | 
						|
      name: string;
 | 
						|
      PageNum: Integer;
 | 
						|
    begin
 | 
						|
      blocks:=nil;
 | 
						|
      name:='';
 | 
						|
      seek(DictionaryOffset);
 | 
						|
      SetLength(blocks,DictionarySizeInBlocks);
 | 
						|
      read(blocks[0],DictionarySizeInBlocks*SizeOf(TBlock));
 | 
						|
      for blocknr:=0 to DictionarySizeInBlocks-1 do
 | 
						|
        begin
 | 
						|
          block:=@(blocks[blocknr]);
 | 
						|
          for bucket:=0 to nbuckets-1 do
 | 
						|
            if block^[bucket]<>0 then
 | 
						|
              begin
 | 
						|
                ofs:=2*block^[bucket];
 | 
						|
                length_of_string:=block^[ofs];
 | 
						|
                if (ofs+1+length_of_string+1)>High(TBlock) then
 | 
						|
                  begin
 | 
						|
                    Comment(V_Error,'OMF dictionary entry goes beyond end of block');
 | 
						|
                    continue;
 | 
						|
                  end;
 | 
						|
                SetLength(name,length_of_string);
 | 
						|
                Move(block^[ofs+1],name[1],length_of_string);
 | 
						|
                PageNum:=block^[ofs+1+length_of_string]+
 | 
						|
                         block^[ofs+1+length_of_string+1] shl 8;
 | 
						|
                TOmfLibDictionaryEntry.create(LibSymbols,name,PageNum);
 | 
						|
              end;
 | 
						|
        end;
 | 
						|
    end;
 | 
						|
 | 
						|
  function TOmfLibObjectReader.getfilename: string;
 | 
						|
    begin
 | 
						|
      Result:=inherited getfilename;
 | 
						|
      if CurrMemberName<>'' then
 | 
						|
        result:=result+'('+CurrMemberName+')';
 | 
						|
    end;
 | 
						|
 | 
						|
  function TOmfLibObjectReader.GetPos: longint;
 | 
						|
    begin
 | 
						|
      result:=inherited GetPos-CurrMemberPos;
 | 
						|
    end;
 | 
						|
 | 
						|
  function TOmfLibObjectReader.GetIsArchive: boolean;
 | 
						|
    begin
 | 
						|
      result:=islib;
 | 
						|
    end;
 | 
						|
 | 
						|
  constructor TOmfLibObjectReader.createAr(const Aarfn: string; allow_nonar: boolean);
 | 
						|
    var
 | 
						|
      RecType: Byte;
 | 
						|
    begin
 | 
						|
      inherited Create;
 | 
						|
      LibSymbols:=TFPHashObjectList.Create(true);
 | 
						|
      CurrMemberPos:=0;
 | 
						|
      CurrMemberName:='';
 | 
						|
      if inherited openfile(Aarfn) then
 | 
						|
        begin
 | 
						|
          Read(RecType,1);
 | 
						|
          Seek(0);
 | 
						|
          islib:=RecType=RT_LIBHEAD;
 | 
						|
          if islib then
 | 
						|
            ReadLibrary
 | 
						|
          else if (not allow_nonar) then
 | 
						|
            Comment(V_Error,'Not an OMF library file, illegal magic: '+filename);
 | 
						|
        end;
 | 
						|
    end;
 | 
						|
 | 
						|
  destructor TOmfLibObjectReader.destroy;
 | 
						|
    begin
 | 
						|
      inherited closefile;
 | 
						|
      LibSymbols.Free;
 | 
						|
      inherited Destroy;
 | 
						|
    end;
 | 
						|
 | 
						|
  function TOmfLibObjectReader.openfile(const fn: string): boolean;
 | 
						|
    var
 | 
						|
      libsym: TOmfLibDictionaryEntry;
 | 
						|
      RawRec: TOmfRawRecord;
 | 
						|
      Header: TOmfRecord_THEADR;
 | 
						|
    begin
 | 
						|
      result:=false;
 | 
						|
      libsym:=TOmfLibDictionaryEntry(LibSymbols.Find(ModName2DictEntry(fn)));
 | 
						|
      if not assigned(libsym) then
 | 
						|
        exit;
 | 
						|
      CurrMemberPos:=libsym.PageNum*FPageSize;
 | 
						|
      inherited Seek(CurrMemberPos);
 | 
						|
 | 
						|
      { read the header, to obtain the module name }
 | 
						|
      RawRec:=TOmfRawRecord.Create;
 | 
						|
      RawRec.ReadFrom(self);
 | 
						|
      Header:=TOmfRecord_THEADR.Create;
 | 
						|
      Header.DecodeFrom(RawRec);
 | 
						|
      CurrMemberName:=Header.ModuleName;
 | 
						|
      Header.Free;
 | 
						|
      RawRec.Free;
 | 
						|
 | 
						|
      { go back to the beginning of the file }
 | 
						|
      inherited Seek(CurrMemberPos);
 | 
						|
      result:=true;
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TOmfLibObjectReader.closefile;
 | 
						|
    begin
 | 
						|
      CurrMemberPos:=0;
 | 
						|
      CurrMemberName:='';
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TOmfLibObjectReader.seek(len: longint);
 | 
						|
    begin
 | 
						|
      inherited Seek(CurrMemberPos+len);
 | 
						|
    end;
 | 
						|
 | 
						|
end.
 |