owomflib.pas 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. {
  2. Copyright (c) 2015 by Nikolay Nikolov
  3. Contains the stuff for writing Relocatable Object Module Format (OMF)
  4. libraries directly. This is the object format used on the i8086-msdos
  5. platform (also known as .lib files in the dos world, even though Free
  6. Pascal uses the extension .a).
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ****************************************************************************
  19. }
  20. unit owomflib;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. cclasses,
  25. owbase;
  26. type
  27. { TOmfLibObjectWriter }
  28. TOmfLibObjectWriter=class(TObjectWriter)
  29. private
  30. FPageSize: Integer;
  31. FLibName: string;
  32. FLibData: TDynamicArray;
  33. FObjFileName: string;
  34. FObjData: TDynamicArray;
  35. FObjStartPage: Word;
  36. procedure WriteHeader(DictStart: DWord; DictBlocks: Word);
  37. procedure WriteFooter;
  38. procedure WriteLib;
  39. public
  40. constructor createAr(const Aarfn:string);override;
  41. destructor destroy;override;
  42. function createfile(const fn:string):boolean;override;
  43. procedure closefile;override;
  44. procedure writesym(const sym:string);override;
  45. procedure write(const b;len:longword);override;
  46. end;
  47. implementation
  48. uses
  49. SysUtils,
  50. cstreams,
  51. globals,
  52. verbose,
  53. omfbase;
  54. const
  55. libbufsize = 65536;
  56. objbufsize = 65536;
  57. {*****************************************************************************
  58. TOmfLibObjectWriter
  59. *****************************************************************************}
  60. constructor TOmfLibObjectWriter.createAr(const Aarfn: string);
  61. begin
  62. FPageSize:=512;
  63. FLibName:=Aarfn;
  64. FLibData:=TDynamicArray.Create(libbufsize);
  65. { header is at page 0, so first module starts at page 1 }
  66. FObjStartPage:=1;
  67. end;
  68. destructor TOmfLibObjectWriter.destroy;
  69. begin
  70. if Errorcount=0 then
  71. WriteLib;
  72. FLibData.Free;
  73. FObjData.Free;
  74. inherited destroy;
  75. end;
  76. function TOmfLibObjectWriter.createfile(const fn: string): boolean;
  77. begin
  78. FObjFileName:=fn;
  79. FreeAndNil(FObjData);
  80. FObjData:=TDynamicArray.Create(objbufsize);
  81. createfile:=true;
  82. fobjsize:=0;
  83. end;
  84. procedure TOmfLibObjectWriter.closefile;
  85. var
  86. RawRec: TOmfRawRecord;
  87. begin
  88. FLibData.seek(FObjStartPage*FPageSize);
  89. FObjData.seek(0);
  90. RawRec:=TOmfRawRecord.Create;
  91. repeat
  92. RawRec.ReadFrom(FObjData);
  93. RawRec.WriteTo(FLibData);
  94. until RawRec.RecordType in [RT_MODEND,RT_MODEND32];
  95. RawRec.Free;
  96. { calculate start page of next module }
  97. FObjStartPage:=(FLibData.Pos+FPageSize-1) div FPageSize;
  98. fobjsize:=0;
  99. end;
  100. procedure TOmfLibObjectWriter.writesym(const sym: string);
  101. begin
  102. inherited writesym(sym);
  103. end;
  104. procedure TOmfLibObjectWriter.write(const b; len: longword);
  105. begin
  106. inc(fobjsize,len);
  107. inc(fsize,len);
  108. FObjData.write(b,len);
  109. end;
  110. procedure TOmfLibObjectWriter.WriteHeader(DictStart: DWord; DictBlocks: Word);
  111. var
  112. Header: TOmfRecord_LIBHEAD;
  113. RawRec: TOmfRawRecord;
  114. begin
  115. { set header properties }
  116. Header:=TOmfRecord_LIBHEAD.Create;
  117. Header.PageSize:=FPageSize;
  118. Header.DictionaryOffset:=DictStart;
  119. Header.DictionarySizeInBlocks:=DictBlocks;
  120. Header.CaseSensitive:=true;
  121. { write header }
  122. RawRec:=TOmfRawRecord.Create;
  123. Header.EncodeTo(RawRec);
  124. FLibData.seek(0);
  125. RawRec.WriteTo(FLibData);
  126. Header.Free;
  127. RawRec.Free;
  128. end;
  129. procedure TOmfLibObjectWriter.WriteFooter;
  130. var
  131. Footer: TOmfRecord_LIBEND;
  132. RawRec: TOmfRawRecord;
  133. begin
  134. FLibData.seek(FObjStartPage*FPageSize);
  135. Footer:=TOmfRecord_LIBEND.Create;
  136. Footer.CalculatePaddingBytes(FLibData.Pos);
  137. RawRec:=TOmfRawRecord.Create;
  138. Footer.EncodeTo(RawRec);
  139. RawRec.WriteTo(FLibData);
  140. Footer.Free;
  141. RawRec.Free;
  142. end;
  143. procedure TOmfLibObjectWriter.WriteLib;
  144. var
  145. libf: TCCustomFileStream;
  146. begin
  147. libf:=CFileStreamClass.Create(FLibName,fmCreate);
  148. if CStreamError<>0 then
  149. begin
  150. Message1(exec_e_cant_create_archivefile,FLibName);
  151. exit;
  152. end;
  153. WriteFooter;
  154. WriteHeader(FLibData.Pos,2);
  155. FLibData.WriteStream(libf);
  156. libf.Free;
  157. end;
  158. end.