ppu.pas 14 KB

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