ppu.pas 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Routines to read/write ppu files
  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 ppu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cpuinfo;
  23. { Also write the ppu if only crc if done, this can be used with ppudump to
  24. see the differences between the intf and implementation }
  25. { define INTFPPU}
  26. {$ifdef Test_Double_checksum}
  27. var
  28. CRCFile : text;
  29. const
  30. CRC_array_Size = 200000;
  31. type
  32. tcrc_array = array[0..crc_array_size] of longint;
  33. pcrc_array = ^tcrc_array;
  34. {$endif Test_Double_checksum}
  35. const
  36. {$ifdef ansistring_bits}
  37. CurrentPPUVersion=41;
  38. {$else}
  39. CurrentPPUVersion=40;
  40. {$endif}
  41. { buffer sizes }
  42. maxentrysize = 1024;
  43. ppubufsize = 16384;
  44. {ppu entries}
  45. mainentryid = 1;
  46. subentryid = 2;
  47. {special}
  48. iberror = 0;
  49. ibstartdefs = 248;
  50. ibenddefs = 249;
  51. ibstartsyms = 250;
  52. ibendsyms = 251;
  53. ibendinterface = 252;
  54. ibendimplementation = 253;
  55. ibendbrowser = 254;
  56. ibend = 255;
  57. {general}
  58. ibmodulename = 1;
  59. ibsourcefiles = 2;
  60. ibloadunit = 3;
  61. ibinitunit = 4;
  62. iblinkunitofiles = 5;
  63. iblinkunitstaticlibs = 6;
  64. iblinkunitsharedlibs = 7;
  65. iblinkotherofiles = 8;
  66. iblinkotherstaticlibs = 9;
  67. iblinkothersharedlibs = 10;
  68. ibdbxcount = 11;
  69. ibsymref = 12;
  70. ibdefref = 13;
  71. ibendsymtablebrowser = 14;
  72. ibbeginsymtablebrowser = 15;
  73. ibusedmacros = 16;
  74. ibderefdata = 17;
  75. {syms}
  76. ibtypesym = 20;
  77. ibprocsym = 21;
  78. ibvarsym = 22;
  79. ibconstsym = 23;
  80. ibenumsym = 24;
  81. ibtypedconstsym = 25;
  82. ibabsolutesym = 26;
  83. ibpropertysym = 27;
  84. ibvarsym_C = 28;
  85. ibunitsym = 29; { needed for browser }
  86. iblabelsym = 30;
  87. ibsyssym = 31;
  88. ibrttisym = 32;
  89. {definitions}
  90. iborddef = 40;
  91. ibpointerdef = 41;
  92. ibarraydef = 42;
  93. ibprocdef = 43;
  94. ibshortstringdef = 44;
  95. ibrecorddef = 45;
  96. ibfiledef = 46;
  97. ibformaldef = 47;
  98. ibobjectdef = 48;
  99. ibenumdef = 49;
  100. ibsetdef = 50;
  101. ibprocvardef = 51;
  102. ibfloatdef = 52;
  103. ibclassrefdef = 53;
  104. iblongstringdef = 54;
  105. {$ifdef ansistring_bits}
  106. ibansistring16def = 58;
  107. ibansistring32def = 55;
  108. ibansistring64def = 59;
  109. {$else}
  110. ibansistringdef = 55;
  111. {$endif}
  112. ibwidestringdef = 56;
  113. ibvariantdef = 57;
  114. {implementation/objectdata}
  115. ibnodetree = 80;
  116. ibasmsymbols = 81;
  117. { unit flags }
  118. uf_init = $1;
  119. uf_finalize = $2;
  120. uf_big_endian = $4;
  121. uf_has_dbx = $8;
  122. uf_has_browser = $10;
  123. uf_in_library = $20; { is the file in another file than <ppufile>.* ? }
  124. uf_smart_linked = $40; { the ppu can be smartlinked }
  125. uf_static_linked = $80; { the ppu can be linked static }
  126. uf_shared_linked = $100; { the ppu can be linked shared }
  127. uf_local_browser = $200;
  128. uf_no_link = $400; { unit has no .o generated, but can still have
  129. external linking! }
  130. uf_has_resources = $800; { unit has resource section }
  131. uf_little_endian = $1000;
  132. uf_release = $2000; { unit was compiled with -Ur option }
  133. uf_threadvars = $4000; { unit has threadvars }
  134. uf_fpu_emulation = $8000; { this unit was compiled with fpu emulation on }
  135. type
  136. ppureal=extended;
  137. tppuerror=(ppuentrytoobig,ppuentryerror);
  138. tppuheader=packed record { 36 bytes }
  139. id : array[1..3] of char; { = 'PPU' }
  140. ver : array[1..3] of char;
  141. compiler : word;
  142. cpu : word;
  143. target : word;
  144. flags : longint;
  145. size : longint; { size of the ppufile without header }
  146. checksum : cardinal; { checksum for this ppufile }
  147. interface_checksum : cardinal;
  148. future : array[0..2] of longint;
  149. end;
  150. tppuentry=packed record
  151. size : longint;
  152. id : byte;
  153. nr : byte;
  154. end;
  155. tppufile=class
  156. private
  157. f : file;
  158. mode : byte; {0 - Closed, 1 - Reading, 2 - Writing}
  159. fname : string;
  160. fsize : integer;
  161. {$ifdef Test_Double_checksum}
  162. public
  163. crcindex,
  164. crc_index,
  165. crcindex2,
  166. crc_index2 : cardinal;
  167. crc_test,
  168. crc_test2 : pcrc_array;
  169. private
  170. {$endif def Test_Double_checksum}
  171. change_endian : boolean;
  172. buf : pchar;
  173. bufstart,
  174. bufsize,
  175. bufidx : integer;
  176. entrybufstart,
  177. entrystart,
  178. entryidx : integer;
  179. entry : tppuentry;
  180. closed,
  181. tempclosed : boolean;
  182. closepos : integer;
  183. public
  184. entrytyp : byte;
  185. header : tppuheader;
  186. size : integer;
  187. crc,
  188. interface_crc : cardinal;
  189. error,
  190. do_crc,
  191. do_interface_crc : boolean;
  192. crc_only : boolean; { used to calculate interface_crc before implementation }
  193. constructor Create(const fn:string);
  194. destructor Destroy;override;
  195. procedure flush;
  196. procedure closefile;
  197. function CheckPPUId:boolean;
  198. function GetPPUVersion:integer;
  199. procedure NewHeader;
  200. procedure NewEntry;
  201. {read}
  202. function openfile:boolean;
  203. procedure reloadbuf;
  204. procedure readdata(var b;len:integer);
  205. procedure skipdata(len:integer);
  206. function readentry:byte;
  207. function EndOfEntry:boolean;
  208. function entrysize:longint;
  209. procedure getdatabuf(var b;len:integer;var res:integer);
  210. procedure getdata(var b;len:integer);
  211. function getbyte:byte;
  212. function getword:word;
  213. function getlongint:longint;
  214. function getint64:int64;
  215. function getaint:aint;
  216. function getreal:ppureal;
  217. function getstring:string;
  218. procedure getnormalset(var b);
  219. procedure getsmallset(var b);
  220. function skipuntilentry(untilb:byte):boolean;
  221. {write}
  222. function createfile:boolean;
  223. procedure writeheader;
  224. procedure writebuf;
  225. procedure writedata(const b;len:integer);
  226. procedure writeentry(ibnr:byte);
  227. procedure putdata(const b;len:integer);
  228. procedure putbyte(b:byte);
  229. procedure putword(w:word);
  230. procedure putlongint(l:longint);
  231. procedure putint64(i:int64);
  232. procedure putaint(i:aint);
  233. procedure putreal(d:ppureal);
  234. procedure putstring(s:string);
  235. procedure putnormalset(const b);
  236. procedure putsmallset(const b);
  237. procedure tempclose;
  238. function tempopen:boolean;
  239. end;
  240. implementation
  241. uses
  242. {$ifdef Test_Double_checksum}
  243. comphook,
  244. {$endif def Test_Double_checksum}
  245. crc,
  246. cutils;
  247. {*****************************************************************************
  248. Endian Handling
  249. *****************************************************************************}
  250. Function SwapLong(x : longint): longint;
  251. var
  252. y : word;
  253. z : word;
  254. Begin
  255. y := x shr 16;
  256. y := word(longint(y) shl 8) or (y shr 8);
  257. z := x and $FFFF;
  258. z := word(longint(z) shl 8) or (z shr 8);
  259. SwapLong := (longint(z) shl 16) or longint(y);
  260. End;
  261. Function SwapWord(x : word): word;
  262. var
  263. z : byte;
  264. Begin
  265. z := x shr 8;
  266. x := x and $ff;
  267. x := word(x shl 8);
  268. SwapWord := x or z;
  269. End;
  270. {*****************************************************************************
  271. TPPUFile
  272. *****************************************************************************}
  273. constructor tppufile.Create(const fn:string);
  274. begin
  275. fname:=fn;
  276. change_endian:=false;
  277. crc_only:=false;
  278. Mode:=0;
  279. NewHeader;
  280. Error:=false;
  281. closed:=true;
  282. tempclosed:=false;
  283. getmem(buf,ppubufsize);
  284. end;
  285. destructor tppufile.destroy;
  286. begin
  287. closefile;
  288. if assigned(buf) then
  289. freemem(buf,ppubufsize);
  290. end;
  291. procedure tppufile.flush;
  292. begin
  293. if Mode=2 then
  294. writebuf;
  295. end;
  296. procedure tppufile.closefile;
  297. begin
  298. {$ifdef Test_Double_checksum}
  299. if mode=2 then
  300. begin
  301. if assigned(crc_test) then
  302. dispose(crc_test);
  303. if assigned(crc_test2) then
  304. dispose(crc_test2);
  305. end;
  306. {$endif Test_Double_checksum}
  307. if Mode<>0 then
  308. begin
  309. Flush;
  310. {$I-}
  311. system.close(f);
  312. {$I+}
  313. if ioresult<>0 then;
  314. Mode:=0;
  315. closed:=true;
  316. end;
  317. end;
  318. function tppufile.CheckPPUId:boolean;
  319. begin
  320. CheckPPUId:=((Header.Id[1]='P') and (Header.Id[2]='P') and (Header.Id[3]='U'));
  321. end;
  322. function tppufile.GetPPUVersion:integer;
  323. var
  324. l : integer;
  325. code : integer;
  326. begin
  327. Val(header.ver[1]+header.ver[2]+header.ver[3],l,code);
  328. if code=0 then
  329. GetPPUVersion:=l
  330. else
  331. GetPPUVersion:=0;
  332. end;
  333. procedure tppufile.NewHeader;
  334. var
  335. s : string;
  336. begin
  337. fillchar(header,sizeof(tppuheader),0);
  338. str(currentppuversion,s);
  339. while length(s)<3 do
  340. s:='0'+s;
  341. with header do
  342. begin
  343. Id[1]:='P';
  344. Id[2]:='P';
  345. Id[3]:='U';
  346. Ver[1]:=s[1];
  347. Ver[2]:=s[2];
  348. Ver[3]:=s[3];
  349. end;
  350. end;
  351. {*****************************************************************************
  352. TPPUFile Reading
  353. *****************************************************************************}
  354. function tppufile.openfile:boolean;
  355. var
  356. ofmode : byte;
  357. i : integer;
  358. begin
  359. openfile:=false;
  360. assign(f,fname);
  361. ofmode:=filemode;
  362. filemode:=$0;
  363. {$I-}
  364. reset(f,1);
  365. {$I+}
  366. filemode:=ofmode;
  367. if ioresult<>0 then
  368. exit;
  369. closed:=false;
  370. {read ppuheader}
  371. fsize:=filesize(f);
  372. if fsize<sizeof(tppuheader) then
  373. exit;
  374. blockread(f,header,sizeof(tppuheader),i);
  375. { The header is always stored in little endian order }
  376. { therefore swap if on a big endian machine }
  377. {$IFDEF ENDIAN_BIG}
  378. header.compiler := SwapWord(header.compiler);
  379. header.cpu := SwapWord(header.cpu);
  380. header.target := SwapWord(header.target);
  381. header.flags := SwapLong(header.flags);
  382. header.size := SwapLong(header.size);
  383. header.checksum := cardinal(SwapLong(longint(header.checksum)));
  384. header.interface_checksum := cardinal(SwapLong(longint(header.interface_checksum)));
  385. {$ENDIF}
  386. { the PPU DATA is stored in native order }
  387. if (header.flags and uf_big_endian) = uf_big_endian then
  388. Begin
  389. {$IFDEF ENDIAN_LITTLE}
  390. change_endian := TRUE;
  391. {$ELSE}
  392. change_endian := FALSE;
  393. {$ENDIF}
  394. End
  395. else if (header.flags and uf_little_endian) = uf_little_endian then
  396. Begin
  397. {$IFDEF ENDIAN_BIG}
  398. change_endian := TRUE;
  399. {$ELSE}
  400. change_endian := FALSE;
  401. {$ENDIF}
  402. End;
  403. {reset buffer}
  404. bufstart:=i;
  405. bufsize:=0;
  406. bufidx:=0;
  407. Mode:=1;
  408. FillChar(entry,sizeof(tppuentry),0);
  409. entryidx:=0;
  410. entrystart:=0;
  411. entrybufstart:=0;
  412. Error:=false;
  413. openfile:=true;
  414. end;
  415. procedure tppufile.reloadbuf;
  416. begin
  417. inc(bufstart,bufsize);
  418. blockread(f,buf^,ppubufsize,bufsize);
  419. bufidx:=0;
  420. end;
  421. procedure tppufile.readdata(var b;len:integer);
  422. var
  423. p : pchar;
  424. left,
  425. idx : integer;
  426. begin
  427. p:=pchar(@b);
  428. idx:=0;
  429. while len>0 do
  430. begin
  431. left:=bufsize-bufidx;
  432. if len>left then
  433. begin
  434. move(buf[bufidx],p[idx],left);
  435. dec(len,left);
  436. inc(idx,left);
  437. reloadbuf;
  438. if bufsize=0 then
  439. exit;
  440. end
  441. else
  442. begin
  443. move(buf[bufidx],p[idx],len);
  444. inc(bufidx,len);
  445. exit;
  446. end;
  447. end;
  448. end;
  449. procedure tppufile.skipdata(len:integer);
  450. var
  451. left : integer;
  452. begin
  453. while len>0 do
  454. begin
  455. left:=bufsize-bufidx;
  456. if len>left then
  457. begin
  458. dec(len,left);
  459. reloadbuf;
  460. if bufsize=0 then
  461. exit;
  462. end
  463. else
  464. begin
  465. inc(bufidx,len);
  466. exit;
  467. end;
  468. end;
  469. end;
  470. function tppufile.readentry:byte;
  471. begin
  472. if entryidx<entry.size then
  473. skipdata(entry.size-entryidx);
  474. readdata(entry,sizeof(tppuentry));
  475. entrystart:=bufstart+bufidx;
  476. entryidx:=0;
  477. if not(entry.id in [mainentryid,subentryid]) then
  478. begin
  479. readentry:=iberror;
  480. error:=true;
  481. exit;
  482. end;
  483. readentry:=entry.nr;
  484. end;
  485. function tppufile.endofentry:boolean;
  486. begin
  487. endofentry:=(entryidx>=entry.size);
  488. end;
  489. function tppufile.entrysize:longint;
  490. begin
  491. entrysize:=entry.size;
  492. end;
  493. procedure tppufile.getdatabuf(var b;len:integer;var res:integer);
  494. begin
  495. if entryidx+len>entry.size then
  496. res:=entry.size-entryidx
  497. else
  498. res:=len;
  499. readdata(b,res);
  500. inc(entryidx,res);
  501. end;
  502. procedure tppufile.getdata(var b;len:integer);
  503. begin
  504. if entryidx+len>entry.size then
  505. begin
  506. error:=true;
  507. exit;
  508. end;
  509. readdata(b,len);
  510. inc(entryidx,len);
  511. end;
  512. function tppufile.getbyte:byte;
  513. var
  514. b : byte;
  515. begin
  516. if entryidx+1>entry.size then
  517. begin
  518. error:=true;
  519. getbyte:=0;
  520. exit;
  521. end;
  522. readdata(b,1);
  523. getbyte:=b;
  524. inc(entryidx);
  525. end;
  526. function tppufile.getword:word;
  527. var
  528. w : word;
  529. begin
  530. if entryidx+2>entry.size then
  531. begin
  532. error:=true;
  533. getword:=0;
  534. exit;
  535. end;
  536. readdata(w,2);
  537. if change_endian then
  538. getword:=swapword(w)
  539. else
  540. getword:=w;
  541. inc(entryidx,2);
  542. end;
  543. function tppufile.getlongint:longint;
  544. var
  545. l : longint;
  546. begin
  547. if entryidx+4>entry.size then
  548. begin
  549. error:=true;
  550. getlongint:=0;
  551. exit;
  552. end;
  553. readdata(l,4);
  554. if change_endian then
  555. getlongint:=swaplong(l)
  556. else
  557. getlongint:=l;
  558. inc(entryidx,4);
  559. end;
  560. function tppufile.getint64:int64;
  561. var
  562. i : int64;
  563. begin
  564. if entryidx+8>entry.size then
  565. begin
  566. error:=true;
  567. result:=0;
  568. exit;
  569. end;
  570. readdata(i,8);
  571. if change_endian then
  572. result:=swapint64(i)
  573. else
  574. result:=i;
  575. inc(entryidx,8);
  576. end;
  577. function tppufile.getaint:aint;
  578. begin
  579. {$ifdef cpu64bit}
  580. result:=getint64;
  581. {$else cpu64bit}
  582. result:=getlongint;
  583. {$endif cpu64bit}
  584. end;
  585. function tppufile.getreal:ppureal;
  586. var
  587. d : ppureal;
  588. begin
  589. if entryidx+sizeof(ppureal)>entry.size then
  590. begin
  591. error:=true;
  592. getreal:=0;
  593. exit;
  594. end;
  595. readdata(d,sizeof(ppureal));
  596. getreal:=d;
  597. inc(entryidx,sizeof(ppureal));
  598. end;
  599. function tppufile.getstring:string;
  600. var
  601. s : string;
  602. begin
  603. s[0]:=chr(getbyte);
  604. if entryidx+length(s)>entry.size then
  605. begin
  606. error:=true;
  607. exit;
  608. end;
  609. ReadData(s[1],length(s));
  610. getstring:=s;
  611. inc(entryidx,length(s));
  612. end;
  613. procedure tppufile.getsmallset(var b);
  614. var
  615. l : longint;
  616. begin
  617. l:=getlongint;
  618. longint(b):=l;
  619. end;
  620. procedure tppufile.getnormalset(var b);
  621. type
  622. SetLongintArray = Array [0..7] of longint;
  623. var
  624. i : longint;
  625. begin
  626. if change_endian then
  627. begin
  628. for i:=0 to 7 do
  629. SetLongintArray(b)[i]:=getlongint;
  630. end
  631. else
  632. getdata(b,32);
  633. end;
  634. function tppufile.skipuntilentry(untilb:byte):boolean;
  635. var
  636. b : byte;
  637. begin
  638. repeat
  639. b:=readentry;
  640. until (b in [ibend,iberror]) or ((b=untilb) and (entry.id=mainentryid));
  641. skipuntilentry:=(b=untilb);
  642. end;
  643. {*****************************************************************************
  644. TPPUFile Writing
  645. *****************************************************************************}
  646. function tppufile.createfile:boolean;
  647. begin
  648. createfile:=false;
  649. {$ifdef INTFPPU}
  650. if crc_only then
  651. begin
  652. fname:=fname+'.intf';
  653. crc_only:=false;
  654. end;
  655. {$endif}
  656. if not crc_only then
  657. begin
  658. assign(f,fname);
  659. {$I-}
  660. rewrite(f,1);
  661. {$I+}
  662. if ioresult<>0 then
  663. exit;
  664. Mode:=2;
  665. {write header for sure}
  666. blockwrite(f,header,sizeof(tppuheader));
  667. end;
  668. bufsize:=ppubufsize;
  669. bufstart:=sizeof(tppuheader);
  670. bufidx:=0;
  671. {reset}
  672. crc:=cardinal($ffffffff);
  673. interface_crc:=cardinal($ffffffff);
  674. do_interface_crc:=true;
  675. Error:=false;
  676. do_crc:=true;
  677. size:=0;
  678. entrytyp:=mainentryid;
  679. {start}
  680. NewEntry;
  681. createfile:=true;
  682. end;
  683. procedure tppufile.writeheader;
  684. var
  685. opos : integer;
  686. begin
  687. if crc_only then
  688. exit;
  689. { flush buffer }
  690. writebuf;
  691. { update size (w/o header!) in the header }
  692. header.size:=bufstart-sizeof(tppuheader);
  693. { set the endian flag }
  694. {$ifndef FPC_BIG_ENDIAN}
  695. header.flags := header.flags or uf_little_endian;
  696. {$else not FPC_BIG_ENDIAN}
  697. header.flags := header.flags or uf_big_endian;
  698. { Now swap the header in the correct endian (always little endian) }
  699. header.compiler := SwapWord(header.compiler);
  700. header.cpu := SwapWord(header.cpu);
  701. header.target := SwapWord(header.target);
  702. header.flags := SwapLong(header.flags);
  703. header.size := SwapLong(header.size);
  704. header.checksum := cardinal(SwapLong(longint(header.checksum)));
  705. header.interface_checksum := cardinal(SwapLong(longint(header.interface_checksum)));
  706. {$endif not FPC_BIG_ENDIAN}
  707. { write header and restore filepos after it }
  708. opos:=filepos(f);
  709. seek(f,0);
  710. blockwrite(f,header,sizeof(tppuheader));
  711. seek(f,opos);
  712. end;
  713. procedure tppufile.writebuf;
  714. begin
  715. if not crc_only then
  716. blockwrite(f,buf^,bufidx);
  717. inc(bufstart,bufidx);
  718. bufidx:=0;
  719. end;
  720. procedure tppufile.writedata(const b;len:integer);
  721. var
  722. p : pchar;
  723. left,
  724. idx : integer;
  725. begin
  726. if crc_only then
  727. exit;
  728. p:=pchar(@b);
  729. idx:=0;
  730. while len>0 do
  731. begin
  732. left:=bufsize-bufidx;
  733. if len>left then
  734. begin
  735. move(p[idx],buf[bufidx],left);
  736. dec(len,left);
  737. inc(idx,left);
  738. inc(bufidx,left);
  739. writebuf;
  740. end
  741. else
  742. begin
  743. move(p[idx],buf[bufidx],len);
  744. inc(bufidx,len);
  745. exit;
  746. end;
  747. end;
  748. end;
  749. procedure tppufile.NewEntry;
  750. begin
  751. with entry do
  752. begin
  753. id:=entrytyp;
  754. nr:=ibend;
  755. size:=0;
  756. end;
  757. {Reset Entry State}
  758. entryidx:=0;
  759. entrybufstart:=bufstart;
  760. entrystart:=bufstart+bufidx;
  761. {Alloc in buffer}
  762. writedata(entry,sizeof(tppuentry));
  763. end;
  764. procedure tppufile.writeentry(ibnr:byte);
  765. var
  766. opos : integer;
  767. begin
  768. {create entry}
  769. entry.id:=entrytyp;
  770. entry.nr:=ibnr;
  771. entry.size:=entryidx;
  772. {it's already been sent to disk ?}
  773. if entrybufstart<>bufstart then
  774. begin
  775. if not crc_only then
  776. begin
  777. {flush to be sure}
  778. WriteBuf;
  779. {write entry}
  780. opos:=filepos(f);
  781. seek(f,entrystart);
  782. blockwrite(f,entry,sizeof(tppuentry));
  783. seek(f,opos);
  784. end;
  785. entrybufstart:=bufstart;
  786. end
  787. else
  788. move(entry,buf[entrystart-bufstart],sizeof(entry));
  789. {Add New Entry, which is ibend by default}
  790. entrystart:=bufstart+bufidx; {next entry position}
  791. NewEntry;
  792. end;
  793. procedure tppufile.putdata(const b;len:integer);
  794. begin
  795. if do_crc then
  796. begin
  797. crc:=UpdateCrc32(crc,b,len);
  798. {$ifdef Test_Double_checksum}
  799. if crc_only then
  800. begin
  801. crc_test2^[crc_index2]:=crc;
  802. {$ifdef Test_Double_checksum_write}
  803. Writeln(CRCFile,crc);
  804. {$endif Test_Double_checksum_write}
  805. if crc_index2<crc_array_size then
  806. inc(crc_index2);
  807. end
  808. else
  809. begin
  810. if (crcindex2<crc_array_size) and (crcindex2<crc_index2) and
  811. (crc_test2^[crcindex2]<>crc) then
  812. Do_comment(V_Note,'impl CRC changed');
  813. {$ifdef Test_Double_checksum_write}
  814. Writeln(CRCFile,crc);
  815. {$endif Test_Double_checksum_write}
  816. inc(crcindex2);
  817. end;
  818. {$endif def Test_Double_checksum}
  819. if do_interface_crc then
  820. begin
  821. interface_crc:=UpdateCrc32(interface_crc,b,len);
  822. {$ifdef Test_Double_checksum}
  823. if crc_only then
  824. begin
  825. crc_test^[crc_index]:=interface_crc;
  826. {$ifdef Test_Double_checksum_write}
  827. Writeln(CRCFile,interface_crc);
  828. {$endif Test_Double_checksum_write}
  829. if crc_index<crc_array_size then
  830. inc(crc_index);
  831. end
  832. else
  833. begin
  834. if (crcindex<crc_array_size) and (crcindex<crc_index) and
  835. (crc_test^[crcindex]<>interface_crc) then
  836. Do_comment(V_Warning,'CRC changed');
  837. {$ifdef Test_Double_checksum_write}
  838. Writeln(CRCFile,interface_crc);
  839. {$endif Test_Double_checksum_write}
  840. inc(crcindex);
  841. end;
  842. {$endif def Test_Double_checksum}
  843. end;
  844. end;
  845. if not crc_only then
  846. writedata(b,len);
  847. inc(entryidx,len);
  848. end;
  849. procedure tppufile.putbyte(b:byte);
  850. begin
  851. putdata(b,1);
  852. end;
  853. procedure tppufile.putword(w:word);
  854. begin
  855. putdata(w,2);
  856. end;
  857. procedure tppufile.putlongint(l:longint);
  858. begin
  859. putdata(l,4);
  860. end;
  861. procedure tppufile.putint64(i:int64);
  862. begin
  863. putdata(i,8);
  864. end;
  865. procedure tppufile.putaint(i:aint);
  866. begin
  867. putdata(i,sizeof(aint));
  868. end;
  869. procedure tppufile.putreal(d:ppureal);
  870. begin
  871. putdata(d,sizeof(ppureal));
  872. end;
  873. procedure tppufile.putstring(s:string);
  874. begin
  875. putdata(s,length(s)+1);
  876. end;
  877. procedure tppufile.putsmallset(const b);
  878. var
  879. l : longint;
  880. begin
  881. l:=longint(b);
  882. putlongint(l);
  883. end;
  884. procedure tppufile.putnormalset(const b);
  885. type
  886. SetLongintArray = Array [0..7] of longint;
  887. var
  888. i : longint;
  889. tempb : setlongintarray;
  890. begin
  891. if change_endian then
  892. begin
  893. for i:=0 to 7 do
  894. tempb[i]:=SwapLong(SetLongintArray(b)[i]);
  895. putdata(tempb,32);
  896. end
  897. else
  898. putdata(b,32);
  899. end;
  900. procedure tppufile.tempclose;
  901. begin
  902. if not closed then
  903. begin
  904. closepos:=filepos(f);
  905. {$I-}
  906. system.close(f);
  907. {$I+}
  908. if ioresult<>0 then;
  909. closed:=true;
  910. tempclosed:=true;
  911. end;
  912. end;
  913. function tppufile.tempopen:boolean;
  914. var
  915. ofm : byte;
  916. begin
  917. tempopen:=false;
  918. if not closed or not tempclosed then
  919. exit;
  920. ofm:=filemode;
  921. filemode:=0;
  922. {$I-}
  923. reset(f,1);
  924. {$I+}
  925. filemode:=ofm;
  926. if ioresult<>0 then
  927. exit;
  928. closed:=false;
  929. tempclosed:=false;
  930. { restore state }
  931. seek(f,closepos);
  932. tempopen:=true;
  933. end;
  934. end.
  935. {
  936. $Log$
  937. Revision 1.48 2004-04-29 19:56:37 daniel
  938. * Prepare compiler infrastructure for multiple ansistring types
  939. Revision 1.47 2004/03/23 22:34:49 peter
  940. * constants ordinals now always have a type assigned
  941. * integer constants have the smallest type, unsigned prefered over
  942. signed
  943. Revision 1.46 2004/02/27 10:21:05 florian
  944. * top_symbol killed
  945. + refaddr to treference added
  946. + refsymbol to treference added
  947. * top_local stuff moved to an extra record to save memory
  948. + aint introduced
  949. * tppufile.get/putint64/aint implemented
  950. Revision 1.45 2004/01/30 13:42:03 florian
  951. * fixed more alignment issues
  952. Revision 1.44 2003/11/10 22:02:52 peter
  953. * cross unit inlining fixed
  954. Revision 1.43 2003/10/22 20:40:00 peter
  955. * write derefdata in a separate ppu entry
  956. Revision 1.42 2003/09/23 17:56:05 peter
  957. * locals and paras are allocated in the code generation
  958. * tvarsym.localloc contains the location of para/local when
  959. generating code for the current procedure
  960. Revision 1.41 2003/07/05 20:06:28 jonas
  961. * fixed some range check errors that occurred on big endian systems
  962. * slightly optimized the swap*() functions
  963. Revision 1.40 2003/06/17 16:34:44 jonas
  964. * lots of newra fixes (need getfuncretparaloc implementation for i386)!
  965. * renamed all_intregisters to volatile_intregisters and made it
  966. processor dependent
  967. Revision 1.39 2003/06/07 20:26:32 peter
  968. * re-resolving added instead of reloading from ppu
  969. * tderef object added to store deref info for resolving
  970. Revision 1.38 2003/05/26 19:39:51 peter
  971. * removed systems unit
  972. Revision 1.37 2003/05/26 15:49:54 jonas
  973. * endian fix is now done using a define instead of with source_info
  974. Revision 1.36 2003/05/24 13:37:10 jonas
  975. * endian fixes
  976. Revision 1.35 2003/05/23 17:03:51 peter
  977. * write header for crc_only
  978. Revision 1.34 2003/04/25 20:59:34 peter
  979. * removed funcretn,funcretsym, function result is now in varsym
  980. and aliases for result and function name are added using absolutesym
  981. * vs_hidden parameter for funcret passed in parameter
  982. * vs_hidden fixes
  983. * writenode changed to printnode and released from extdebug
  984. * -vp option added to generate a tree.log with the nodetree
  985. * nicer printnode for statements, callnode
  986. Revision 1.33 2003/04/24 13:03:01 florian
  987. * comp is now written with its bit pattern to the ppu instead as an extended
  988. Revision 1.32 2003/04/23 14:42:07 daniel
  989. * Further register allocator work. Compiler now smaller with new
  990. allocator than without.
  991. * Somebody forgot to adjust ppu version number
  992. Revision 1.31 2003/04/10 17:57:53 peter
  993. * vs_hidden released
  994. Revision 1.30 2003/03/17 15:54:22 peter
  995. * store symoptions also for procdef
  996. * check symoptions (private,public) when calculating possible
  997. overload candidates
  998. Revision 1.29 2003/01/08 18:43:56 daniel
  999. * Tregister changed into a record
  1000. Revision 1.28 2002/11/15 01:58:53 peter
  1001. * merged changes from 1.0.7 up to 04-11
  1002. - -V option for generating bug report tracing
  1003. - more tracing for option parsing
  1004. - errors for cdecl and high()
  1005. - win32 import stabs
  1006. - win32 records<=8 are returned in eax:edx (turned off by default)
  1007. - heaptrc update
  1008. - more info for temp management in .s file with EXTDEBUG
  1009. Revision 1.27 2002/10/14 19:42:33 peter
  1010. * only use init tables for threadvars
  1011. Revision 1.26 2002/08/18 20:06:25 peter
  1012. * inlining is now also allowed in interface
  1013. * renamed write/load to ppuwrite/ppuload
  1014. * tnode storing in ppu
  1015. * nld,ncon,nbas are already updated for storing in ppu
  1016. Revision 1.25 2002/08/15 19:10:35 peter
  1017. * first things tai,tnode storing in ppu
  1018. Revision 1.24 2002/08/15 15:09:42 carl
  1019. + fpu emulation helpers (ppu checking also)
  1020. Revision 1.23 2002/08/13 21:40:56 florian
  1021. * more fixes for ppc calling conventions
  1022. Revision 1.22 2002/08/11 13:24:12 peter
  1023. * saving of asmsymbols in ppu supported
  1024. * asmsymbollist global is removed and moved into a new class
  1025. tasmlibrarydata that will hold the info of a .a file which
  1026. corresponds with a single module. Added librarydata to tmodule
  1027. to keep the library info stored for the module. In the future the
  1028. objectfiles will also be stored to the tasmlibrarydata class
  1029. * all getlabel/newasmsymbol and friends are moved to the new class
  1030. Revision 1.21 2002/08/09 07:33:02 florian
  1031. * a couple of interface related fixes
  1032. Revision 1.20 2002/05/18 13:34:13 peter
  1033. * readded missing revisions
  1034. Revision 1.19 2002/05/16 19:46:44 carl
  1035. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1036. + try to fix temp allocation (still in ifdef)
  1037. + generic constructor calls
  1038. + start of tassembler / tmodulebase class cleanup
  1039. Revision 1.17 2002/04/04 19:06:03 peter
  1040. * removed unused units
  1041. * use tlocation.size in cg.a_*loc*() routines
  1042. Revision 1.16 2002/03/31 20:26:36 jonas
  1043. + a_loadfpu_* and a_loadmm_* methods in tcg
  1044. * register allocation is now handled by a class and is mostly processor
  1045. independent (+rgobj.pas and i386/rgcpu.pas)
  1046. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1047. * some small improvements and fixes to the optimizer
  1048. * some register allocation fixes
  1049. * some fpuvaroffset fixes in the unary minus node
  1050. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1051. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1052. also better optimizable)
  1053. * fixed and optimized register saving/restoring for new/dispose nodes
  1054. * LOC_FPU locations now also require their "register" field to be set to
  1055. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1056. - list field removed of the tnode class because it's not used currently
  1057. and can cause hard-to-find bugs
  1058. Revision 1.15 2002/03/28 16:07:52 armin
  1059. + initialize threadvars defined local in units
  1060. }