owar.pas 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. {
  2. $Id$
  3. Copyright (c) 1999 by Peter Vreman
  4. Contains the stuff for writing .a files directly
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit owar;
  19. interface
  20. uses
  21. cobjects,owbase;
  22. type
  23. tarhdr=packed record
  24. name : array[0..15] of char;
  25. date : array[0..11] of char;
  26. uid : array[0..5] of char;
  27. gid : array[0..5] of char;
  28. mode : array[0..7] of char;
  29. size : array[0..9] of char;
  30. fmag : array[0..1] of char;
  31. end;
  32. parobjectwriter=^tarobjectwriter;
  33. tarobjectwriter=object(tobjectwriter)
  34. constructor Init(const Aarfn:string);
  35. destructor Done;virtual;
  36. procedure create(const fn:string);virtual;
  37. procedure close;virtual;
  38. procedure writesym(sym:string);virtual;
  39. procedure write(var b;len:longint);virtual;
  40. private
  41. arfn : string;
  42. arhdr : tarhdr;
  43. symreloc,
  44. symstr,
  45. lfnstr,
  46. ardata,
  47. objdata : PDynamicArray;
  48. objfixup : longint;
  49. objfn : string;
  50. timestamp : string[12];
  51. procedure createarhdr(fn:string;size:longint;const gid,uid,mode:string);
  52. procedure writear;
  53. end;
  54. implementation
  55. uses
  56. {$ifdef Delphi}
  57. dmisc,
  58. {$endif Delphi}
  59. dos;
  60. const
  61. {$ifdef TP}
  62. symrelocbufsize = 32;
  63. symstrbufsize = 256;
  64. lfnstrbufsize = 256;
  65. arbufsize = 256;
  66. objbufsize = 256;
  67. {$else}
  68. symrelocbufsize = 1024;
  69. symstrbufsize = 8192;
  70. lfnstrbufsize = 4096;
  71. arbufsize = 65536;
  72. objbufsize = 16384;
  73. {$endif}
  74. {*****************************************************************************
  75. Helpers
  76. *****************************************************************************}
  77. const
  78. C1970=2440588;
  79. D0=1461;
  80. D1=146097;
  81. D2=1721119;
  82. Function Gregorian2Julian(DT:DateTime):LongInt;
  83. Var
  84. Century,XYear,Month : LongInt;
  85. Begin
  86. Month:=DT.Month;
  87. If Month<=2 Then
  88. Begin
  89. Dec(DT.Year);
  90. Inc(Month,12);
  91. End;
  92. Dec(Month,3);
  93. Century:=(longint(DT.Year Div 100)*D1) shr 2;
  94. XYear:=(longint(DT.Year Mod 100)*D0) shr 2;
  95. Gregorian2Julian:=((((Month*153)+2) div 5)+DT.Day)+D2+XYear+Century;
  96. End;
  97. function DT2Unix(DT:DateTime):LongInt;
  98. Begin
  99. DT2Unix:=(Gregorian2Julian(DT)-C1970)*86400+(LongInt(DT.Hour)*3600)+(DT.Min*60)+DT.Sec;
  100. end;
  101. {*****************************************************************************
  102. TArObjectWriter
  103. *****************************************************************************}
  104. constructor tarobjectwriter.init(const Aarfn:string);
  105. var
  106. time : datetime;
  107. dummy : word;
  108. begin
  109. arfn:=Aarfn;
  110. new(arData,init(1,arbufsize));
  111. new(symreloc,init(4,symrelocbufsize));
  112. new(symstr,init(1,symstrbufsize));
  113. new(lfnstr,init(1,lfnstrbufsize));
  114. { create timestamp }
  115. getdate(time.year,time.month,time.day,dummy);
  116. gettime(time.hour,time.min,time.sec,dummy);
  117. Str(DT2Unix(time),timestamp);
  118. end;
  119. destructor tarobjectwriter.done;
  120. begin
  121. writear;
  122. dispose(arData,done);
  123. dispose(symreloc,done);
  124. dispose(symstr,done);
  125. dispose(lfnstr,done);
  126. end;
  127. procedure tarobjectwriter.createarhdr(fn:string;size:longint;const gid,uid,mode:string);
  128. var
  129. tmp : string[9];
  130. begin
  131. fillchar(arhdr,sizeof(tarhdr),' ');
  132. { create ar header }
  133. fn:=fn+'/';
  134. if length(fn)>16 then
  135. begin
  136. arhdr.name[0]:='/';
  137. str(lfnstr^.usedsize,tmp);
  138. move(tmp[1],arhdr.name[1],length(tmp));
  139. fn:=fn+#10;
  140. lfnstr^.write(fn[1],length(fn));
  141. end
  142. else
  143. move(fn[1],arhdr.name,length(fn));
  144. { don't write a date if also no gid/uid/mode is specified }
  145. if gid<>'' then
  146. move(timestamp[1],arhdr.date,sizeof(timestamp));
  147. str(size,tmp);
  148. move(tmp[1],arhdr.size,length(tmp));
  149. move(gid[1],arhdr.gid,length(gid));
  150. move(uid[1],arhdr.uid,length(uid));
  151. move(mode[1],arhdr.mode,length(mode));
  152. arhdr.fmag:='`'#10;
  153. end;
  154. procedure tarobjectwriter.create(const fn:string);
  155. begin
  156. objfn:=fn;
  157. objfixup:=ardata^.usedsize;
  158. { reset size }
  159. new(objdata,init(1,objbufsize));
  160. end;
  161. procedure tarobjectwriter.close;
  162. begin
  163. objdata^.align(2);
  164. { fix the size in the header }
  165. createarhdr(objfn,objdata^.usedsize,'42','42','644');
  166. { write the header }
  167. ardata^.write(arhdr,sizeof(tarhdr));
  168. { write the data of this objfile }
  169. ardata^.write(objdata^.data^,objdata^.usedsize);
  170. { free this object }
  171. dispose(objdata,done);
  172. end;
  173. procedure tarobjectwriter.writesym(sym:string);
  174. begin
  175. sym:=sym+#0;
  176. symreloc^.write(objfixup,1);
  177. symstr^.write(sym[1],length(sym));
  178. end;
  179. procedure tarobjectwriter.write(var b;len:longint);
  180. begin
  181. objdata^.write(b,len);
  182. end;
  183. procedure tarobjectwriter.writear;
  184. function lsb2msb(l:longint):longint;
  185. type
  186. bytearr=array[0..3] of byte;
  187. var
  188. l1 : longint;
  189. begin
  190. bytearr(l1)[0]:=bytearr(l)[3];
  191. bytearr(l1)[1]:=bytearr(l)[2];
  192. bytearr(l1)[2]:=bytearr(l)[1];
  193. bytearr(l1)[3]:=bytearr(l)[0];
  194. lsb2msb:=l1;
  195. end;
  196. const
  197. armagic:array[1..8] of char='!<arch>'#10;
  198. type
  199. plongint=^longint;
  200. var
  201. arf : file;
  202. fixup,
  203. relocs,i : longint;
  204. begin
  205. assign(arf,arfn);
  206. {$I-}
  207. rewrite(arf,1);
  208. {$I+}
  209. if ioresult<>0 then
  210. exit;
  211. blockwrite(arf,armagic,sizeof(armagic));
  212. { align first, because we need the size for the fixups of the symbol reloc }
  213. if lfnstr^.usedsize>0 then
  214. lfnstr^.align(2);
  215. if symreloc^.usedsize>0 then
  216. begin
  217. symstr^.align(2);
  218. fixup:=12+sizeof(tarhdr)+symreloc^.usedsize+symstr^.usedsize;
  219. if lfnstr^.usedsize>0 then
  220. inc(fixup,lfnstr^.usedsize+sizeof(tarhdr));
  221. relocs:=symreloc^.count;
  222. for i:=0to relocs-1 do
  223. plongint(@symreloc^.data[i*4])^:=lsb2msb(plongint(@symreloc^.data[i*4])^+fixup);
  224. createarhdr('',4+symreloc^.usedsize+symstr^.usedsize,'0','0','0');
  225. blockwrite(arf,arhdr,sizeof(tarhdr));
  226. relocs:=lsb2msb(relocs);
  227. blockwrite(arf,relocs,4);
  228. blockwrite(arf,symreloc^.data^,symreloc^.usedsize);
  229. blockwrite(arf,symstr^.data^,symstr^.usedsize);
  230. end;
  231. if lfnstr^.usedsize>0 then
  232. begin
  233. createarhdr('/',lfnstr^.usedsize,'','','');
  234. blockwrite(arf,arhdr,sizeof(tarhdr));
  235. blockwrite(arf,lfnstr^.data^,lfnstr^.usedsize);
  236. end;
  237. blockwrite(arf,ardata^.data^,ardata^.usedsize);
  238. system.close(arf);
  239. end;
  240. end.
  241. {
  242. $Log$
  243. Revision 1.2 1999-05-04 21:44:53 florian
  244. * changes to compile it with Delphi 4.0
  245. Revision 1.1 1999/05/01 13:24:26 peter
  246. * merged nasm compiler
  247. * old asm moved to oldasm/
  248. Revision 1.1 1999/03/18 20:30:51 peter
  249. + .a writer
  250. }