ppu.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 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. {$ifdef TP}
  19. {$N+,E+}
  20. {$endif}
  21. unit ppu;
  22. interface
  23. const
  24. { buffer sizes }
  25. maxentrysize = 1024;
  26. {$ifdef TP}
  27. ppubufsize = 1024;
  28. {$else}
  29. ppubufsize = 16384;
  30. {$endif}
  31. {ppu entries}
  32. {special}
  33. iberror = 0;
  34. ibenddefs = 250;
  35. ibendsyms = 251;
  36. ibendinterface = 252;
  37. ibendimplementation = 253;
  38. ibentry = 254;
  39. ibend = 255;
  40. {general}
  41. ibmodulename = 1;
  42. ibsourcefiles = 2;
  43. ibloadunit_int = 3;
  44. ibloadunit_imp = 4;
  45. ibinitunit = 5;
  46. iblinkofiles = 6;
  47. iblinksharedlibs = 7;
  48. iblinkstaticlibs = 8;
  49. ibdbxcount = 9;
  50. ibref = 10;
  51. {syms}
  52. ibtypesym = 20;
  53. ibprocsym = 21;
  54. ibvarsym = 22;
  55. ibconstsym = 23;
  56. ibenumsym = 24;
  57. ibtypedconstsym = 25;
  58. ibabsolutesym = 26;
  59. ibpropertysym = 27;
  60. {defenitions}
  61. iborddef = 40;
  62. ibpointerdef = 41;
  63. ibarraydef = 42;
  64. ibprocdef = 43;
  65. ibstringdef = 44;
  66. ibrecorddef = 45;
  67. ibfiledef = 46;
  68. ibformaldef = 47;
  69. ibobjectdef = 48;
  70. ibenumdef = 49;
  71. ibsetdef = 50;
  72. ibprocvardef = 51;
  73. ibfloatdef = 52;
  74. ibextsymref = 53;
  75. ibextdefref = 54;
  76. ibclassrefdef = 55;
  77. iblongstringdef = 56;
  78. ibansistringdef = 57;
  79. ibwidestringdef = 58;
  80. { unit flags }
  81. uf_init = $1;
  82. uf_uses_dbx = $2;
  83. uf_uses_browser = $4;
  84. uf_big_endian = $8;
  85. uf_in_library = $10;
  86. uf_shared_library = $20;
  87. uf_smartlink = $40;
  88. type
  89. tppuerror=(ppuentrytoobig,ppuentryerror);
  90. tppuheader=packed record
  91. id : array[1..3] of char; { = 'PPU' }
  92. ver : array[1..3] of char;
  93. compiler : word;
  94. target : word;
  95. flags : longint;
  96. size : longint; { size of the ppufile without header }
  97. checksum : longint; { checksum for this ppufile }
  98. end;
  99. tppuentry=packed record
  100. id : byte;
  101. nr : byte;
  102. size : word;
  103. end;
  104. pppufile=^tppufile;
  105. tppufile=object
  106. f : file;
  107. mode : byte; {0 - Closed, 1 - Reading, 2 - Writing}
  108. error : boolean;
  109. fname : string;
  110. fsize : longint;
  111. header : tppuheader;
  112. size,crc : longint;
  113. do_crc,
  114. change_endian : boolean;
  115. buf : pchar;
  116. bufstart,
  117. bufsize,
  118. bufidx : longint;
  119. entry : tppuentry;
  120. entrybufstart,
  121. entrystart,
  122. entryidx : longint;
  123. constructor init(fn:string);
  124. destructor done;
  125. procedure flush;
  126. procedure close;
  127. function CheckPPUId:boolean;
  128. function GetPPUVersion:longint;
  129. procedure NewHeader;
  130. procedure NewEntry;
  131. {read}
  132. function open:boolean;
  133. procedure reloadbuf;
  134. procedure readdata(var b;len:longint);
  135. procedure skipdata(len:longint);
  136. function readentry:byte;
  137. function EndOfEntry:boolean;
  138. procedure getdata(var b;len:longint);
  139. function getbyte:byte;
  140. function getword:word;
  141. function getlongint:longint;
  142. function getdouble:double;
  143. function getstring:string;
  144. {write}
  145. function create:boolean;
  146. procedure writeheader;
  147. procedure writebuf;
  148. procedure writedata(var b;len:longint);
  149. procedure writeentry(ibnr:byte);
  150. procedure putdata(var b;len:longint);
  151. procedure putbyte(b:byte);
  152. procedure putword(w:word);
  153. procedure putlongint(l:longint);
  154. procedure putdouble(d:double);
  155. procedure putstring(s:string);
  156. end;
  157. implementation
  158. {*****************************************************************************
  159. Crc 32
  160. *****************************************************************************}
  161. var
  162. Crc32Tbl : array[0..255] of longint;
  163. procedure MakeCRC32Tbl;
  164. var
  165. crc : longint;
  166. i,n : byte;
  167. begin
  168. for i:=0 to 255 do
  169. begin
  170. crc:=i;
  171. for n:=1 to 8 do
  172. if odd(crc) then
  173. crc:=(crc shr 1) xor $edb88320
  174. else
  175. crc:=crc shr 1;
  176. Crc32Tbl[i]:=crc;
  177. end;
  178. end;
  179. {CRC 32}
  180. Function Crc32(Const HStr:String):longint;
  181. var
  182. i,InitCrc : longint;
  183. begin
  184. if Crc32Tbl[1]=0 then
  185. MakeCrc32Tbl;
  186. InitCrc:=$ffffffff;
  187. for i:=1to Length(Hstr) do
  188. InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(Hstr[i])] xor (InitCrc shr 8);
  189. Crc32:=InitCrc;
  190. end;
  191. Function UpdateCrc32(InitCrc:longint;var InBuf;InLen:Longint):longint;
  192. var
  193. i : word;
  194. p : pchar;
  195. begin
  196. if Crc32Tbl[1]=0 then
  197. MakeCrc32Tbl;
  198. p:=@InBuf;
  199. for i:=1to InLen do
  200. begin
  201. InitCrc:=Crc32Tbl[byte(InitCrc) xor byte(p^)] xor (InitCrc shr 8);
  202. inc(longint(p));
  203. end;
  204. UpdateCrc32:=InitCrc;
  205. end;
  206. Function UpdCrc32(InitCrc:longint;b:byte):longint;
  207. begin
  208. if Crc32Tbl[1]=0 then
  209. MakeCrc32Tbl;
  210. UpdCrc32:=Crc32Tbl[byte(InitCrc) xor b] xor (InitCrc shr 8);
  211. end;
  212. {*****************************************************************************
  213. TPPUFile
  214. *****************************************************************************}
  215. constructor tppufile.init(fn:string);
  216. begin
  217. fname:=fn;
  218. change_endian:=false;
  219. Mode:=0;
  220. NewHeader;
  221. Error:=false;
  222. getmem(buf,ppubufsize);
  223. end;
  224. destructor tppufile.done;
  225. begin
  226. close;
  227. freemem(buf,ppubufsize);
  228. end;
  229. procedure tppufile.flush;
  230. begin
  231. if Mode=2 then
  232. writebuf;
  233. end;
  234. procedure tppufile.close;
  235. var
  236. i : word;
  237. begin
  238. if Mode<>0 then
  239. begin
  240. Flush;
  241. {$I-}
  242. system.close(f);
  243. {$I+}
  244. i:=ioresult;
  245. Mode:=0;
  246. end;
  247. end;
  248. function tppufile.CheckPPUId:boolean;
  249. begin
  250. CheckPPUId:=((Header.Id[1]='P') and (Header.Id[2]='P') and (Header.Id[3]='U'));
  251. end;
  252. function tppufile.GetPPUVersion:longint;
  253. var
  254. l : longint;
  255. code : word;
  256. begin
  257. Val(header.ver[1]+header.ver[2]+header.ver[3],l,code);
  258. if code=0 then
  259. GetPPUVersion:=l
  260. else
  261. GetPPUVersion:=0;
  262. end;
  263. procedure tppufile.NewHeader;
  264. begin
  265. fillchar(header,sizeof(tppuheader),0);
  266. with header do
  267. begin
  268. Id[1]:='P';
  269. Id[2]:='P';
  270. Id[3]:='U';
  271. Ver[1]:='0';
  272. Ver[2]:='1';
  273. Ver[3]:='5';
  274. end;
  275. end;
  276. {*****************************************************************************
  277. TPPUFile Reading
  278. *****************************************************************************}
  279. function tppufile.open:boolean;
  280. var
  281. ofmode : byte;
  282. i : word;
  283. begin
  284. open:=false;
  285. assign(f,fname);
  286. ofmode:=filemode;
  287. filemode:=$0;
  288. {$I-}
  289. reset(f,1);
  290. {$I+}
  291. filemode:=ofmode;
  292. if ioresult<>0 then
  293. exit;
  294. {read ppuheader}
  295. fsize:=filesize(f);
  296. if fsize<sizeof(tppuheader) then
  297. exit;
  298. blockread(f,header,sizeof(tppuheader),i);
  299. {reset buffer}
  300. bufstart:=i;
  301. bufsize:=0;
  302. bufidx:=0;
  303. Mode:=1;
  304. FillChar(entry,sizeof(tppuentry),0);
  305. Error:=false;
  306. open:=true;
  307. end;
  308. procedure tppufile.reloadbuf;
  309. {$ifdef TP}
  310. var
  311. i : word;
  312. {$endif}
  313. begin
  314. inc(bufstart,bufsize);
  315. {$ifdef TP}
  316. blockread(f,buf^,ppubufsize,i);
  317. bufsize:=i;
  318. {$else}
  319. blockread(f,buf^,ppubufsize,bufsize);
  320. {$endif}
  321. bufidx:=0;
  322. end;
  323. procedure tppufile.readdata(var b;len:longint);
  324. var
  325. p : pchar;
  326. left,
  327. idx : longint;
  328. begin
  329. p:=pchar(@b);
  330. idx:=0;
  331. while len>0 do
  332. begin
  333. left:=bufsize-bufidx;
  334. if len>left then
  335. begin
  336. move(buf[bufidx],p[idx],left);
  337. dec(len,left);
  338. inc(idx,left);
  339. reloadbuf;
  340. if bufsize=0 then
  341. exit;
  342. end
  343. else
  344. begin
  345. move(buf[bufidx],p[idx],len);
  346. inc(bufidx,len);
  347. exit;
  348. end;
  349. end;
  350. end;
  351. procedure tppufile.skipdata(len:longint);
  352. var
  353. left : longint;
  354. begin
  355. while len>0 do
  356. begin
  357. left:=bufsize-bufidx;
  358. if len>left then
  359. begin
  360. dec(len,left);
  361. reloadbuf;
  362. if bufsize=0 then
  363. exit;
  364. end
  365. else
  366. begin
  367. inc(bufidx,len);
  368. exit;
  369. end;
  370. end;
  371. end;
  372. function tppufile.readentry:byte;
  373. begin
  374. if entryidx<entry.size then
  375. skipdata(entry.size-entryidx);
  376. readdata(entry,sizeof(tppuentry));
  377. entryidx:=0;
  378. if entry.id<>ibentry then
  379. begin
  380. readentry:=iberror;
  381. error:=true;
  382. exit;
  383. end;
  384. readentry:=entry.nr;
  385. end;
  386. function tppufile.endofentry:boolean;
  387. begin
  388. endofentry:=(entryidx>=entry.size);
  389. end;
  390. procedure tppufile.getdata(var b;len:longint);
  391. begin
  392. if entryidx+len>entry.size then
  393. begin
  394. error:=true;
  395. exit;
  396. end;
  397. readdata(b,len);
  398. inc(entryidx,len);
  399. end;
  400. function tppufile.getbyte:byte;
  401. var
  402. b : byte;
  403. begin
  404. if entryidx+1>entry.size then
  405. begin
  406. error:=true;
  407. exit;
  408. end;
  409. { if bufidx+1>bufsize then
  410. getbyte:=ord(buf[bufidx]);
  411. inc(bufidx);}
  412. readdata(b,1);
  413. getbyte:=b;
  414. inc(entryidx);
  415. end;
  416. function tppufile.getword:word;
  417. type
  418. pword = ^word;
  419. var
  420. w : word;
  421. begin
  422. if entryidx+2>entry.size then
  423. begin
  424. error:=true;
  425. exit;
  426. end;
  427. { getword:=pword(@entrybuf[entrybufidx])^;}
  428. readdata(w,2);
  429. getword:=w;
  430. inc(entryidx,2);
  431. end;
  432. function tppufile.getlongint:longint;
  433. type
  434. plongint = ^longint;
  435. var
  436. l : longint;
  437. begin
  438. if entryidx+4>entry.size then
  439. begin
  440. error:=true;
  441. exit;
  442. end;
  443. readdata(l,4);
  444. getlongint:=l;
  445. {
  446. getlongint:=plongint(@entrybuf[entrybufidx])^;}
  447. inc(entryidx,4);
  448. end;
  449. function tppufile.getdouble:double;
  450. type
  451. pdouble = ^double;
  452. var
  453. d : double;
  454. begin
  455. if entryidx+sizeof(double)>entry.size then
  456. begin
  457. error:=true;
  458. exit;
  459. end;
  460. readdata(d,sizeof(double));
  461. getdouble:=d;
  462. {
  463. getlongint:=plongint(@entrybuf[entrybufidx])^;}
  464. inc(entryidx,sizeof(double));
  465. end;
  466. function tppufile.getstring:string;
  467. var
  468. s : string;
  469. begin
  470. s[0]:=chr(getbyte);
  471. if entryidx+length(s)>entry.size then
  472. begin
  473. error:=true;
  474. exit;
  475. end;
  476. ReadData(s[1],length(s));
  477. getstring:=s;
  478. { move(entrybuf[entrybufidx],s[1],length(s));}
  479. inc(entryidx,length(s));
  480. end;
  481. {*****************************************************************************
  482. TPPUFile Writing
  483. *****************************************************************************}
  484. function tppufile.create:boolean;
  485. begin
  486. create:=false;
  487. assign(f,fname);
  488. {$I-}
  489. rewrite(f,1);
  490. {$I+}
  491. if ioresult<>0 then
  492. exit;
  493. Mode:=2;
  494. {write header for sure}
  495. blockwrite(f,header,sizeof(tppuheader));
  496. bufsize:=ppubufsize;
  497. bufstart:=sizeof(tppuheader);
  498. bufidx:=0;
  499. {reset}
  500. crc:=$ffffffff;
  501. Error:=false;
  502. do_crc:=true;
  503. size:=0;
  504. {start}
  505. NewEntry;
  506. create:=true;
  507. end;
  508. procedure tppufile.writeheader;
  509. var
  510. opos : longint;
  511. begin
  512. { flush buffer }
  513. writebuf;
  514. { update size (w/o header!) in the header }
  515. header.size:=bufstart-sizeof(tppuheader);
  516. { write header and restore filepos after it }
  517. opos:=filepos(f);
  518. seek(f,0);
  519. blockwrite(f,header,sizeof(tppuheader));
  520. seek(f,opos);
  521. end;
  522. procedure tppufile.writebuf;
  523. begin
  524. if do_crc then
  525. UpdateCrc32(crc,buf,bufidx);
  526. blockwrite(f,buf^,bufidx);
  527. inc(bufstart,bufidx);
  528. bufidx:=0;
  529. end;
  530. procedure tppufile.writedata(var b;len:longint);
  531. var
  532. p : pchar;
  533. left,
  534. idx : longint;
  535. begin
  536. p:=pchar(@b);
  537. idx:=0;
  538. while len>0 do
  539. begin
  540. left:=bufsize-bufidx;
  541. if len>left then
  542. begin
  543. move(p[idx],buf[bufidx],left);
  544. dec(len,left);
  545. inc(idx,left);
  546. inc(bufidx,left);
  547. writebuf;
  548. end
  549. else
  550. begin
  551. move(p[idx],buf[bufidx],len);
  552. inc(bufidx,len);
  553. exit;
  554. end;
  555. end;
  556. end;
  557. procedure tppufile.NewEntry;
  558. begin
  559. with entry do
  560. begin
  561. id:=ibentry;
  562. nr:=ibend;
  563. size:=0;
  564. end;
  565. {Reset Entry State}
  566. entryidx:=0;
  567. entrybufstart:=bufstart;
  568. entrystart:=bufstart+bufidx;
  569. {Alloc in buffer}
  570. writedata(entry,sizeof(tppuentry));
  571. end;
  572. procedure tppufile.writeentry(ibnr:byte);
  573. var
  574. opos : longint;
  575. begin
  576. {create entry}
  577. entry.id:=ibentry;
  578. entry.nr:=ibnr;
  579. entry.size:=entryidx;
  580. {it's already been sent to disk ?}
  581. if entrybufstart<>bufstart then
  582. begin
  583. {flush when the entry is partly in the new buffer}
  584. if entrybufstart+sizeof(entry)>bufstart then
  585. WriteBuf;
  586. {write entry}
  587. opos:=filepos(f);
  588. seek(f,entrystart);
  589. blockwrite(f,entry,sizeof(tppuentry));
  590. seek(f,opos);
  591. entrybufstart:=bufstart;
  592. end
  593. else
  594. move(entry,buf[entrystart-bufstart],sizeof(entry));
  595. {Add New Entry, which is ibend by default}
  596. entrystart:=bufstart+bufidx; {next entry position}
  597. NewEntry;
  598. end;
  599. procedure tppufile.putdata(var b;len:longint);
  600. begin
  601. writedata(b,len);
  602. inc(entryidx,len);
  603. end;
  604. procedure tppufile.putbyte(b:byte);
  605. begin
  606. writedata(b,1);
  607. {
  608. entrybuf[entrybufidx]:=chr(b);}
  609. inc(entryidx);
  610. end;
  611. procedure tppufile.putword(w:word);
  612. type
  613. pword = ^word;
  614. begin
  615. if change_endian then
  616. w:=swap(w);
  617. { pword(@entrybuf[entrybufidx])^:=w;}
  618. writedata(w,2);
  619. inc(entryidx,2);
  620. end;
  621. procedure tppufile.putlongint(l:longint);
  622. type
  623. plongint = ^longint;
  624. begin
  625. { plongint(@entrybuf[entrybufidx])^:=l;}
  626. if change_endian then
  627. l:=swap(l shr 16) or (longint(swap(l and $ffff)) shl 16);
  628. writedata(l,4);
  629. inc(entryidx,4);
  630. end;
  631. procedure tppufile.putdouble(d:double);
  632. type
  633. pdouble = ^double;
  634. begin
  635. { plongint(@entrybuf[entrybufidx])^:=l;}
  636. writedata(d,sizeof(double));
  637. inc(entryidx,sizeof(double));
  638. end;
  639. procedure tppufile.putstring(s:string);
  640. begin
  641. writedata(s,length(s)+1);
  642. { move(s,entrybuf[entrybufidx],length(s)+1);}
  643. inc(entryidx,length(s)+1);
  644. end;
  645. end.
  646. {
  647. $Log$
  648. Revision 1.3 1998-05-28 14:40:26 peter
  649. * fixes for newppu, remake3 works now with it
  650. Revision 1.2 1998/05/27 19:45:08 peter
  651. * symtable.pas splitted into includefiles
  652. * symtable adapted for $ifdef NEWPPU
  653. Revision 1.1 1998/05/12 10:56:07 peter
  654. + the ppufile object unit
  655. }