ppu.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017
  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. { Also write the ppu if only crc if done, this can be used with ppudump to
  22. see the differences between the intf and implementation }
  23. { define INTFPPU}
  24. {$ifdef Test_Double_checksum}
  25. var
  26. CRCFile : text;
  27. const
  28. CRC_array_Size = 200000;
  29. type
  30. tcrc_array = array[0..crc_array_size] of longint;
  31. pcrc_array = ^tcrc_array;
  32. {$endif Test_Double_checksum}
  33. const
  34. CurrentPPUVersion=27;
  35. { buffer sizes }
  36. maxentrysize = 1024;
  37. ppubufsize = 16384;
  38. {ppu entries}
  39. mainentryid = 1;
  40. subentryid = 2;
  41. {special}
  42. iberror = 0;
  43. ibstartdefs = 248;
  44. ibenddefs = 249;
  45. ibstartsyms = 250;
  46. ibendsyms = 251;
  47. ibendinterface = 252;
  48. ibendimplementation = 253;
  49. ibendbrowser = 254;
  50. ibend = 255;
  51. {general}
  52. ibmodulename = 1;
  53. ibsourcefiles = 2;
  54. ibloadunit = 3;
  55. ibinitunit = 4;
  56. iblinkunitofiles = 5;
  57. iblinkunitstaticlibs = 6;
  58. iblinkunitsharedlibs = 7;
  59. iblinkotherofiles = 8;
  60. iblinkotherstaticlibs = 9;
  61. iblinkothersharedlibs = 10;
  62. ibdbxcount = 11;
  63. ibsymref = 12;
  64. ibdefref = 13;
  65. ibendsymtablebrowser = 14;
  66. ibbeginsymtablebrowser = 15;
  67. ibusedmacros = 16;
  68. {syms}
  69. ibtypesym = 20;
  70. ibprocsym = 21;
  71. ibvarsym = 22;
  72. ibconstsym = 23;
  73. ibenumsym = 24;
  74. ibtypedconstsym = 25;
  75. ibabsolutesym = 26;
  76. ibpropertysym = 27;
  77. ibvarsym_C = 28;
  78. ibunitsym = 29; { needed for browser }
  79. iblabelsym = 30;
  80. ibfuncretsym = 31;
  81. ibsyssym = 32;
  82. ibrttisym = 33;
  83. {definitions}
  84. iborddef = 40;
  85. ibpointerdef = 41;
  86. ibarraydef = 42;
  87. ibprocdef = 43;
  88. ibshortstringdef = 44;
  89. ibrecorddef = 45;
  90. ibfiledef = 46;
  91. ibformaldef = 47;
  92. ibobjectdef = 48;
  93. ibenumdef = 49;
  94. ibsetdef = 50;
  95. ibprocvardef = 51;
  96. ibfloatdef = 52;
  97. ibclassrefdef = 53;
  98. iblongstringdef = 54;
  99. ibansistringdef = 55;
  100. ibwidestringdef = 56;
  101. ibvariantdef = 57;
  102. { unit flags }
  103. uf_init = $1;
  104. uf_finalize = $2;
  105. uf_big_endian = $4;
  106. uf_has_dbx = $8;
  107. uf_has_browser = $10;
  108. uf_in_library = $20; { is the file in another file than <ppufile>.* ? }
  109. uf_smart_linked = $40; { the ppu can be smartlinked }
  110. uf_static_linked = $80; { the ppu can be linked static }
  111. uf_shared_linked = $100; { the ppu can be linked shared }
  112. uf_local_browser = $200;
  113. uf_no_link = $400; { unit has no .o generated, but can still have
  114. external linking! }
  115. uf_has_resources = $800; { unit has resource section }
  116. uf_little_endian = $1000;
  117. uf_release = $2000;{ unit was compiled with -Ur option }
  118. uf_local_threadvars = $4000; { unit has local threadvars }
  119. type
  120. ppureal=extended;
  121. tppuerror=(ppuentrytoobig,ppuentryerror);
  122. tppuheader=packed record { 36 bytes }
  123. id : array[1..3] of char; { = 'PPU' }
  124. ver : array[1..3] of char;
  125. compiler : word;
  126. cpu : word;
  127. target : word;
  128. flags : longint;
  129. size : longint; { size of the ppufile without header }
  130. checksum : cardinal; { checksum for this ppufile }
  131. interface_checksum : cardinal;
  132. future : array[0..2] of longint;
  133. end;
  134. tppuentry=packed record
  135. id : byte;
  136. nr : byte;
  137. size : longint;
  138. end;
  139. tppufile=class
  140. private
  141. f : file;
  142. mode : byte; {0 - Closed, 1 - Reading, 2 - Writing}
  143. fname : string;
  144. fsize : integer;
  145. {$ifdef Test_Double_checksum}
  146. crcindex,
  147. crc_index,
  148. crcindex2,
  149. crc_index2 : cardinal;
  150. crc_test,
  151. crc_test2 : pcrc_array;
  152. {$endif def Test_Double_checksum}
  153. change_endian : boolean;
  154. buf : pchar;
  155. bufstart,
  156. bufsize,
  157. bufidx : integer;
  158. entrybufstart,
  159. entrystart,
  160. entryidx : integer;
  161. entry : tppuentry;
  162. closed,
  163. tempclosed : boolean;
  164. closepos : integer;
  165. public
  166. entrytyp : byte;
  167. header : tppuheader;
  168. size : integer;
  169. crc,
  170. interface_crc : cardinal;
  171. error,
  172. do_crc,
  173. do_interface_crc : boolean;
  174. crc_only : boolean; { used to calculate interface_crc before implementation }
  175. constructor Create(const fn:string);
  176. destructor Destroy;override;
  177. procedure flush;
  178. procedure closefile;
  179. function CheckPPUId:boolean;
  180. function GetPPUVersion:integer;
  181. procedure NewHeader;
  182. procedure NewEntry;
  183. {read}
  184. function openfile:boolean;
  185. procedure reloadbuf;
  186. procedure readdata(var b;len:integer);
  187. procedure skipdata(len:integer);
  188. function readentry:byte;
  189. function EndOfEntry:boolean;
  190. procedure getdatabuf(var b;len:integer;var res:integer);
  191. procedure getdata(var b;len:integer);
  192. function getbyte:byte;
  193. function getword:word;
  194. function getlongint:longint;
  195. function getreal:ppureal;
  196. function getstring:string;
  197. procedure getnormalset(var b);
  198. procedure getsmallset(var b);
  199. function skipuntilentry(untilb:byte):boolean;
  200. {write}
  201. function createfile:boolean;
  202. procedure writeheader;
  203. procedure writebuf;
  204. procedure writedata(const b;len:integer);
  205. procedure writeentry(ibnr:byte);
  206. procedure putdata(const b;len:integer);
  207. procedure putbyte(b:byte);
  208. procedure putword(w:word);
  209. procedure putlongint(l:longint);
  210. procedure putreal(d:ppureal);
  211. procedure putstring(s:string);
  212. procedure putnormalset(const b);
  213. procedure putsmallset(const b);
  214. procedure tempclose;
  215. function tempopen:boolean;
  216. end;
  217. implementation
  218. uses
  219. {$ifdef Test_Double_checksum}
  220. comphook,
  221. {$endif def Test_Double_checksum}
  222. crc;
  223. {*****************************************************************************
  224. Endian Handling
  225. *****************************************************************************}
  226. Function SwapLong(x : longint): longint;
  227. var
  228. y : word;
  229. z : word;
  230. Begin
  231. y := (x shr 16) and $FFFF;
  232. y := (y shl 8) or ((y shr 8) and $ff);
  233. z := x and $FFFF;
  234. z := (z shl 8) or ((z shr 8) and $ff);
  235. SwapLong := (longint(z) shl 16) or longint(y);
  236. End;
  237. Function SwapWord(x : word): word;
  238. var
  239. z : byte;
  240. Begin
  241. z := (x shr 8) and $ff;
  242. x := x and $ff;
  243. x := (x shl 8);
  244. SwapWord := x or z;
  245. End;
  246. {*****************************************************************************
  247. TPPUFile
  248. *****************************************************************************}
  249. constructor tppufile.Create(const fn:string);
  250. begin
  251. fname:=fn;
  252. change_endian:=false;
  253. crc_only:=false;
  254. Mode:=0;
  255. NewHeader;
  256. Error:=false;
  257. closed:=true;
  258. tempclosed:=false;
  259. getmem(buf,ppubufsize);
  260. end;
  261. destructor tppufile.destroy;
  262. begin
  263. closefile;
  264. if assigned(buf) then
  265. freemem(buf,ppubufsize);
  266. end;
  267. procedure tppufile.flush;
  268. begin
  269. if Mode=2 then
  270. writebuf;
  271. end;
  272. procedure tppufile.closefile;
  273. begin
  274. {$ifdef Test_Double_checksum}
  275. if mode=2 then
  276. begin
  277. if assigned(crc_test) then
  278. dispose(crc_test);
  279. if assigned(crc_test2) then
  280. dispose(crc_test2);
  281. end;
  282. {$endif Test_Double_checksum}
  283. if Mode<>0 then
  284. begin
  285. Flush;
  286. {$I-}
  287. system.close(f);
  288. {$I+}
  289. if ioresult<>0 then;
  290. Mode:=0;
  291. closed:=true;
  292. end;
  293. end;
  294. function tppufile.CheckPPUId:boolean;
  295. begin
  296. CheckPPUId:=((Header.Id[1]='P') and (Header.Id[2]='P') and (Header.Id[3]='U'));
  297. end;
  298. function tppufile.GetPPUVersion:integer;
  299. var
  300. l : integer;
  301. code : integer;
  302. begin
  303. Val(header.ver[1]+header.ver[2]+header.ver[3],l,code);
  304. if code=0 then
  305. GetPPUVersion:=l
  306. else
  307. GetPPUVersion:=0;
  308. end;
  309. procedure tppufile.NewHeader;
  310. var
  311. s : string;
  312. begin
  313. fillchar(header,sizeof(tppuheader),0);
  314. str(currentppuversion,s);
  315. while length(s)<3 do
  316. s:='0'+s;
  317. with header do
  318. begin
  319. Id[1]:='P';
  320. Id[2]:='P';
  321. Id[3]:='U';
  322. Ver[1]:=s[1];
  323. Ver[2]:=s[2];
  324. Ver[3]:=s[3];
  325. end;
  326. end;
  327. {*****************************************************************************
  328. TPPUFile Reading
  329. *****************************************************************************}
  330. function tppufile.openfile:boolean;
  331. var
  332. ofmode : byte;
  333. i : integer;
  334. begin
  335. openfile:=false;
  336. assign(f,fname);
  337. ofmode:=filemode;
  338. filemode:=$0;
  339. {$I-}
  340. reset(f,1);
  341. {$I+}
  342. filemode:=ofmode;
  343. if ioresult<>0 then
  344. exit;
  345. closed:=false;
  346. {read ppuheader}
  347. fsize:=filesize(f);
  348. if fsize<sizeof(tppuheader) then
  349. exit;
  350. blockread(f,header,sizeof(tppuheader),i);
  351. { The header is always stored in little endian order }
  352. { therefore swap if on a big endian machine }
  353. {$IFDEF ENDIAN_BIG}
  354. header.compiler := SwapWord(header.compiler);
  355. header.cpu := SwapWord(header.cpu);
  356. header.target := SwapWord(header.target);
  357. header.flags := SwapLong(header.flags);
  358. header.size := SwapLong(header.size);
  359. header.checksum := SwapLong(header.checksum);
  360. header.interface_checksum := SwapLong(header.interface_checksum);
  361. {$ENDIF}
  362. { the PPU DATA is stored in native order }
  363. if (header.flags and uf_big_endian) = uf_big_endian then
  364. Begin
  365. {$IFDEF ENDIAN_LITTLE}
  366. change_endian := TRUE;
  367. {$ELSE}
  368. change_endian := FALSE;
  369. {$ENDIF}
  370. End
  371. else if (header.flags and uf_little_endian) = uf_little_endian then
  372. Begin
  373. {$IFDEF ENDIAN_BIG}
  374. change_endian := TRUE;
  375. {$ELSE}
  376. change_endian := FALSE;
  377. {$ENDIF}
  378. End;
  379. {reset buffer}
  380. bufstart:=i;
  381. bufsize:=0;
  382. bufidx:=0;
  383. Mode:=1;
  384. FillChar(entry,sizeof(tppuentry),0);
  385. entryidx:=0;
  386. entrystart:=0;
  387. entrybufstart:=0;
  388. Error:=false;
  389. openfile:=true;
  390. end;
  391. procedure tppufile.reloadbuf;
  392. begin
  393. inc(bufstart,bufsize);
  394. blockread(f,buf^,ppubufsize,bufsize);
  395. bufidx:=0;
  396. end;
  397. procedure tppufile.readdata(var b;len:integer);
  398. var
  399. p : pchar;
  400. left,
  401. idx : integer;
  402. begin
  403. p:=pchar(@b);
  404. idx:=0;
  405. while len>0 do
  406. begin
  407. left:=bufsize-bufidx;
  408. if len>left then
  409. begin
  410. move(buf[bufidx],p[idx],left);
  411. dec(len,left);
  412. inc(idx,left);
  413. reloadbuf;
  414. if bufsize=0 then
  415. exit;
  416. end
  417. else
  418. begin
  419. move(buf[bufidx],p[idx],len);
  420. inc(bufidx,len);
  421. exit;
  422. end;
  423. end;
  424. end;
  425. procedure tppufile.skipdata(len:integer);
  426. var
  427. left : integer;
  428. begin
  429. while len>0 do
  430. begin
  431. left:=bufsize-bufidx;
  432. if len>left then
  433. begin
  434. dec(len,left);
  435. reloadbuf;
  436. if bufsize=0 then
  437. exit;
  438. end
  439. else
  440. begin
  441. inc(bufidx,len);
  442. exit;
  443. end;
  444. end;
  445. end;
  446. function tppufile.readentry:byte;
  447. begin
  448. if entryidx<entry.size then
  449. skipdata(entry.size-entryidx);
  450. readdata(entry,sizeof(tppuentry));
  451. entrystart:=bufstart+bufidx;
  452. entryidx:=0;
  453. if not(entry.id in [mainentryid,subentryid]) then
  454. begin
  455. readentry:=iberror;
  456. error:=true;
  457. exit;
  458. end;
  459. readentry:=entry.nr;
  460. end;
  461. function tppufile.endofentry:boolean;
  462. begin
  463. endofentry:=(entryidx>=entry.size);
  464. end;
  465. procedure tppufile.getdatabuf(var b;len:integer;var res:integer);
  466. begin
  467. if entryidx+len>entry.size then
  468. res:=entry.size-entryidx
  469. else
  470. res:=len;
  471. readdata(b,res);
  472. inc(entryidx,res);
  473. end;
  474. procedure tppufile.getdata(var b;len:integer);
  475. begin
  476. if entryidx+len>entry.size then
  477. begin
  478. error:=true;
  479. exit;
  480. end;
  481. readdata(b,len);
  482. inc(entryidx,len);
  483. end;
  484. function tppufile.getbyte:byte;
  485. var
  486. b : byte;
  487. begin
  488. if entryidx+1>entry.size then
  489. begin
  490. error:=true;
  491. getbyte:=0;
  492. exit;
  493. end;
  494. readdata(b,1);
  495. getbyte:=b;
  496. inc(entryidx);
  497. end;
  498. function tppufile.getword:word;
  499. var
  500. w : word;
  501. begin
  502. if entryidx+2>entry.size then
  503. begin
  504. error:=true;
  505. getword:=0;
  506. exit;
  507. end;
  508. readdata(w,2);
  509. if change_endian then
  510. getword:=swapword(w)
  511. else
  512. getword:=w;
  513. inc(entryidx,2);
  514. end;
  515. function tppufile.getlongint:longint;
  516. var
  517. l : longint;
  518. begin
  519. if entryidx+4>entry.size then
  520. begin
  521. error:=true;
  522. getlongint:=0;
  523. exit;
  524. end;
  525. readdata(l,4);
  526. if change_endian then
  527. getlongint:=swaplong(l)
  528. else
  529. getlongint:=l;
  530. inc(entryidx,4);
  531. end;
  532. function tppufile.getreal:ppureal;
  533. var
  534. d : ppureal;
  535. begin
  536. if entryidx+sizeof(ppureal)>entry.size then
  537. begin
  538. error:=true;
  539. getreal:=0;
  540. exit;
  541. end;
  542. readdata(d,sizeof(ppureal));
  543. getreal:=d;
  544. inc(entryidx,sizeof(ppureal));
  545. end;
  546. function tppufile.getstring:string;
  547. var
  548. s : string;
  549. begin
  550. s[0]:=chr(getbyte);
  551. if entryidx+length(s)>entry.size then
  552. begin
  553. error:=true;
  554. exit;
  555. end;
  556. ReadData(s[1],length(s));
  557. getstring:=s;
  558. inc(entryidx,length(s));
  559. end;
  560. procedure tppufile.getsmallset(var b);
  561. var
  562. l : longint;
  563. begin
  564. l:=getlongint;
  565. longint(b):=l;
  566. end;
  567. procedure tppufile.getnormalset(var b);
  568. type
  569. SetLongintArray = Array [0..7] of longint;
  570. var
  571. i : longint;
  572. begin
  573. if change_endian then
  574. begin
  575. for i:=0 to 7 do
  576. SetLongintArray(b)[i]:=getlongint;
  577. end
  578. else
  579. getdata(b,32);
  580. end;
  581. function tppufile.skipuntilentry(untilb:byte):boolean;
  582. var
  583. b : byte;
  584. begin
  585. repeat
  586. b:=readentry;
  587. until (b in [ibend,iberror]) or ((b=untilb) and (entry.id=mainentryid));
  588. skipuntilentry:=(b=untilb);
  589. end;
  590. {*****************************************************************************
  591. TPPUFile Writing
  592. *****************************************************************************}
  593. function tppufile.createfile:boolean;
  594. begin
  595. createfile:=false;
  596. {$ifdef INTFPPU}
  597. if crc_only then
  598. begin
  599. fname:=fname+'.intf';
  600. crc_only:=false;
  601. end;
  602. {$endif}
  603. if not crc_only then
  604. begin
  605. assign(f,fname);
  606. {$I-}
  607. rewrite(f,1);
  608. {$I+}
  609. if ioresult<>0 then
  610. exit;
  611. Mode:=2;
  612. {write header for sure}
  613. blockwrite(f,header,sizeof(tppuheader));
  614. end;
  615. bufsize:=ppubufsize;
  616. bufstart:=sizeof(tppuheader);
  617. bufidx:=0;
  618. {reset}
  619. crc:=cardinal($ffffffff);
  620. interface_crc:=cardinal($ffffffff);
  621. do_interface_crc:=true;
  622. Error:=false;
  623. do_crc:=true;
  624. size:=0;
  625. entrytyp:=mainentryid;
  626. {start}
  627. NewEntry;
  628. createfile:=true;
  629. end;
  630. procedure tppufile.writeheader;
  631. var
  632. opos : integer;
  633. begin
  634. { flush buffer }
  635. writebuf;
  636. { update size (w/o header!) in the header }
  637. header.size:=bufstart-sizeof(tppuheader);
  638. { set the endian flag }
  639. {$IFDEF SOURCE_BIG_ENDIAN}
  640. header.flags := header.flags or uf_big_endian;
  641. {$ENDIF}
  642. {$IFDEF SOURCE_LITTLE_ENDIAN}
  643. header.flags := header.flags or uf_little_endian;
  644. {$ENDIF}
  645. { Now swap the header in the correct endian (always little endian) }
  646. {$IFDEF SOURCE_BIG_ENDIAN}
  647. header.compiler := SwapWord(header.compiler);
  648. header.cpu := SwapWord(header.cpu);
  649. header.target := SwapWord(header.target);
  650. header.flags := SwapLong(header.flags);
  651. header.size := SwapLong(header.size);
  652. header.checksum := SwapLong(header.checksum);
  653. header.interface_checksum := SwapLong(header.interface_checksum);
  654. {$ENDIF}
  655. { write header and restore filepos after it }
  656. opos:=filepos(f);
  657. seek(f,0);
  658. blockwrite(f,header,sizeof(tppuheader));
  659. seek(f,opos);
  660. end;
  661. procedure tppufile.writebuf;
  662. begin
  663. if not crc_only then
  664. blockwrite(f,buf^,bufidx);
  665. inc(bufstart,bufidx);
  666. bufidx:=0;
  667. end;
  668. procedure tppufile.writedata(const b;len:integer);
  669. var
  670. p : pchar;
  671. left,
  672. idx : integer;
  673. begin
  674. if crc_only then
  675. exit;
  676. p:=pchar(@b);
  677. idx:=0;
  678. while len>0 do
  679. begin
  680. left:=bufsize-bufidx;
  681. if len>left then
  682. begin
  683. move(p[idx],buf[bufidx],left);
  684. dec(len,left);
  685. inc(idx,left);
  686. inc(bufidx,left);
  687. writebuf;
  688. end
  689. else
  690. begin
  691. move(p[idx],buf[bufidx],len);
  692. inc(bufidx,len);
  693. exit;
  694. end;
  695. end;
  696. end;
  697. procedure tppufile.NewEntry;
  698. begin
  699. with entry do
  700. begin
  701. id:=entrytyp;
  702. nr:=ibend;
  703. size:=0;
  704. end;
  705. {Reset Entry State}
  706. entryidx:=0;
  707. entrybufstart:=bufstart;
  708. entrystart:=bufstart+bufidx;
  709. {Alloc in buffer}
  710. writedata(entry,sizeof(tppuentry));
  711. end;
  712. procedure tppufile.writeentry(ibnr:byte);
  713. var
  714. opos : integer;
  715. begin
  716. {create entry}
  717. entry.id:=entrytyp;
  718. entry.nr:=ibnr;
  719. entry.size:=entryidx;
  720. {it's already been sent to disk ?}
  721. if entrybufstart<>bufstart then
  722. begin
  723. if not crc_only then
  724. begin
  725. {flush to be sure}
  726. WriteBuf;
  727. {write entry}
  728. opos:=filepos(f);
  729. seek(f,entrystart);
  730. blockwrite(f,entry,sizeof(tppuentry));
  731. seek(f,opos);
  732. end;
  733. entrybufstart:=bufstart;
  734. end
  735. else
  736. move(entry,buf[entrystart-bufstart],sizeof(entry));
  737. {Add New Entry, which is ibend by default}
  738. entrystart:=bufstart+bufidx; {next entry position}
  739. NewEntry;
  740. end;
  741. procedure tppufile.putdata(const b;len:integer);
  742. begin
  743. if do_crc then
  744. begin
  745. crc:=UpdateCrc32(crc,b,len);
  746. {$ifdef Test_Double_checksum}
  747. if crc_only then
  748. begin
  749. crc_test2^[crc_index2]:=crc;
  750. {$ifdef Test_Double_checksum_write}
  751. Writeln(CRCFile,crc);
  752. {$endif Test_Double_checksum_write}
  753. if crc_index2<crc_array_size then
  754. inc(crc_index2);
  755. end
  756. else
  757. begin
  758. if (crcindex2<crc_array_size) and (crcindex2<crc_index2) and
  759. (crc_test2^[crcindex2]<>crc) then
  760. Do_comment(V_Warning,'impl CRC changed');
  761. {$ifdef Test_Double_checksum_write}
  762. Writeln(CRCFile,crc);
  763. {$endif Test_Double_checksum_write}
  764. inc(crcindex2);
  765. end;
  766. {$endif def Test_Double_checksum}
  767. if do_interface_crc then
  768. begin
  769. interface_crc:=UpdateCrc32(interface_crc,b,len);
  770. {$ifdef Test_Double_checksum}
  771. if crc_only then
  772. begin
  773. crc_test^[crc_index]:=interface_crc;
  774. {$ifdef Test_Double_checksum_write}
  775. Writeln(CRCFile,interface_crc);
  776. {$endif Test_Double_checksum_write}
  777. if crc_index<crc_array_size then
  778. inc(crc_index);
  779. end
  780. else
  781. begin
  782. if (crcindex<crc_array_size) and (crcindex<crc_index) and
  783. (crc_test^[crcindex]<>interface_crc) then
  784. Do_comment(V_Warning,'CRC changed');
  785. {$ifdef Test_Double_checksum_write}
  786. Writeln(CRCFile,interface_crc);
  787. {$endif Test_Double_checksum_write}
  788. inc(crcindex);
  789. end;
  790. {$endif def Test_Double_checksum}
  791. end;
  792. end;
  793. if not crc_only then
  794. writedata(b,len);
  795. inc(entryidx,len);
  796. end;
  797. procedure tppufile.putbyte(b:byte);
  798. begin
  799. putdata(b,1);
  800. end;
  801. procedure tppufile.putword(w:word);
  802. begin
  803. putdata(w,2);
  804. end;
  805. procedure tppufile.putlongint(l:longint);
  806. begin
  807. putdata(l,4);
  808. end;
  809. procedure tppufile.putreal(d:ppureal);
  810. begin
  811. putdata(d,sizeof(ppureal));
  812. end;
  813. procedure tppufile.putstring(s:string);
  814. begin
  815. putdata(s,length(s)+1);
  816. end;
  817. procedure tppufile.putsmallset(const b);
  818. var
  819. l : longint;
  820. begin
  821. l:=longint(b);
  822. putlongint(l);
  823. end;
  824. procedure tppufile.putnormalset(const b);
  825. type
  826. SetLongintArray = Array [0..7] of longint;
  827. var
  828. i : longint;
  829. tempb : setlongintarray;
  830. begin
  831. if change_endian then
  832. begin
  833. for i:=0 to 7 do
  834. tempb[i]:=SwapLong(SetLongintArray(b)[i]);
  835. putdata(tempb,32);
  836. end
  837. else
  838. putdata(b,32);
  839. end;
  840. procedure tppufile.tempclose;
  841. begin
  842. if not closed then
  843. begin
  844. closepos:=filepos(f);
  845. {$I-}
  846. system.close(f);
  847. {$I+}
  848. if ioresult<>0 then;
  849. closed:=true;
  850. tempclosed:=true;
  851. end;
  852. end;
  853. function tppufile.tempopen:boolean;
  854. var
  855. ofm : byte;
  856. begin
  857. tempopen:=false;
  858. if not closed or not tempclosed then
  859. exit;
  860. ofm:=filemode;
  861. filemode:=0;
  862. {$I-}
  863. reset(f,1);
  864. {$I+}
  865. filemode:=ofm;
  866. if ioresult<>0 then
  867. exit;
  868. closed:=false;
  869. tempclosed:=false;
  870. { restore state }
  871. seek(f,closepos);
  872. tempopen:=true;
  873. end;
  874. end.
  875. {
  876. $Log$
  877. Revision 1.20 2002-05-18 13:34:13 peter
  878. * readded missing revisions
  879. Revision 1.19 2002/05/16 19:46:44 carl
  880. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  881. + try to fix temp allocation (still in ifdef)
  882. + generic constructor calls
  883. + start of tassembler / tmodulebase class cleanup
  884. Revision 1.17 2002/04/04 19:06:03 peter
  885. * removed unused units
  886. * use tlocation.size in cg.a_*loc*() routines
  887. Revision 1.16 2002/03/31 20:26:36 jonas
  888. + a_loadfpu_* and a_loadmm_* methods in tcg
  889. * register allocation is now handled by a class and is mostly processor
  890. independent (+rgobj.pas and i386/rgcpu.pas)
  891. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  892. * some small improvements and fixes to the optimizer
  893. * some register allocation fixes
  894. * some fpuvaroffset fixes in the unary minus node
  895. * push/popusedregisters is now called rg.save/restoreusedregisters and
  896. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  897. also better optimizable)
  898. * fixed and optimized register saving/restoring for new/dispose nodes
  899. * LOC_FPU locations now also require their "register" field to be set to
  900. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  901. - list field removed of the tnode class because it's not used currently
  902. and can cause hard-to-find bugs
  903. Revision 1.15 2002/03/28 16:07:52 armin
  904. + initialize threadvars defined local in units
  905. }