entfile.pas 25 KB

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