entfile.pas 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384
  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. ibextraheader = 242;
  32. ibpputable = 243;
  33. ibstartrequireds = 244;
  34. ibendrequireds = 245;
  35. ibstartcontained = 246;
  36. ibendcontained = 247;
  37. ibstartdefs = 248;
  38. ibenddefs = 249;
  39. ibstartsyms = 250;
  40. ibendsyms = 251;
  41. ibendinterface = 252;
  42. ibendimplementation = 253;
  43. // ibendbrowser = 254;
  44. ibend = 255;
  45. {general}
  46. ibmodulename = 1;
  47. ibsourcefiles = 2;
  48. ibloadunit = 3;
  49. ibinitunit = 4;
  50. iblinkunitofiles = 5;
  51. iblinkunitstaticlibs = 6;
  52. iblinkunitsharedlibs = 7;
  53. iblinkotherofiles = 8;
  54. iblinkotherstaticlibs = 9;
  55. iblinkothersharedlibs = 10;
  56. ibImportSymbols = 11;
  57. ibsymref = 12;
  58. ibdefref = 13;
  59. ibfeatures = 14;
  60. {$IFDEF MACRO_DIFF_HINT}
  61. ibusedmacros = 16;
  62. {$ENDIF}
  63. ibderefdata = 17;
  64. ibexportedmacros = 18;
  65. ibderefmap = 19;
  66. {syms}
  67. ibtypesym = 20;
  68. ibprocsym = 21;
  69. ibstaticvarsym = 22;
  70. ibconstsym = 23;
  71. ibenumsym = 24;
  72. // ibtypedconstsym = 25;
  73. ibabsolutevarsym = 26;
  74. ibpropertysym = 27;
  75. ibfieldvarsym = 28;
  76. ibunitsym = 29;
  77. iblabelsym = 30;
  78. ibsyssym = 31;
  79. ibnamespacesym = 32;
  80. iblocalvarsym = 33;
  81. ibparavarsym = 34;
  82. ibmacrosym = 35;
  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. ibundefineddef = 58;
  103. ibunicodestringdef = 59;
  104. {implementation/ObjData}
  105. ibnodetree = 80;
  106. ibasmsymbols = 81;
  107. ibresources = 82;
  108. ibcreatedobjtypes = 83;
  109. ibwpofile = 84;
  110. ibmoduleoptions = 85;
  111. ibunitimportsyms = 86;
  112. iborderedsymbols = 87;
  113. ibmainname = 90;
  114. ibsymtableoptions = 91;
  115. ibrecsymtableoptions = 91;
  116. ibpackagefiles = 92;
  117. ibpackagename = 93;
  118. { target-specific things }
  119. iblinkotherframeworks = 100;
  120. ibjvmnamespace = 101;
  121. {$ifdef generic_cpu}
  122. { We need to use the correct size of aint and pint for
  123. the target CPU }
  124. const
  125. CpuAddrBitSize : array[tsystemcpu] of longint =
  126. (
  127. { 0 } 32 {'none'},
  128. { 1 } 32 {'i386'},
  129. { 2 } 32 {'m68k'},
  130. { 3 } 32 {'alpha'},
  131. { 4 } 32 {'powerpc'},
  132. { 5 } 32 {'sparc'},
  133. { 6 } 32 {'vis'},
  134. { 7 } 64 {'ia64'},
  135. { 8 } 64 {'x86_64'},
  136. { 9 } 32 {'mipseb'},
  137. { 10 } 32 {'arm'},
  138. { 11 } 64 {'powerpc64'},
  139. { 12 } 16 {'avr'},
  140. { 13 } 32 {'mipsel'},
  141. { 14 } 32 {'jvm'},
  142. { 15 } 16 {'i8086'},
  143. { 16 } 64 {'aarch64'},
  144. { 17 } 32 {'wasm'},
  145. { 18 } 64 {'sparc64'},
  146. { 19 } 32 {'riscv32'},
  147. { 20 } 64 {'riscv64'}
  148. );
  149. CpuAluBitSize : array[tsystemcpu] of longint =
  150. (
  151. { 0 } 32 {'none'},
  152. { 1 } 32 {'i386'},
  153. { 2 } 32 {'m68k'},
  154. { 3 } 32 {'alpha'},
  155. { 4 } 32 {'powerpc'},
  156. { 5 } 32 {'sparc'},
  157. { 6 } 32 {'vis'},
  158. { 7 } 64 {'ia64'},
  159. { 8 } 64 {'x86_64'},
  160. { 9 } 32 {'mipseb'},
  161. { 10 } 32 {'arm'},
  162. { 11 } 64 {'powerpc64'},
  163. { 12 } 8 {'avr'},
  164. { 13 } 32 {'mipsel'},
  165. { 14 } 64 {'jvm'},
  166. { 15 } 16 {'i8086'},
  167. { 16 } 64 {'aarch64'},
  168. { 17 } 64 {'wasm'},
  169. { 18 } 64 {'sparc64'},
  170. { 19 } 32 {'riscv32'},
  171. { 20 } 64 {'riscv64'}
  172. );
  173. {$endif generic_cpu}
  174. type
  175. { bestreal is defined based on the target architecture }
  176. entryreal=bestreal;
  177. { common part of the header for all kinds of entry files }
  178. tentryheader=record
  179. id : array[1..3] of char;
  180. ver : array[1..3] of char;
  181. compiler : word;
  182. cpu : word;
  183. target : word;
  184. flags : dword;
  185. size : dword; { size of the ppufile without header }
  186. end;
  187. pentryheader=^tentryheader;
  188. tentry=packed record
  189. size : longint;
  190. id : byte;
  191. nr : byte;
  192. end;
  193. tentryfile=class
  194. private
  195. function getposition:longint;
  196. procedure setposition(value:longint);
  197. protected
  198. buf : pchar;
  199. bufstart,
  200. bufsize,
  201. bufidx : integer;
  202. entrybufstart,
  203. entrystart,
  204. entryidx : integer;
  205. entry : tentry;
  206. closed,
  207. tempclosed : boolean;
  208. closepos : integer;
  209. protected
  210. f : TCStream;
  211. mode : byte; {0 - Closed, 1 - Reading, 2 - Writing}
  212. fisfile : boolean;
  213. fname : string;
  214. fsize : integer;
  215. procedure newheader;virtual;abstract;
  216. function readheader:longint;virtual;abstract;
  217. function outputallowed:boolean;virtual;
  218. procedure resetfile;virtual;abstract;
  219. function getheadersize:longint;virtual;abstract;
  220. function getheaderaddr:pentryheader;virtual;abstract;
  221. procedure RaiseAssertion(Code: Longint); virtual;
  222. public
  223. entrytyp : byte;
  224. size : integer;
  225. change_endian : boolean; { Used in ppudump util }
  226. {$ifdef generic_cpu}
  227. has_more,
  228. {$endif not generic_cpu}
  229. error : boolean;
  230. constructor create(const fn:string);
  231. destructor destroy;override;
  232. function getversion:integer;
  233. procedure flush;
  234. procedure closefile;virtual;
  235. procedure newentry;
  236. property position:longint read getposition write setposition;
  237. { Warning: don't keep the stream open during a tempclose! }
  238. function substream(ofs,len:longint):TCStream;
  239. { Warning: don't use the put* or write* functions anymore when writing through this }
  240. property stream:TCStream read f;
  241. {read}
  242. function openfile:boolean;
  243. function openstream(strm:TCStream):boolean;
  244. procedure reloadbuf;
  245. procedure readdata(out b;len:integer);
  246. procedure skipdata(len:integer);
  247. function readentry:byte;
  248. function EndOfEntry:boolean;
  249. function entrysize:longint;
  250. function entryleft:longint;
  251. procedure getdatabuf(out b;len:integer;out res:integer);
  252. procedure getdata(out b;len:integer);
  253. function getbyte:byte;
  254. function getword:word;
  255. function getdword:dword;
  256. function getlongint:longint;
  257. function getint64:int64;
  258. function getqword:qword;
  259. function getaint:{$ifdef generic_cpu}int64{$else}aint{$endif};
  260. function getasizeint:{$ifdef generic_cpu}int64{$else}asizeint{$endif};
  261. function getpuint:{$ifdef generic_cpu}qword{$else}puint{$endif};
  262. function getptruint:{$ifdef generic_cpu}qword{$else}TConstPtrUInt{$endif};
  263. function getaword:{$ifdef generic_cpu}qword{$else}aword{$endif};
  264. function getreal:entryreal;
  265. function getrealsize(sizeofreal : longint):entryreal;
  266. function getboolean:boolean;inline;
  267. function getstring:string;
  268. function getpshortstring:pshortstring;
  269. function getansistring:ansistring;
  270. procedure getnormalset(out b);
  271. procedure getsmallset(out b);
  272. function skipuntilentry(untilb:byte):boolean;
  273. {write}
  274. function createfile:boolean;virtual;
  275. function createstream(strm:TCStream):boolean;
  276. procedure writeheader;virtual;abstract;
  277. procedure writebuf;
  278. procedure writedata(const b;len:integer);
  279. procedure writeentry(ibnr:byte);
  280. procedure putdata(const b;len:integer);virtual;
  281. procedure putbyte(b:byte);
  282. procedure putword(w:word);
  283. procedure putdword(w:dword);
  284. procedure putlongint(l:longint);
  285. procedure putint64(i:int64);
  286. procedure putqword(q:qword);
  287. procedure putaint(i:aint);
  288. procedure putasizeint(i:asizeint);
  289. procedure putpuint(i:puint);
  290. procedure putptruint(v:TConstPtrUInt);
  291. procedure putaword(i:aword);
  292. procedure putreal(d:entryreal);
  293. procedure putboolean(b:boolean);inline;
  294. procedure putstring(const s:string);
  295. procedure putansistring(const s:ansistring);
  296. procedure putnormalset(const b);
  297. procedure putsmallset(const b);
  298. procedure tempclose; // MG: not used, obsolete?
  299. function tempopen:boolean; // MG: not used, obsolete?
  300. end;
  301. implementation
  302. uses
  303. cutils;
  304. function swapendian_entryreal(d:entryreal):entryreal;
  305. type
  306. entryreal_bytes=array[0..sizeof(d)-1] of byte;
  307. var
  308. i:0..sizeof(d)-1;
  309. begin
  310. for i:=low(entryreal_bytes) to high(entryreal_bytes) do
  311. entryreal_bytes(result)[i]:=entryreal_bytes(d)[high(entryreal_bytes)-i];
  312. end;
  313. {*****************************************************************************
  314. tentryfile
  315. *****************************************************************************}
  316. function tentryfile.outputallowed: boolean;
  317. begin
  318. result:=true;
  319. end;
  320. constructor tentryfile.create(const fn:string);
  321. begin
  322. fname:=fn;
  323. fisfile:=false;
  324. change_endian:=false;
  325. mode:=0;
  326. newheader;
  327. error:=false;
  328. closed:=true;
  329. tempclosed:=false;
  330. getmem(buf,entryfilebufsize);
  331. end;
  332. destructor tentryfile.destroy;
  333. begin
  334. closefile;
  335. if assigned(buf) then
  336. freemem(buf,entryfilebufsize);
  337. end;
  338. function tentryfile.getversion:integer;
  339. var
  340. l : integer;
  341. code : integer;
  342. header : pentryheader;
  343. begin
  344. header:=getheaderaddr;
  345. Val(header^.ver[1]+header^.ver[2]+header^.ver[3],l,code);
  346. if code=0 then
  347. result:=l
  348. else
  349. result:=0;
  350. end;
  351. procedure tentryfile.flush;
  352. begin
  353. if mode=2 then
  354. writebuf;
  355. end;
  356. procedure tentryfile.RaiseAssertion(Code: Longint);
  357. begin
  358. { It's down to descendent classes to raise an internal error as desired. [Kit] }
  359. error := true;
  360. end;
  361. procedure tentryfile.closefile;
  362. begin
  363. if mode<>0 then
  364. begin
  365. flush;
  366. if fisfile then
  367. f.Free;
  368. mode:=0;
  369. closed:=true;
  370. end;
  371. end;
  372. procedure tentryfile.setposition(value:longint);
  373. begin
  374. if assigned(f) then
  375. f.Position:=value
  376. else
  377. if tempclosed then
  378. closepos:=value;
  379. end;
  380. function tentryfile.getposition:longint;
  381. begin
  382. if assigned(f) then
  383. result:=f.Position
  384. else
  385. if tempclosed then
  386. result:=closepos
  387. else
  388. result:=0;
  389. end;
  390. function tentryfile.substream(ofs,len:longint):TCStream;
  391. begin
  392. result:=nil;
  393. if assigned(f) then
  394. result:=TCRangeStream.Create(f,ofs,len);
  395. end;
  396. {*****************************************************************************
  397. tentryfile Reading
  398. *****************************************************************************}
  399. function tentryfile.openfile:boolean;
  400. var
  401. strm : TCStream;
  402. begin
  403. openfile:=false;
  404. try
  405. strm:=CFileStreamClass.Create(fname,fmOpenRead)
  406. except
  407. exit;
  408. end;
  409. openfile:=openstream(strm);
  410. fisfile:=result;
  411. end;
  412. function tentryfile.openstream(strm:TCStream):boolean;
  413. var
  414. i : longint;
  415. begin
  416. openstream:=false;
  417. f:=strm;
  418. closed:=false;
  419. {read ppuheader}
  420. fsize:=f.Size;
  421. i:=readheader;
  422. if i<0 then
  423. exit;
  424. {reset buffer}
  425. bufstart:=i;
  426. bufsize:=0;
  427. bufidx:=0;
  428. mode:=1;
  429. FillChar(entry,sizeof(tentry),0);
  430. entryidx:=0;
  431. entrystart:=0;
  432. entrybufstart:=0;
  433. error:=false;
  434. openstream:=true;
  435. end;
  436. procedure tentryfile.reloadbuf;
  437. begin
  438. inc(bufstart,bufsize);
  439. bufsize:=f.Read(buf^,entryfilebufsize);
  440. bufidx:=0;
  441. end;
  442. procedure tentryfile.readdata(out b;len:integer);
  443. var
  444. p,pbuf : pchar;
  445. left : integer;
  446. begin
  447. p:=pchar(@b);
  448. pbuf:=@buf[bufidx];
  449. repeat
  450. left:=bufsize-bufidx;
  451. if len<left then
  452. break;
  453. move(pbuf^,p^,left);
  454. dec(len,left);
  455. inc(p,left);
  456. reloadbuf;
  457. pbuf:=@buf[bufidx];
  458. if bufsize=0 then
  459. exit;
  460. until false;
  461. move(pbuf^,p^,len);
  462. inc(bufidx,len);
  463. end;
  464. procedure tentryfile.skipdata(len:integer);
  465. var
  466. left : integer;
  467. begin
  468. while len>0 do
  469. begin
  470. left:=bufsize-bufidx;
  471. if len>left then
  472. begin
  473. dec(len,left);
  474. reloadbuf;
  475. if bufsize=0 then
  476. exit;
  477. end
  478. else
  479. begin
  480. inc(bufidx,len);
  481. exit;
  482. end;
  483. end;
  484. end;
  485. function tentryfile.readentry:byte;
  486. begin
  487. if entryidx<entry.size then
  488. begin
  489. {$ifdef generic_cpu}
  490. has_more:=true;
  491. {$endif not generic_cpu}
  492. skipdata(entry.size-entryidx);
  493. end;
  494. readdata(entry,sizeof(tentry));
  495. if change_endian then
  496. entry.size:=swapendian(entry.size);
  497. entrystart:=bufstart+bufidx;
  498. entryidx:=0;
  499. {$ifdef generic_cpu}
  500. has_more:=false;
  501. {$endif not generic_cpu}
  502. if not(entry.id in [mainentryid,subentryid]) then
  503. begin
  504. readentry:=iberror;
  505. error:=true;
  506. exit;
  507. end;
  508. readentry:=entry.nr;
  509. end;
  510. function tentryfile.endofentry:boolean;
  511. begin
  512. {$ifdef generic_cpu}
  513. endofentry:=(entryidx=entry.size);
  514. {$else not generic_cpu}
  515. endofentry:=(entryidx>=entry.size);
  516. {$endif not generic_cpu}
  517. end;
  518. function tentryfile.entrysize:longint;
  519. begin
  520. entrysize:=entry.size;
  521. end;
  522. function tentryfile.entryleft:longint;
  523. begin
  524. entryleft:=entry.size-entryidx;
  525. end;
  526. procedure tentryfile.getdatabuf(out b;len:integer;out res:integer);
  527. begin
  528. if entryidx+len>entry.size then
  529. res:=entry.size-entryidx
  530. else
  531. res:=len;
  532. readdata(b,res);
  533. inc(entryidx,res);
  534. end;
  535. procedure tentryfile.getdata(out b;len:integer);
  536. begin
  537. if entryidx+len>entry.size then
  538. begin
  539. error:=true;
  540. exit;
  541. end;
  542. readdata(b,len);
  543. inc(entryidx,len);
  544. end;
  545. function tentryfile.getbyte:byte;
  546. begin
  547. if entryidx>=entry.size then
  548. begin
  549. error:=true;
  550. result:=0;
  551. exit;
  552. end;
  553. if bufidx<bufsize then
  554. begin
  555. result:=pbyte(@buf[bufidx])^;
  556. inc(bufidx);
  557. end
  558. else
  559. readdata(result,1);
  560. inc(entryidx);
  561. end;
  562. function tentryfile.getword:word;
  563. begin
  564. if entryidx+2>entry.size then
  565. begin
  566. error:=true;
  567. result:=0;
  568. exit;
  569. end;
  570. if bufsize-bufidx>=sizeof(word) then
  571. begin
  572. result:=Unaligned(pword(@buf[bufidx])^);
  573. inc(bufidx,sizeof(word));
  574. end
  575. else
  576. readdata(result,sizeof(word));
  577. if change_endian then
  578. result:=swapendian(result);
  579. inc(entryidx,2);
  580. end;
  581. function tentryfile.getlongint:longint;
  582. begin
  583. if entryidx+4>entry.size then
  584. begin
  585. error:=true;
  586. result:=0;
  587. exit;
  588. end;
  589. if bufsize-bufidx>=sizeof(longint) then
  590. begin
  591. result:=Unaligned(plongint(@buf[bufidx])^);
  592. inc(bufidx,sizeof(longint));
  593. end
  594. else
  595. readdata(result,sizeof(longint));
  596. if change_endian then
  597. result:=swapendian(result);
  598. inc(entryidx,4);
  599. end;
  600. function tentryfile.getdword:dword;
  601. begin
  602. if entryidx+4>entry.size then
  603. begin
  604. error:=true;
  605. result:=0;
  606. exit;
  607. end;
  608. if bufsize-bufidx>=sizeof(dword) then
  609. begin
  610. result:=Unaligned(pdword(@buf[bufidx])^);
  611. inc(bufidx,sizeof(longint));
  612. end
  613. else
  614. readdata(result,sizeof(dword));
  615. if change_endian then
  616. result:=swapendian(result);
  617. inc(entryidx,4);
  618. end;
  619. function tentryfile.getint64:int64;
  620. begin
  621. if entryidx+8>entry.size then
  622. begin
  623. error:=true;
  624. result:=0;
  625. exit;
  626. end;
  627. if bufsize-bufidx>=sizeof(int64) then
  628. begin
  629. result:=Unaligned(pint64(@buf[bufidx])^);
  630. inc(bufidx,sizeof(int64));
  631. end
  632. else
  633. readdata(result,sizeof(int64));
  634. if change_endian then
  635. result:=swapendian(result);
  636. inc(entryidx,8);
  637. end;
  638. function tentryfile.getqword:qword;
  639. begin
  640. if entryidx+8>entry.size then
  641. begin
  642. error:=true;
  643. result:=0;
  644. exit;
  645. end;
  646. if bufsize-bufidx>=sizeof(qword) then
  647. begin
  648. result:=Unaligned(pqword(@buf[bufidx])^);
  649. inc(bufidx,sizeof(qword));
  650. end
  651. else
  652. readdata(result,sizeof(qword));
  653. if change_endian then
  654. result:=swapendian(result);
  655. inc(entryidx,8);
  656. end;
  657. function tentryfile.getaint:{$ifdef generic_cpu}int64{$else}aint{$endif};
  658. {$ifdef generic_cpu}
  659. var
  660. header : pentryheader;
  661. {$endif generic_cpu}
  662. begin
  663. {$ifdef generic_cpu}
  664. header:=getheaderaddr;
  665. if CpuAluBitSize[tsystemcpu(header^.cpu)]=64 then
  666. result:=getint64
  667. else if CpuAluBitSize[tsystemcpu(header^.cpu)]=32 then
  668. result:=getlongint
  669. else if CpuAluBitSize[tsystemcpu(header^.cpu)]=16 then
  670. result:=smallint(getword)
  671. else if CpuAluBitSize[tsystemcpu(header^.cpu)]=8 then
  672. result:=shortint(getbyte)
  673. else
  674. begin
  675. error:=true;
  676. result:=0;
  677. end;
  678. {$else not generic_cpu}
  679. case sizeof(aint) of
  680. 8: result:=getint64;
  681. 4: result:=getlongint;
  682. 2: result:=smallint(getword);
  683. 1: result:=shortint(getbyte);
  684. else
  685. begin
  686. RaiseAssertion(2019041801);
  687. result:=0;
  688. end;
  689. end;
  690. {$endif not generic_cpu}
  691. end;
  692. function tentryfile.getasizeint:{$ifdef generic_cpu}int64{$else}asizeint{$endif};
  693. {$ifdef generic_cpu}
  694. var
  695. header : pentryheader;
  696. {$endif generic_cpu}
  697. begin
  698. {$ifdef generic_cpu}
  699. header:=getheaderaddr;
  700. if CpuAddrBitSize[tsystemcpu(header^.cpu)]=64 then
  701. result:=getint64
  702. else if CpuAddrBitSize[tsystemcpu(header^.cpu)]=32 then
  703. result:=getlongint
  704. else if CpuAddrBitSize[tsystemcpu(header^.cpu)]=16 then
  705. begin
  706. { result:=smallint(getword);
  707. would have been logical, but it contradicts
  708. definition of asizeint in globtype unit,
  709. which uses 32-bit lngint type even for 16-bit
  710. address size, to be able to cope with
  711. I8086 seg:ofs huge addresses }
  712. result:=getlongint;
  713. end
  714. else
  715. begin
  716. error:=true;
  717. result:=0;
  718. end;
  719. {$else not generic_cpu}
  720. case sizeof(asizeint) of
  721. 8: result:=asizeint(getint64);
  722. 4: result:=asizeint(getlongint);
  723. 2: result:=asizeint(getword);
  724. 1: result:=asizeint(getbyte);
  725. else
  726. begin
  727. RaiseAssertion(2019041802);
  728. result:=0;
  729. end;
  730. end;
  731. {$endif not generic_cpu}
  732. end;
  733. function tentryfile.getpuint:{$ifdef generic_cpu}qword{$else}puint{$endif};
  734. {$ifdef generic_cpu}
  735. var
  736. header : pentryheader;
  737. {$endif generic_cpu}
  738. begin
  739. {$ifdef generic_cpu}
  740. header:=getheaderaddr;
  741. if CpuAddrBitSize[tsystemcpu(header^.cpu)]=64 then
  742. result:=getqword
  743. else if CpuAddrBitSize[tsystemcpu(header^.cpu)]=32 then
  744. result:=getdword
  745. else if CpuAddrBitSize[tsystemcpu(header^.cpu)]=16 then
  746. result:=getword
  747. else
  748. begin
  749. error:=true;
  750. result:=0;
  751. end;
  752. {$else not generic_cpu}
  753. case sizeof(puint) of
  754. 8: result:=getqword;
  755. 4: result:=getdword;
  756. 2: result:=getword;
  757. 1: result:=getbyte;
  758. else
  759. begin
  760. RaiseAssertion(2019041803);
  761. result:=0;
  762. end;
  763. end;
  764. {$endif not generic_cpu}
  765. end;
  766. function tentryfile.getptruint:{$ifdef generic_cpu}qword{$else}TConstPtrUInt{$endif};
  767. {$ifdef generic_cpu}
  768. var
  769. header : pentryheader;
  770. {$endif generic_cpu}
  771. begin
  772. {$ifdef generic_cpu}
  773. header:=getheaderaddr;
  774. if CpuAddrBitSize[tsystemcpu(header^.cpu)]=64 then
  775. result:=getqword
  776. else result:=getdword;
  777. {$else not generic_cpu}
  778. {$if sizeof(TConstPtrUInt)=8}
  779. result:=tconstptruint(getint64);
  780. {$else}
  781. result:=TConstPtrUInt(getlongint);
  782. {$endif}
  783. {$endif not generic_cpu}
  784. end;
  785. function tentryfile.getaword:{$ifdef generic_cpu}qword{$else}aword{$endif};
  786. {$ifdef generic_cpu}
  787. var
  788. header : pentryheader;
  789. {$endif generic_cpu}
  790. begin
  791. {$ifdef generic_cpu}
  792. header:=getheaderaddr;
  793. if CpuAluBitSize[tsystemcpu(header^.cpu)]=64 then
  794. result:=getqword
  795. else if CpuAluBitSize[tsystemcpu(header^.cpu)]=32 then
  796. result:=getdword
  797. else if CpuAluBitSize[tsystemcpu(header^.cpu)]=16 then
  798. result:=getword
  799. else if CpuAluBitSize[tsystemcpu(header^.cpu)]=8 then
  800. result:=getbyte
  801. else
  802. begin
  803. error:=true;
  804. result:=0;
  805. end;
  806. {$else not generic_cpu}
  807. case sizeof(aword) of
  808. 8: result:=getqword;
  809. 4: result:=getdword;
  810. 2: result:=getword;
  811. 1: result:=getbyte;
  812. else
  813. begin
  814. RaiseAssertion(2019041804);
  815. result:=0;
  816. end;
  817. end;
  818. {$endif not generic_cpu}
  819. end;
  820. function tentryfile.getrealsize(sizeofreal : longint):entryreal;
  821. var
  822. e : entryreal;
  823. d : double;
  824. s : single;
  825. begin
  826. if sizeofreal=sizeof(e) then
  827. begin
  828. if entryidx+sizeof(e)>entry.size then
  829. begin
  830. error:=true;
  831. result:=0;
  832. exit;
  833. end;
  834. readdata(e,sizeof(e));
  835. if change_endian then
  836. result:=swapendian_entryreal(e)
  837. else
  838. result:=e;
  839. inc(entryidx,sizeof(e));
  840. exit;
  841. end;
  842. if sizeofreal=sizeof(d) then
  843. begin
  844. if entryidx+sizeof(d)>entry.size then
  845. begin
  846. error:=true;
  847. result:=0;
  848. exit;
  849. end;
  850. readdata(d,sizeof(d));
  851. if change_endian then
  852. result:=swapendian(pqword(@d)^)
  853. else
  854. result:=d;
  855. inc(entryidx,sizeof(d));
  856. result:=d;
  857. exit;
  858. end;
  859. if sizeofreal=sizeof(s) then
  860. begin
  861. if entryidx+sizeof(s)>entry.size then
  862. begin
  863. error:=true;
  864. result:=0;
  865. exit;
  866. end;
  867. readdata(s,sizeof(s));
  868. if change_endian then
  869. result:=swapendian(pdword(@s)^)
  870. else
  871. result:=s;
  872. inc(entryidx,sizeof(s));
  873. result:=s;
  874. exit;
  875. end;
  876. error:=true;
  877. result:=0.0;
  878. end;
  879. function tentryfile.getreal:entryreal;
  880. var
  881. d : entryreal;
  882. hd : double;
  883. begin
  884. if target_info.system=system_x86_64_win64 then
  885. begin
  886. hd:=getrealsize(sizeof(hd));
  887. getreal:=hd;
  888. end
  889. else
  890. begin
  891. d:=getrealsize(sizeof(d));
  892. getreal:=d;
  893. end;
  894. end;
  895. function tentryfile.getboolean:boolean;
  896. begin
  897. result:=boolean(getbyte);
  898. end;
  899. function tentryfile.getstring:string;
  900. begin
  901. result[0]:=chr(getbyte);
  902. if entryidx+length(result)>entry.size then
  903. begin
  904. error:=true;
  905. exit;
  906. end;
  907. ReadData(result[1],length(result));
  908. inc(entryidx,length(result));
  909. end;
  910. function tentryfile.getpshortstring:pshortstring;
  911. var
  912. len: char;
  913. begin
  914. result:=nil;
  915. len:=chr(getbyte);
  916. if entryidx+ord(len)>entry.size then
  917. begin
  918. error:=true;
  919. exit;
  920. end;
  921. getmem(result,ord(len)+1);
  922. result^[0]:=len;
  923. ReadData(result^[1],ord(len));
  924. inc(entryidx,ord(len));
  925. end;
  926. function tentryfile.getansistring:ansistring;
  927. var
  928. len: longint;
  929. begin
  930. len:=getlongint;
  931. if entryidx+len>entry.size then
  932. begin
  933. error:=true;
  934. result:='';
  935. exit;
  936. end;
  937. setlength(result,len);
  938. if len>0 then
  939. getdata(result[1],len);
  940. end;
  941. procedure tentryfile.getsmallset(out b);
  942. var
  943. i : longint;
  944. begin
  945. getdata(b,4);
  946. if change_endian then
  947. for i:=0 to 3 do
  948. Pbyte(@b)[i]:=reverse_byte(Pbyte(@b)[i]);
  949. end;
  950. procedure tentryfile.getnormalset(out b);
  951. var
  952. i : longint;
  953. begin
  954. getdata(b,32);
  955. if change_endian then
  956. for i:=0 to 31 do
  957. Pbyte(@b)[i]:=reverse_byte(Pbyte(@b)[i]);
  958. end;
  959. function tentryfile.skipuntilentry(untilb:byte):boolean;
  960. var
  961. b : byte;
  962. begin
  963. repeat
  964. b:=readentry;
  965. until (b in [ibend,iberror]) or ((b=untilb) and (entry.id=mainentryid));
  966. skipuntilentry:=(b=untilb);
  967. end;
  968. {*****************************************************************************
  969. tentryfile Writing
  970. *****************************************************************************}
  971. function tentryfile.createfile:boolean;
  972. var
  973. ok: boolean;
  974. strm : TCStream;
  975. begin
  976. createfile:=false;
  977. strm:=nil;
  978. if outputallowed then
  979. begin
  980. {$ifdef MACOS}
  981. {FPas is FreePascal's creator code on MacOS. See systems/mac_crea.txt}
  982. SetDefaultMacOSCreator('FPas');
  983. SetDefaultMacOSFiletype('FPPU');
  984. {$endif}
  985. ok:=false;
  986. try
  987. strm:=CFileStreamClass.Create(fname,fmCreate);
  988. ok:=true;
  989. except
  990. end;
  991. {$ifdef MACOS}
  992. SetDefaultMacOSCreator('MPS ');
  993. SetDefaultMacOSFiletype('TEXT');
  994. {$endif}
  995. if not ok then
  996. exit;
  997. end;
  998. createfile:=createstream(strm);
  999. fisfile:=result;
  1000. end;
  1001. function tentryfile.createstream(strm:TCStream):boolean;
  1002. begin
  1003. createstream:=false;
  1004. if outputallowed then
  1005. begin
  1006. f:=strm;
  1007. mode:=2;
  1008. {write header for sure}
  1009. f.Write(getheaderaddr^,getheadersize);
  1010. end;
  1011. bufsize:=entryfilebufsize;
  1012. bufstart:=getheadersize;
  1013. bufidx:=0;
  1014. {reset}
  1015. resetfile;
  1016. error:=false;
  1017. size:=0;
  1018. entrytyp:=mainentryid;
  1019. {start}
  1020. newentry;
  1021. createstream:=true;
  1022. end;
  1023. procedure tentryfile.writebuf;
  1024. begin
  1025. if outputallowed and
  1026. (bufidx <> 0) then
  1027. f.Write(buf^,bufidx);
  1028. inc(bufstart,bufidx);
  1029. bufidx:=0;
  1030. end;
  1031. procedure tentryfile.writedata(const b;len:integer);
  1032. var
  1033. p : pchar;
  1034. left,
  1035. idx : integer;
  1036. begin
  1037. if not outputallowed then
  1038. exit;
  1039. p:=pchar(@b);
  1040. idx:=0;
  1041. while len>0 do
  1042. begin
  1043. left:=bufsize-bufidx;
  1044. if len>left then
  1045. begin
  1046. move(p[idx],buf[bufidx],left);
  1047. dec(len,left);
  1048. inc(idx,left);
  1049. inc(bufidx,left);
  1050. writebuf;
  1051. end
  1052. else
  1053. begin
  1054. move(p[idx],buf[bufidx],len);
  1055. inc(bufidx,len);
  1056. exit;
  1057. end;
  1058. end;
  1059. end;
  1060. procedure tentryfile.newentry;
  1061. begin
  1062. with entry do
  1063. begin
  1064. id:=entrytyp;
  1065. nr:=ibend;
  1066. size:=0;
  1067. end;
  1068. {Reset Entry State}
  1069. entryidx:=0;
  1070. entrybufstart:=bufstart;
  1071. entrystart:=bufstart+bufidx;
  1072. {Alloc in buffer}
  1073. writedata(entry,sizeof(tentry));
  1074. end;
  1075. procedure tentryfile.writeentry(ibnr:byte);
  1076. var
  1077. opos : integer;
  1078. begin
  1079. {create entry}
  1080. entry.id:=entrytyp;
  1081. entry.nr:=ibnr;
  1082. entry.size:=entryidx;
  1083. {it's already been sent to disk ?}
  1084. if entrybufstart<>bufstart then
  1085. begin
  1086. if outputallowed then
  1087. begin
  1088. {flush to be sure}
  1089. WriteBuf;
  1090. {write entry}
  1091. opos:=f.Position;
  1092. f.Position:=entrystart;
  1093. f.write(entry,sizeof(tentry));
  1094. f.Position:=opos;
  1095. end;
  1096. entrybufstart:=bufstart;
  1097. end
  1098. else
  1099. move(entry,buf[entrystart-bufstart],sizeof(entry));
  1100. {Add New Entry, which is ibend by default}
  1101. entrystart:=bufstart+bufidx; {next entry position}
  1102. newentry;
  1103. end;
  1104. procedure tentryfile.putdata(const b;len:integer);
  1105. begin
  1106. if outputallowed then
  1107. writedata(b,len);
  1108. inc(entryidx,len);
  1109. end;
  1110. procedure tentryfile.putbyte(b:byte);
  1111. begin
  1112. putdata(b,1);
  1113. end;
  1114. procedure tentryfile.putword(w:word);
  1115. begin
  1116. putdata(w,2);
  1117. end;
  1118. procedure tentryfile.putdword(w:dword);
  1119. begin
  1120. putdata(w,4);
  1121. end;
  1122. procedure tentryfile.putlongint(l:longint);
  1123. begin
  1124. putdata(l,4);
  1125. end;
  1126. procedure tentryfile.putint64(i:int64);
  1127. begin
  1128. putdata(i,8);
  1129. end;
  1130. procedure tentryfile.putqword(q:qword);
  1131. begin
  1132. putdata(q,sizeof(qword));
  1133. end;
  1134. procedure tentryfile.putaint(i:aint);
  1135. begin
  1136. putdata(i,sizeof(aint));
  1137. end;
  1138. procedure tentryfile.putasizeint(i: asizeint);
  1139. begin
  1140. putdata(i,sizeof(asizeint));
  1141. end;
  1142. procedure tentryfile.putpuint(i : puint);
  1143. begin
  1144. putdata(i,sizeof(puint));
  1145. end;
  1146. procedure tentryfile.putptruint(v:TConstPtrUInt);
  1147. begin
  1148. {$if sizeof(TConstPtrUInt)=8}
  1149. putint64(int64(v));
  1150. {$else}
  1151. putlongint(longint(v));
  1152. {$endif}
  1153. end;
  1154. procedure tentryfile.putaword(i:aword);
  1155. begin
  1156. putdata(i,sizeof(aword));
  1157. end;
  1158. procedure tentryfile.putreal(d:entryreal);
  1159. var
  1160. hd : double;
  1161. begin
  1162. if target_info.system=system_x86_64_win64 then
  1163. begin
  1164. hd:=d;
  1165. putdata(hd,sizeof(hd));
  1166. end
  1167. else
  1168. putdata(d,sizeof(entryreal));
  1169. end;
  1170. procedure tentryfile.putboolean(b:boolean);
  1171. begin
  1172. putbyte(byte(b));
  1173. end;
  1174. procedure tentryfile.putstring(const s:string);
  1175. begin
  1176. putdata(s,length(s)+1);
  1177. end;
  1178. procedure tentryfile.putansistring(const s:ansistring);
  1179. var
  1180. len: longint;
  1181. begin
  1182. len:=length(s);
  1183. putlongint(len);
  1184. if len>0 then
  1185. putdata(s[1],len);
  1186. end;
  1187. procedure tentryfile.putsmallset(const b);
  1188. var
  1189. l : longint;
  1190. begin
  1191. l:=longint(b);
  1192. putlongint(l);
  1193. end;
  1194. procedure tentryfile.putnormalset(const b);
  1195. begin
  1196. putdata(b,32);
  1197. end;
  1198. procedure tentryfile.tempclose;
  1199. begin
  1200. if not closed then
  1201. begin
  1202. closepos:=f.Position;
  1203. f.Free;
  1204. f:=nil;
  1205. closed:=true;
  1206. tempclosed:=true;
  1207. end;
  1208. end;
  1209. function tentryfile.tempopen:boolean;
  1210. begin
  1211. tempopen:=false;
  1212. if not closed or not tempclosed then
  1213. exit;
  1214. { MG: not sure, if this is correct
  1215. f.position:=0;
  1216. No, f was freed in tempclose above, we need to
  1217. recreate it. PM 2011/06/06 }
  1218. try
  1219. f:=CFileStreamClass.Create(fname,fmOpenRead);
  1220. except
  1221. exit;
  1222. end;
  1223. closed:=false;
  1224. tempclosed:=false;
  1225. { restore state }
  1226. f.Position:=closepos;
  1227. tempopen:=true;
  1228. end;
  1229. end.