entfile.pas 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150
  1. {
  2. Copyright (c) 1998-2013 by Free Pascal development team
  3. Routines to read/write entry based files (ppu, pcp)
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit entfile;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. systems,globtype,constexp,cstreams;
  22. const
  23. { buffer sizes }
  24. maxentrysize = 1024;
  25. entryfilebufsize = 16384;
  26. {ppu entries}
  27. mainentryid = 1;
  28. subentryid = 2;
  29. {special}
  30. iberror = 0;
  31. ibstartdefs = 248;
  32. ibenddefs = 249;
  33. ibstartsyms = 250;
  34. ibendsyms = 251;
  35. ibendinterface = 252;
  36. ibendimplementation = 253;
  37. // ibendbrowser = 254;
  38. ibend = 255;
  39. {general}
  40. ibmodulename = 1;
  41. ibsourcefiles = 2;
  42. ibloadunit = 3;
  43. ibinitunit = 4;
  44. iblinkunitofiles = 5;
  45. iblinkunitstaticlibs = 6;
  46. iblinkunitsharedlibs = 7;
  47. iblinkotherofiles = 8;
  48. iblinkotherstaticlibs = 9;
  49. iblinkothersharedlibs = 10;
  50. ibImportSymbols = 11;
  51. ibsymref = 12;
  52. ibdefref = 13;
  53. // ibendsymtablebrowser = 14;
  54. // ibbeginsymtablebrowser = 15;
  55. {$IFDEF MACRO_DIFF_HINT}
  56. ibusedmacros = 16;
  57. {$ENDIF}
  58. ibderefdata = 17;
  59. ibexportedmacros = 18;
  60. ibderefmap = 19;
  61. {syms}
  62. ibtypesym = 20;
  63. ibprocsym = 21;
  64. ibstaticvarsym = 22;
  65. ibconstsym = 23;
  66. ibenumsym = 24;
  67. // ibtypedconstsym = 25;
  68. ibabsolutevarsym = 26;
  69. ibpropertysym = 27;
  70. ibfieldvarsym = 28;
  71. ibunitsym = 29;
  72. iblabelsym = 30;
  73. ibsyssym = 31;
  74. ibnamespacesym = 32;
  75. iblocalvarsym = 33;
  76. ibparavarsym = 34;
  77. ibmacrosym = 35;
  78. {definitions}
  79. iborddef = 40;
  80. ibpointerdef = 41;
  81. ibarraydef = 42;
  82. ibprocdef = 43;
  83. ibshortstringdef = 44;
  84. ibrecorddef = 45;
  85. ibfiledef = 46;
  86. ibformaldef = 47;
  87. ibobjectdef = 48;
  88. ibenumdef = 49;
  89. ibsetdef = 50;
  90. ibprocvardef = 51;
  91. ibfloatdef = 52;
  92. ibclassrefdef = 53;
  93. iblongstringdef = 54;
  94. ibansistringdef = 55;
  95. ibwidestringdef = 56;
  96. ibvariantdef = 57;
  97. ibundefineddef = 58;
  98. ibunicodestringdef = 59;
  99. {implementation/ObjData}
  100. ibnodetree = 80;
  101. ibasmsymbols = 81;
  102. ibresources = 82;
  103. ibcreatedobjtypes = 83;
  104. ibwpofile = 84;
  105. ibmoduleoptions = 85;
  106. ibmainname = 90;
  107. ibsymtableoptions = 91;
  108. ibrecsymtableoptions = 91;
  109. { target-specific things }
  110. iblinkotherframeworks = 100;
  111. ibjvmnamespace = 101;
  112. {$ifdef generic_cpu}
  113. { We need to use the correct size of aint and pint for
  114. the target CPU }
  115. const
  116. CpuAddrBitSize : array[tsystemcpu] of longint =
  117. (
  118. { 0 } 32 {'none'},
  119. { 1 } 32 {'i386'},
  120. { 2 } 32 {'m68k'},
  121. { 3 } 32 {'alpha'},
  122. { 4 } 32 {'powerpc'},
  123. { 5 } 32 {'sparc'},
  124. { 6 } 32 {'vis'},
  125. { 7 } 64 {'ia64'},
  126. { 8 } 64 {'x86_64'},
  127. { 9 } 32 {'mipseb'},
  128. { 10 } 32 {'arm'},
  129. { 11 } 64 {'powerpc64'},
  130. { 12 } 16 {'avr'},
  131. { 13 } 32 {'mipsel'},
  132. { 14 } 32 {'jvm'},
  133. { 15 } 16 {'i8086'},
  134. { 16 } 64 {'aarch64'}
  135. );
  136. CpuAluBitSize : array[tsystemcpu] of longint =
  137. (
  138. { 0 } 32 {'none'},
  139. { 1 } 32 {'i386'},
  140. { 2 } 32 {'m68k'},
  141. { 3 } 32 {'alpha'},
  142. { 4 } 32 {'powerpc'},
  143. { 5 } 32 {'sparc'},
  144. { 6 } 32 {'vis'},
  145. { 7 } 64 {'ia64'},
  146. { 8 } 64 {'x86_64'},
  147. { 9 } 32 {'mipseb'},
  148. { 10 } 32 {'arm'},
  149. { 11 } 64 {'powerpc64'},
  150. { 12 } 8 {'avr'},
  151. { 13 } 32 {'mipsel'},
  152. { 14 } 64 {'jvm'},
  153. { 15 } 16 {'i8086'},
  154. { 16 } 64 {'aarch64'}
  155. );
  156. {$endif generic_cpu}
  157. type
  158. { bestreal is defined based on the target architecture }
  159. entryreal=bestreal;
  160. { common part of the header for all kinds of entry files }
  161. tentryheader=record
  162. id : array[1..3] of char;
  163. ver : array[1..3] of char;
  164. compiler : word;
  165. cpu : word;
  166. target : word;
  167. flags : longint;
  168. size : longint; { size of the ppufile without header }
  169. end;
  170. pentryheader=^tentryheader;
  171. tentry=packed record
  172. size : longint;
  173. id : byte;
  174. nr : byte;
  175. end;
  176. tentryfile=class
  177. protected
  178. buf : pchar;
  179. bufstart,
  180. bufsize,
  181. bufidx : integer;
  182. entrybufstart,
  183. entrystart,
  184. entryidx : integer;
  185. entry : tentry;
  186. closed,
  187. tempclosed : boolean;
  188. closepos : integer;
  189. protected
  190. f : TCCustomFileStream;
  191. mode : byte; {0 - Closed, 1 - Reading, 2 - Writing}
  192. fname : string;
  193. fsize : integer;
  194. procedure newheader;virtual;abstract;
  195. function readheader:longint;virtual;abstract;
  196. function outputallowed:boolean;virtual;
  197. procedure resetfile;virtual;abstract;
  198. function getheadersize:longint;virtual;abstract;
  199. function getheaderaddr:pentryheader;virtual;abstract;
  200. public
  201. entrytyp : byte;
  202. size : integer;
  203. change_endian : boolean; { Used in ppudump util }
  204. {$ifdef generic_cpu}
  205. has_more,
  206. {$endif not generic_cpu}
  207. error : boolean;
  208. constructor create(const fn:string);
  209. destructor destroy;override;
  210. procedure flush;
  211. procedure closefile;virtual;
  212. procedure newentry;
  213. {read}
  214. function openfile:boolean;
  215. procedure reloadbuf;
  216. procedure readdata(out b;len:integer);
  217. procedure skipdata(len:integer);
  218. function readentry:byte;
  219. function EndOfEntry:boolean;
  220. function entrysize:longint;
  221. function entryleft:longint;
  222. procedure getdatabuf(out b;len:integer;out res:integer);
  223. procedure getdata(out b;len:integer);
  224. function getbyte:byte;
  225. function getword:word;
  226. function getdword:dword;
  227. function getlongint:longint;
  228. function getint64:int64;
  229. function getqword:qword;
  230. function getaint:{$ifdef generic_cpu}int64{$else}aint{$endif};
  231. function getasizeint:{$ifdef generic_cpu}int64{$else}asizeint{$endif};
  232. function getaword:{$ifdef generic_cpu}qword{$else}aword{$endif};
  233. function getreal:entryreal;
  234. function getrealsize(sizeofreal : longint):entryreal;
  235. function getstring:string;
  236. function getansistring:ansistring;
  237. procedure getnormalset(out b);
  238. procedure getsmallset(out b);
  239. function skipuntilentry(untilb:byte):boolean;
  240. {write}
  241. function createfile:boolean;virtual;
  242. procedure writeheader;virtual;abstract;
  243. procedure writebuf;
  244. procedure writedata(const b;len:integer);
  245. procedure writeentry(ibnr:byte);
  246. procedure putdata(const b;len:integer);virtual;
  247. procedure putbyte(b:byte);
  248. procedure putword(w:word);
  249. procedure putdword(w:dword);
  250. procedure putlongint(l:longint);
  251. procedure putint64(i:int64);
  252. procedure putqword(q:qword);
  253. procedure putaint(i:aint);
  254. procedure putasizeint(i:asizeint);
  255. procedure putaword(i:aword);
  256. procedure putreal(d:entryreal);
  257. procedure putstring(const s:string);
  258. procedure putansistring(const s:ansistring);
  259. procedure putnormalset(const b);
  260. procedure putsmallset(const b);
  261. procedure tempclose; // MG: not used, obsolete?
  262. function tempopen:boolean; // MG: not used, obsolete?
  263. end;
  264. implementation
  265. uses
  266. cutils;
  267. function swapendian_entryreal(d:entryreal):entryreal;
  268. type
  269. entryreal_bytes=array[0..sizeof(d)-1] of byte;
  270. var
  271. i:0..sizeof(d)-1;
  272. begin
  273. for i:=low(entryreal_bytes) to high(entryreal_bytes) do
  274. entryreal_bytes(result)[i]:=entryreal_bytes(d)[high(entryreal_bytes)-i];
  275. end;
  276. {*****************************************************************************
  277. tentryfile
  278. *****************************************************************************}
  279. function tentryfile.outputallowed: boolean;
  280. begin
  281. result:=true;
  282. end;
  283. constructor tentryfile.create(const fn:string);
  284. begin
  285. fname:=fn;
  286. change_endian:=false;
  287. mode:=0;
  288. newheader;
  289. error:=false;
  290. closed:=true;
  291. tempclosed:=false;
  292. getmem(buf,entryfilebufsize);
  293. end;
  294. destructor tentryfile.destroy;
  295. begin
  296. closefile;
  297. if assigned(buf) then
  298. freemem(buf,entryfilebufsize);
  299. end;
  300. procedure tentryfile.flush;
  301. begin
  302. if mode=2 then
  303. writebuf;
  304. end;
  305. procedure tentryfile.closefile;
  306. begin
  307. if mode<>0 then
  308. begin
  309. flush;
  310. f.Free;
  311. mode:=0;
  312. closed:=true;
  313. end;
  314. end;
  315. {*****************************************************************************
  316. tentryfile Reading
  317. *****************************************************************************}
  318. function tentryfile.openfile:boolean;
  319. var
  320. i : integer;
  321. begin
  322. openfile:=false;
  323. try
  324. f:=CFileStreamClass.Create(fname,fmOpenRead)
  325. except
  326. exit;
  327. end;
  328. closed:=false;
  329. {read ppuheader}
  330. fsize:=f.Size;
  331. i:=readheader;
  332. if i<0 then
  333. exit;
  334. {reset buffer}
  335. bufstart:=i;
  336. bufsize:=0;
  337. bufidx:=0;
  338. mode:=1;
  339. FillChar(entry,sizeof(tentry),0);
  340. entryidx:=0;
  341. entrystart:=0;
  342. entrybufstart:=0;
  343. error:=false;
  344. openfile:=true;
  345. end;
  346. procedure tentryfile.reloadbuf;
  347. begin
  348. inc(bufstart,bufsize);
  349. bufsize:=f.Read(buf^,entryfilebufsize);
  350. bufidx:=0;
  351. end;
  352. procedure tentryfile.readdata(out b;len:integer);
  353. var
  354. p,pbuf : pchar;
  355. left : integer;
  356. begin
  357. p:=pchar(@b);
  358. pbuf:=@buf[bufidx];
  359. repeat
  360. left:=bufsize-bufidx;
  361. if len<left then
  362. break;
  363. move(pbuf^,p^,left);
  364. dec(len,left);
  365. inc(p,left);
  366. reloadbuf;
  367. pbuf:=@buf[bufidx];
  368. if bufsize=0 then
  369. exit;
  370. until false;
  371. move(pbuf^,p^,len);
  372. inc(bufidx,len);
  373. end;
  374. procedure tentryfile.skipdata(len:integer);
  375. var
  376. left : integer;
  377. begin
  378. while len>0 do
  379. begin
  380. left:=bufsize-bufidx;
  381. if len>left then
  382. begin
  383. dec(len,left);
  384. reloadbuf;
  385. if bufsize=0 then
  386. exit;
  387. end
  388. else
  389. begin
  390. inc(bufidx,len);
  391. exit;
  392. end;
  393. end;
  394. end;
  395. function tentryfile.readentry:byte;
  396. begin
  397. if entryidx<entry.size then
  398. begin
  399. {$ifdef generic_cpu}
  400. has_more:=true;
  401. {$endif not generic_cpu}
  402. skipdata(entry.size-entryidx);
  403. end;
  404. readdata(entry,sizeof(tentry));
  405. if change_endian then
  406. entry.size:=swapendian(entry.size);
  407. entrystart:=bufstart+bufidx;
  408. entryidx:=0;
  409. {$ifdef generic_cpu}
  410. has_more:=false;
  411. {$endif not generic_cpu}
  412. if not(entry.id in [mainentryid,subentryid]) then
  413. begin
  414. readentry:=iberror;
  415. error:=true;
  416. exit;
  417. end;
  418. readentry:=entry.nr;
  419. end;
  420. function tentryfile.endofentry:boolean;
  421. begin
  422. {$ifdef generic_cpu}
  423. endofentry:=(entryidx=entry.size);
  424. {$else not generic_cpu}
  425. endofentry:=(entryidx>=entry.size);
  426. {$endif not generic_cpu}
  427. end;
  428. function tentryfile.entrysize:longint;
  429. begin
  430. entrysize:=entry.size;
  431. end;
  432. function tentryfile.entryleft:longint;
  433. begin
  434. entryleft:=entry.size-entryidx;
  435. end;
  436. procedure tentryfile.getdatabuf(out b;len:integer;out res:integer);
  437. begin
  438. if entryidx+len>entry.size then
  439. res:=entry.size-entryidx
  440. else
  441. res:=len;
  442. readdata(b,res);
  443. inc(entryidx,res);
  444. end;
  445. procedure tentryfile.getdata(out b;len:integer);
  446. begin
  447. if entryidx+len>entry.size then
  448. begin
  449. error:=true;
  450. exit;
  451. end;
  452. readdata(b,len);
  453. inc(entryidx,len);
  454. end;
  455. function tentryfile.getbyte:byte;
  456. begin
  457. if entryidx+1>entry.size then
  458. begin
  459. error:=true;
  460. result:=0;
  461. exit;
  462. end;
  463. if bufsize-bufidx>=1 then
  464. begin
  465. result:=pbyte(@buf[bufidx])^;
  466. inc(bufidx);
  467. end
  468. else
  469. readdata(result,1);
  470. inc(entryidx);
  471. end;
  472. function tentryfile.getword:word;
  473. begin
  474. if entryidx+2>entry.size then
  475. begin
  476. error:=true;
  477. result:=0;
  478. exit;
  479. end;
  480. if bufsize-bufidx>=sizeof(word) then
  481. begin
  482. result:=Unaligned(pword(@buf[bufidx])^);
  483. inc(bufidx,sizeof(word));
  484. end
  485. else
  486. readdata(result,sizeof(word));
  487. if change_endian then
  488. result:=swapendian(result);
  489. inc(entryidx,2);
  490. end;
  491. function tentryfile.getlongint:longint;
  492. begin
  493. if entryidx+4>entry.size then
  494. begin
  495. error:=true;
  496. result:=0;
  497. exit;
  498. end;
  499. if bufsize-bufidx>=sizeof(longint) then
  500. begin
  501. result:=Unaligned(plongint(@buf[bufidx])^);
  502. inc(bufidx,sizeof(longint));
  503. end
  504. else
  505. readdata(result,sizeof(longint));
  506. if change_endian then
  507. result:=swapendian(result);
  508. inc(entryidx,4);
  509. end;
  510. function tentryfile.getdword:dword;
  511. begin
  512. if entryidx+4>entry.size then
  513. begin
  514. error:=true;
  515. result:=0;
  516. exit;
  517. end;
  518. if bufsize-bufidx>=sizeof(dword) then
  519. begin
  520. result:=Unaligned(plongint(@buf[bufidx])^);
  521. inc(bufidx,sizeof(longint));
  522. end
  523. else
  524. readdata(result,sizeof(dword));
  525. if change_endian then
  526. result:=swapendian(result);
  527. inc(entryidx,4);
  528. end;
  529. function tentryfile.getint64:int64;
  530. begin
  531. if entryidx+8>entry.size then
  532. begin
  533. error:=true;
  534. result:=0;
  535. exit;
  536. end;
  537. if bufsize-bufidx>=sizeof(int64) then
  538. begin
  539. result:=Unaligned(pint64(@buf[bufidx])^);
  540. inc(bufidx,sizeof(int64));
  541. end
  542. else
  543. readdata(result,sizeof(int64));
  544. if change_endian then
  545. result:=swapendian(result);
  546. inc(entryidx,8);
  547. end;
  548. function tentryfile.getqword:qword;
  549. begin
  550. if entryidx+8>entry.size then
  551. begin
  552. error:=true;
  553. result:=0;
  554. exit;
  555. end;
  556. if bufsize-bufidx>=sizeof(qword) then
  557. begin
  558. result:=Unaligned(pqword(@buf[bufidx])^);
  559. inc(bufidx,sizeof(qword));
  560. end
  561. else
  562. readdata(result,sizeof(qword));
  563. if change_endian then
  564. result:=swapendian(result);
  565. inc(entryidx,8);
  566. end;
  567. function tentryfile.getaint:{$ifdef generic_cpu}int64{$else}aint{$endif};
  568. {$ifdef generic_cpu}
  569. var
  570. header : pentryheader;
  571. {$endif generic_cpu}
  572. begin
  573. {$ifdef generic_cpu}
  574. header:=getheaderaddr;
  575. if CpuAluBitSize[tsystemcpu(header^.cpu)]=64 then
  576. result:=getint64
  577. else if CpuAluBitSize[tsystemcpu(header^.cpu)]=32 then
  578. result:=getlongint
  579. else if CpuAluBitSize[tsystemcpu(header^.cpu)]=16 then
  580. result:=smallint(getword)
  581. else if CpuAluBitSize[tsystemcpu(header^.cpu)]=8 then
  582. result:=shortint(getbyte)
  583. else
  584. begin
  585. error:=true;
  586. result:=0;
  587. end;
  588. {$else not generic_cpu}
  589. result:=4;
  590. case sizeof(aint) of
  591. 8: result:=getint64;
  592. 4: result:=getlongint;
  593. 2: result:=smallint(getword);
  594. 1: result:=shortint(getbyte);
  595. end;
  596. {$endif not generic_cpu}
  597. end;
  598. function tentryfile.getasizeint:{$ifdef generic_cpu}int64{$else}asizeint{$endif};
  599. {$ifdef generic_cpu}
  600. var
  601. header : pentryheader;
  602. {$endif generic_cpu}
  603. begin
  604. {$ifdef generic_cpu}
  605. header:=getheaderaddr;
  606. if CpuAddrBitSize[tsystemcpu(header^.cpu)]=64 then
  607. result:=getint64
  608. else if CpuAddrBitSize[tsystemcpu(header^.cpu)]=32 then
  609. result:=getlongint
  610. else if CpuAddrBitSize[tsystemcpu(header^.cpu)]=16 then
  611. result:=smallint(getword)
  612. else
  613. begin
  614. error:=true;
  615. result:=0;
  616. end;
  617. {$else not generic_cpu}
  618. case sizeof(asizeint) of
  619. 8: result:=asizeint(getint64);
  620. 4: result:=asizeint(getlongint);
  621. 2: result:=asizeint(getword);
  622. 1: result:=asizeint(getbyte);
  623. else
  624. result:=0;
  625. end;
  626. {$endif not generic_cpu}
  627. end;
  628. function tentryfile.getaword:{$ifdef generic_cpu}qword{$else}aword{$endif};
  629. {$ifdef generic_cpu}
  630. var
  631. header : pentryheader;
  632. {$endif generic_cpu}
  633. begin
  634. {$ifdef generic_cpu}
  635. header:=getheaderaddr;
  636. if CpuAluBitSize[tsystemcpu(header^.cpu)]=64 then
  637. result:=getqword
  638. else if CpuAluBitSize[tsystemcpu(header^.cpu)]=32 then
  639. result:=getdword
  640. else if CpuAluBitSize[tsystemcpu(header^.cpu)]=16 then
  641. result:=getword
  642. else if CpuAluBitSize[tsystemcpu(header^.cpu)]=8 then
  643. result:=getbyte
  644. else
  645. begin
  646. error:=true;
  647. result:=0;
  648. end;
  649. {$else not generic_cpu}
  650. result:=4;
  651. case sizeof(aword) of
  652. 8: result:=getqword;
  653. 4: result:=getdword;
  654. 2: result:=getword;
  655. 1: result:=getbyte;
  656. end;
  657. {$endif not generic_cpu}
  658. end;
  659. function tentryfile.getrealsize(sizeofreal : longint):entryreal;
  660. var
  661. e : entryreal;
  662. d : double;
  663. s : single;
  664. begin
  665. if sizeofreal=sizeof(e) then
  666. begin
  667. if entryidx+sizeof(e)>entry.size then
  668. begin
  669. error:=true;
  670. result:=0;
  671. exit;
  672. end;
  673. readdata(e,sizeof(e));
  674. if change_endian then
  675. result:=swapendian_entryreal(e)
  676. else
  677. result:=e;
  678. inc(entryidx,sizeof(e));
  679. exit;
  680. end;
  681. if sizeofreal=sizeof(d) then
  682. begin
  683. if entryidx+sizeof(d)>entry.size then
  684. begin
  685. error:=true;
  686. result:=0;
  687. exit;
  688. end;
  689. readdata(d,sizeof(d));
  690. if change_endian then
  691. result:=swapendian(pqword(@d)^)
  692. else
  693. result:=d;
  694. inc(entryidx,sizeof(d));
  695. result:=d;
  696. exit;
  697. end;
  698. if sizeofreal=sizeof(s) then
  699. begin
  700. if entryidx+sizeof(s)>entry.size then
  701. begin
  702. error:=true;
  703. result:=0;
  704. exit;
  705. end;
  706. readdata(s,sizeof(s));
  707. if change_endian then
  708. result:=swapendian(pdword(@s)^)
  709. else
  710. result:=s;
  711. inc(entryidx,sizeof(s));
  712. result:=s;
  713. exit;
  714. end;
  715. error:=true;
  716. result:=0.0;
  717. end;
  718. function tentryfile.getreal:entryreal;
  719. var
  720. d : entryreal;
  721. hd : double;
  722. begin
  723. if target_info.system=system_x86_64_win64 then
  724. begin
  725. hd:=getrealsize(sizeof(hd));
  726. getreal:=hd;
  727. end
  728. else
  729. begin
  730. d:=getrealsize(sizeof(d));
  731. getreal:=d;
  732. end;
  733. end;
  734. function tentryfile.getstring:string;
  735. begin
  736. result[0]:=chr(getbyte);
  737. if entryidx+length(result)>entry.size then
  738. begin
  739. error:=true;
  740. exit;
  741. end;
  742. ReadData(result[1],length(result));
  743. inc(entryidx,length(result));
  744. end;
  745. function tentryfile.getansistring:ansistring;
  746. var
  747. len: longint;
  748. begin
  749. len:=getlongint;
  750. if entryidx+len>entry.size then
  751. begin
  752. error:=true;
  753. result:='';
  754. exit;
  755. end;
  756. setlength(result,len);
  757. if len>0 then
  758. getdata(result[1],len);
  759. end;
  760. procedure tentryfile.getsmallset(out b);
  761. var
  762. i : longint;
  763. begin
  764. getdata(b,4);
  765. if change_endian then
  766. for i:=0 to 3 do
  767. Pbyte(@b)[i]:=reverse_byte(Pbyte(@b)[i]);
  768. end;
  769. procedure tentryfile.getnormalset(out b);
  770. var
  771. i : longint;
  772. begin
  773. getdata(b,32);
  774. if change_endian then
  775. for i:=0 to 31 do
  776. Pbyte(@b)[i]:=reverse_byte(Pbyte(@b)[i]);
  777. end;
  778. function tentryfile.skipuntilentry(untilb:byte):boolean;
  779. var
  780. b : byte;
  781. begin
  782. repeat
  783. b:=readentry;
  784. until (b in [ibend,iberror]) or ((b=untilb) and (entry.id=mainentryid));
  785. skipuntilentry:=(b=untilb);
  786. end;
  787. {*****************************************************************************
  788. tentryfile Writing
  789. *****************************************************************************}
  790. function tentryfile.createfile:boolean;
  791. var
  792. ok: boolean;
  793. begin
  794. createfile:=false;
  795. if outputallowed then
  796. begin
  797. {$ifdef MACOS}
  798. {FPas is FreePascal's creator code on MacOS. See systems/mac_crea.txt}
  799. SetDefaultMacOSCreator('FPas');
  800. SetDefaultMacOSFiletype('FPPU');
  801. {$endif}
  802. ok:=false;
  803. try
  804. f:=CFileStreamClass.Create(fname,fmCreate);
  805. ok:=true;
  806. except
  807. end;
  808. {$ifdef MACOS}
  809. SetDefaultMacOSCreator('MPS ');
  810. SetDefaultMacOSFiletype('TEXT');
  811. {$endif}
  812. if not ok then
  813. exit;
  814. mode:=2;
  815. {write header for sure}
  816. f.Write(getheaderaddr^,getheadersize);
  817. end;
  818. bufsize:=entryfilebufsize;
  819. bufstart:=getheadersize;
  820. bufidx:=0;
  821. {reset}
  822. resetfile;
  823. error:=false;
  824. size:=0;
  825. entrytyp:=mainentryid;
  826. {start}
  827. newentry;
  828. createfile:=true;
  829. end;
  830. procedure tentryfile.writebuf;
  831. begin
  832. if outputallowed and
  833. (bufidx <> 0) then
  834. f.Write(buf^,bufidx);
  835. inc(bufstart,bufidx);
  836. bufidx:=0;
  837. end;
  838. procedure tentryfile.writedata(const b;len:integer);
  839. var
  840. p : pchar;
  841. left,
  842. idx : integer;
  843. begin
  844. if not outputallowed then
  845. exit;
  846. p:=pchar(@b);
  847. idx:=0;
  848. while len>0 do
  849. begin
  850. left:=bufsize-bufidx;
  851. if len>left then
  852. begin
  853. move(p[idx],buf[bufidx],left);
  854. dec(len,left);
  855. inc(idx,left);
  856. inc(bufidx,left);
  857. writebuf;
  858. end
  859. else
  860. begin
  861. move(p[idx],buf[bufidx],len);
  862. inc(bufidx,len);
  863. exit;
  864. end;
  865. end;
  866. end;
  867. procedure tentryfile.newentry;
  868. begin
  869. with entry do
  870. begin
  871. id:=entrytyp;
  872. nr:=ibend;
  873. size:=0;
  874. end;
  875. {Reset Entry State}
  876. entryidx:=0;
  877. entrybufstart:=bufstart;
  878. entrystart:=bufstart+bufidx;
  879. {Alloc in buffer}
  880. writedata(entry,sizeof(tentry));
  881. end;
  882. procedure tentryfile.writeentry(ibnr:byte);
  883. var
  884. opos : integer;
  885. begin
  886. {create entry}
  887. entry.id:=entrytyp;
  888. entry.nr:=ibnr;
  889. entry.size:=entryidx;
  890. {it's already been sent to disk ?}
  891. if entrybufstart<>bufstart then
  892. begin
  893. if outputallowed then
  894. begin
  895. {flush to be sure}
  896. WriteBuf;
  897. {write entry}
  898. opos:=f.Position;
  899. f.Position:=entrystart;
  900. f.write(entry,sizeof(tentry));
  901. f.Position:=opos;
  902. end;
  903. entrybufstart:=bufstart;
  904. end
  905. else
  906. move(entry,buf[entrystart-bufstart],sizeof(entry));
  907. {Add New Entry, which is ibend by default}
  908. entrystart:=bufstart+bufidx; {next entry position}
  909. newentry;
  910. end;
  911. procedure tentryfile.putdata(const b;len:integer);
  912. begin
  913. if outputallowed then
  914. writedata(b,len);
  915. inc(entryidx,len);
  916. end;
  917. procedure tentryfile.putbyte(b:byte);
  918. begin
  919. putdata(b,1);
  920. end;
  921. procedure tentryfile.putword(w:word);
  922. begin
  923. putdata(w,2);
  924. end;
  925. procedure tentryfile.putdword(w:dword);
  926. begin
  927. putdata(w,4);
  928. end;
  929. procedure tentryfile.putlongint(l:longint);
  930. begin
  931. putdata(l,4);
  932. end;
  933. procedure tentryfile.putint64(i:int64);
  934. begin
  935. putdata(i,8);
  936. end;
  937. procedure tentryfile.putqword(q:qword);
  938. begin
  939. putdata(q,sizeof(qword));
  940. end;
  941. procedure tentryfile.putaint(i:aint);
  942. begin
  943. putdata(i,sizeof(aint));
  944. end;
  945. procedure tentryfile.putasizeint(i: asizeint);
  946. begin
  947. putdata(i,sizeof(asizeint));
  948. end;
  949. procedure tentryfile.putaword(i:aword);
  950. begin
  951. putdata(i,sizeof(aword));
  952. end;
  953. procedure tentryfile.putreal(d:entryreal);
  954. var
  955. hd : double;
  956. begin
  957. if target_info.system=system_x86_64_win64 then
  958. begin
  959. hd:=d;
  960. putdata(hd,sizeof(hd));
  961. end
  962. else
  963. putdata(d,sizeof(entryreal));
  964. end;
  965. procedure tentryfile.putstring(const s:string);
  966. begin
  967. putdata(s,length(s)+1);
  968. end;
  969. procedure tentryfile.putansistring(const s:ansistring);
  970. var
  971. len: longint;
  972. begin
  973. len:=length(s);
  974. putlongint(len);
  975. if len>0 then
  976. putdata(s[1],len);
  977. end;
  978. procedure tentryfile.putsmallset(const b);
  979. var
  980. l : longint;
  981. begin
  982. l:=longint(b);
  983. putlongint(l);
  984. end;
  985. procedure tentryfile.putnormalset(const b);
  986. begin
  987. putdata(b,32);
  988. end;
  989. procedure tentryfile.tempclose;
  990. begin
  991. if not closed then
  992. begin
  993. closepos:=f.Position;
  994. f.Free;
  995. f:=nil;
  996. closed:=true;
  997. tempclosed:=true;
  998. end;
  999. end;
  1000. function tentryfile.tempopen:boolean;
  1001. begin
  1002. tempopen:=false;
  1003. if not closed or not tempclosed then
  1004. exit;
  1005. { MG: not sure, if this is correct
  1006. f.position:=0;
  1007. No, f was freed in tempclose above, we need to
  1008. recreate it. PM 2011/06/06 }
  1009. try
  1010. f:=CFileStreamClass.Create(fname,fmOpenRead);
  1011. except
  1012. exit;
  1013. end;
  1014. closed:=false;
  1015. tempclosed:=false;
  1016. { restore state }
  1017. f.Position:=closepos;
  1018. tempopen:=true;
  1019. end;
  1020. end.